Skip to content

Commit

Permalink
👷 add claim v2 which lets frontend wallet make the transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
chriamue committed Jun 22, 2024
1 parent 0ec56c9 commit 3d38886
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 68 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ wasm-bindgen = "0.2.92"
wasm-bindgen-futures = "0.4.42"
console_log = "1.0.0"
gloo-timers = "0.3.0"
gloo-utils = "0.2.0"
web-sys = { version="0.3.69", features = ["HtmlAudioElement"] }
serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.117"
89 changes: 79 additions & 10 deletions src/claim.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::{js_sys::Promise, JsFuture};
use yew::prelude::*;
use serde::Deserialize;
use gloo_utils::format::JsValueSerdeExt;

#[wasm_bindgen(module = "/src/js/confetti.js")]
extern "C" {
Expand All @@ -12,6 +14,16 @@ extern "C" {
fn claim(address: &str, amount: u32) -> Promise;
}

#[wasm_bindgen(module = "/src/js/claim.js")]
extern "C" {
fn claim_v2(address: &str, amount: u32) -> Promise;
}

#[wasm_bindgen(module = "/src/js/wallet.js")]
extern "C" {
fn sendRawTransaction(raw_tx: &str, destination: &str) -> Promise;
}

#[derive(Properties, PartialEq)]
pub struct ClaimCompProps {
pub address: String,
Expand All @@ -25,13 +37,27 @@ enum ClaimState {
Error(String),
}

#[allow(dead_code)]
enum ClaimVersion {
V1,
V2,
}

#[derive(Deserialize)]
struct RawTransaction {
success: bool,
raw_transaction: String,
destination: String,
}

#[function_component(ClaimComp)]
pub fn claim_comp(props: &ClaimCompProps) -> Html {
let address = props.address.clone();
let amount = props.amount;
let claim_state = use_state(|| ClaimState::Initial);
const CLAIM_VERSION: ClaimVersion = ClaimVersion::V1;

let on_claim = {
let on_claim: Callback<MouseEvent> = {
let address = address.clone();
let claim_state = claim_state.clone();

Expand All @@ -48,16 +74,59 @@ pub fn claim_comp(props: &ClaimCompProps) -> Html {
let claim_state = claim_state.clone();

wasm_bindgen_futures::spawn_local(async move {
match JsFuture::from(claim(&address, amount)).await {
Ok(result) => {
let explorer_url = result.as_string().unwrap_or_default();
log::info!("Claim successful: {}", explorer_url);
claim_state.set(ClaimState::Done(explorer_url));

match CLAIM_VERSION {
ClaimVersion::V1 => {
match JsFuture::from(claim(&address, amount)).await {
Ok(result) => {
log::info!("Claim successful: {:?}", result);
let explorer_url = result.as_string().unwrap_or_default();
log::info!("Claim successful: {}", explorer_url);
claim_state.set(ClaimState::Done(explorer_url));
}
Err(e) => {
let error_message = format!("{:?}", e);
log::error!("Claim failed: {}", error_message);
claim_state.set(ClaimState::Error(error_message));
}
}
}
Err(e) => {
let error_message = format!("{:?}", e);
log::error!("Claim failed: {}", error_message);
claim_state.set(ClaimState::Error(error_message));
ClaimVersion::V2 => {
match JsFuture::from(claim_v2(&address, amount)).await {
Ok(result) => {
match result.into_serde::<RawTransaction>() {
Ok(raw_tx) => {
if raw_tx.success {
match JsFuture::from(sendRawTransaction(&raw_tx.raw_transaction, &raw_tx.destination)).await {
Ok(_) => {
log::info!("Transaction sent successfully");
claim_state.set(ClaimState::Done("Transaction sent successfully".to_string()));
}
Err(e) => {
let error_message = format!("{:?}", e);
log::error!("Transaction failed: {}", error_message);
claim_state.set(ClaimState::Error(error_message));
}
}
} else {
let error_message = "Failed to get raw transaction".to_string();
log::error!("{}", error_message);
claim_state.set(ClaimState::Error(error_message));
}
}
Err(e) => {
let error_message = format!("{:?}", e);
log::error!("Claim failed: {}", error_message);
claim_state.set(ClaimState::Error(error_message));
}
}
}
Err(e) => {
let error_message = format!("{:?}", e);
log::error!("Claim failed: {}", error_message);
claim_state.set(ClaimState::Error(error_message));
}
}
}
}
});
Expand Down
170 changes: 114 additions & 56 deletions src/js/claim.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,119 @@
export async function claim(address, amount) {
if (!Telegram.WebApp.initDataUnsafe.user) {
console.error("User is not available");
return;
}

const data = {
id: Telegram.WebApp.initDataUnsafe.user.id,
user: Telegram.WebApp.initDataUnsafe.user.username,
type: "claim",
address,
amount,
};

console.log("Claiming data", data);

try {
const response = await fetch(
"https://tg-api.konnektoren.help/api/v1/claim",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
},
);

if (!response.ok) {
throw new Error("Network response was not ok");
if (!Telegram.WebApp.initDataUnsafe.user) {
console.error("User is not available");
return;
}

const result = await response.json();

if (result.success) {
Telegram.WebApp.showPopup(
{
title: "Claimed successfully",
message: "Success! View transaction",
buttons: [
{ id: "link", type: "default", text: "Open Explorer" },
{ type: "cancel" },
],
},
function (btn) {
if (btn === "link") {
Telegram.WebApp.openLink(result.explorer_url);
}
},
);
return Promise.resolve(result.explorer_url);
} else {
alert("Claim failed.");
return Promise.reject(result);
const data = {
id: Telegram.WebApp.initDataUnsafe.user.id,
user: Telegram.WebApp.initDataUnsafe.user.username,
type: "claim",
address,
amount,
};

console.log("Claiming data", data);

try {
const response = await fetch(
"https://tg-api.konnektoren.help/api/v1/claim",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
},
);

if (!response.ok) {
throw new Error("Network response was not ok");
}

const result = await response.json();

if (result.success) {
Telegram.WebApp.showPopup(
{
title: "Claimed successfully",
message: "Success! View transaction",
buttons: [
{id: "link", type: "default", text: "Open Explorer"},
{type: "cancel"},
],
},
function (btn) {
if (btn === "link") {
Telegram.WebApp.openLink(result.explorer_url);
}
},
);
return Promise.resolve(result.explorer_url);
} else {
alert("Claim failed.");
return Promise.reject(result);
}
} catch (error) {
console.error("Error:", error);
alert("Error occurred while claiming.");
return Promise.reject(error);
}
}

export async function claim_v2(address, amount) {
/*
if (!Telegram.WebApp.initDataUnsafe.user) {
console.error("User is not available");
return Promise.reject(new Error("User is not available"));
}
const data = {
id: Telegram.WebApp.initDataUnsafe.user.id,
user: Telegram.WebApp.initDataUnsafe.user.username,
type: "claim",
address,
amount,
};
*/

const data = {
id: 1,
user: "user",
type: "claim",
address,
amount
};

console.log("Claiming data", data);

try {
const response = await fetch(
//"https://tg-api.konnektoren.help/api/v2/claim",
"http://localhost:3000/api/v2/claim",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
},
);

if (!response.ok) {
throw new Error("Network response was not ok");
}

const result = await response.json();

if (result.success) {
return result;
} else {
alert("Claim failed.");
return Promise.reject(result);
}
} catch (error) {
console.error("Error:", error);
alert("Error occurred while claiming.");
return Promise.reject(error);
}
} catch (error) {
console.error("Error:", error);
alert("Error occurred while claiming.");
return Promise.reject(error);
}
}
21 changes: 19 additions & 2 deletions src/js/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,27 @@ export async function connectWallet(onConnectCallback) {
}

export async function getJettonBalance(address) {
const jettonAddress = KONNEKTOREN_COIN;
const response = await fetch(
`${TON_API_URL}/accounts/${address}/jettons/${jettonAddress}`,
`${TON_API_URL}/accounts/${address}/jettons/${KONNEKTOREN_COIN}`,
);
const data = await response.json();
return data.balance;
}

export async function sendRawTransaction(rawTxBase64, destinationAddress) {
try {
const response = await tonConnectUI.sendTransaction({
validUntil: Math.floor(new Date() / 1000) + 360,
messages: [
{
address: destinationAddress,
payload: rawTxBase64,
amount: "100000000"
},
],
});
} catch (error) {
console.error("Error sending transaction:", error);
throw error;
}
}

0 comments on commit 3d38886

Please sign in to comment.