UNPKG

@codegame.dev/wallet-cli

Version:

A CLI tool for managing wallets across multiple blockchains, supporting operations like wallet creation, balance checking, transfers, and fee estimation.

311 lines (310 loc) 12.9 kB
import { sleep } from "../utils/index.js"; import TonWeb from "tonweb"; export const getBalance = async (params) => { const provider = new TonWeb.HttpProvider(params.jsonRpcProvider); const tonWeb = new TonWeb(provider); const address = new TonWeb.Address(params.address); if (params.tokenAddress) { const tokenAddress = new TonWeb.Address(params.tokenAddress); // @ts-ignore const tokenMinter = new TonWeb.token.jetton.JettonMinter(provider, { address: tokenAddress.toString(true, true, false, params.testnet), }); const jettonWalletAddress = await tokenMinter.getJettonWalletAddress(address); await sleep(params.delay); const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonWeb.provider, { address: jettonWalletAddress, }); const jettonData = await jettonWallet.getData(); if (jettonData.jettonMinterAddress.toString(false) !== tokenMinter.address?.toString(false)) { return { success: false, code: 'jetton-minter-address-mismatch', message: 'Jetton minter address from jetton wallet does not match the expected minter address', }; } const tokenBalance = TonWeb.utils.fromNano(jettonData.balance); return { success: true, token_balance: tokenBalance, }; } else { const coinBalance = TonWeb.utils.fromNano(await tonWeb.getBalance(address)); return { success: true, coin_balance: coinBalance, }; } }; export const transfer = async (params) => { const fromAddress = new TonWeb.Address(params.fromAddress); const toAddress = new TonWeb.Address(params.toAddress); const nacl = TonWeb.utils.nacl; const keyPair = nacl.sign.keyPair.fromSeed(params.secretKey); if (params.tokenAddress) { const tokenAddress = new TonWeb.Address(params.tokenAddress); const provider = new TonWeb.HttpProvider(params.jsonRpcProvider); const tonWeb = new TonWeb(provider); const wallet = new tonWeb.wallet.all.v4R2(provider, { publicKey: keyPair.publicKey }); // @ts-ignore const jettonMinter = new TonWeb.token.jetton.JettonMinter(provider, { address: tokenAddress.toString(true, true, false, params.testnet) }); const jettonWalletAddress = await jettonMinter.getJettonWalletAddress(fromAddress); await sleep(params.delay); const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonWeb.provider, { address: jettonWalletAddress, }); const jettonData = await jettonWallet.getData(); await sleep(params.delay); if (jettonData.jettonMinterAddress.toString(false) !== jettonMinter.address?.toString(false)) { return { success: false, code: 'jetton-minter-address-mismatch', message: 'Jetton minter address from jetton wallet does not match the expected minter address', }; } const seqno = await wallet.methods.seqno().call() || 0; await sleep(params.delay); const tx = wallet.methods.transfer({ secretKey: keyPair.secretKey, toAddress: jettonWalletAddress.toString(true, true, false, params.testnet), amount: TonWeb.utils.toNano("0.05"), seqno, payload: await jettonWallet.createTransferBody({ // @ts-ignore jettonAmount: TonWeb.utils.toNano(Number(params.amount).toString()), toAddress: toAddress, responseAddress: fromAddress, }), sendMode: 3, }); const query = await tx.getQuery(); const boc = await query.toBoc(false); const bocBase64 = tonWeb.utils.bytesToBase64(boc); const payloadHash = tonWeb.utils.bytesToBase64(await query.hash()); const r = await tonWeb.provider.sendBoc(bocBase64); await sleep(params.delay); if (r['@type'] == 'ok') { try { let lastTx; let i = 100; do { const newSeqno = await wallet.methods.seqno().call() || 0; await sleep(params.delay); if (newSeqno <= seqno) { i--; if (i < 0) break; continue; } const index = newSeqno - seqno - 1; const _lastTx = (await tonWeb.getTransactions(fromAddress.toString(true, true, false, params.testnet), 1, undefined, payloadHash))[index]; if (!_lastTx) break; if (_lastTx.transaction_id?.hash && !_lastTx.out_msgs?.length) { return { success: false, hash: _lastTx.transaction_id.hash, fee: _lastTx.fee, }; } lastTx = { utime: _lastTx.utime, lt: _lastTx.transaction_id.lt, source: _lastTx.out_msgs[0].source, destination: _lastTx.out_msgs[0].destination, value: _lastTx.out_msgs[0].value, fee: _lastTx.fee, hash: _lastTx.transaction_id.hash }; break; } while (true); return { success: true, hash: lastTx?.hash, fee: TonWeb.utils.fromNano(lastTx?.fee || '0') }; } catch (e) { return { success: true, hash: "", fee: "0" }; } } else { return { success: false, hash: "", fee: "0" }; } } else { const provider = new TonWeb.HttpProvider(params.jsonRpcProvider); const tonWeb = new TonWeb(provider); const wallet = new tonWeb.wallet.all.v4R2(provider, { publicKey: keyPair.publicKey }); const seqno = await wallet.methods.seqno().call() || 0; await sleep(params.delay); const tx = wallet.methods.transfer({ secretKey: keyPair.secretKey, toAddress: toAddress.toString(true, true, false, params.testnet), amount: TonWeb.utils.toNano(Number(params.amount).toString()), seqno, sendMode: 3, }); const query = await tx.getQuery(); const boc = await query.toBoc(false); const bocBase64 = tonWeb.utils.bytesToBase64(boc); const payloadHash = tonWeb.utils.bytesToBase64(await query.hash()); const r = await tonWeb.provider.sendBoc(bocBase64); await sleep(params.delay); if (r['@type'] == 'ok') { try { let lastTx; let i = 100; do { const newSeqno = await wallet.methods.seqno().call() || 0; await sleep(params.delay); if (newSeqno <= seqno) { i--; if (i < 0) break; continue; } const index = newSeqno - seqno - 1; const _lastTx = (await tonWeb.getTransactions(fromAddress.toString(true, true, false, params.testnet), 1, undefined, payloadHash))[index]; if (!_lastTx) break; if (_lastTx.transaction_id?.hash && !_lastTx.out_msgs?.length) { return { success: false, hash: _lastTx.transaction_id.hash, fee: _lastTx.fee, }; } lastTx = { utime: _lastTx.utime, lt: _lastTx.transaction_id.lt, source: _lastTx.out_msgs[0].source, destination: _lastTx.out_msgs[0].destination, value: _lastTx.out_msgs[0].value, fee: _lastTx.fee, hash: _lastTx.transaction_id.hash }; break; } while (true); return { success: true, hash: lastTx?.hash, fee: TonWeb.utils.fromNano(lastTx?.fee || '0') }; } catch (e) { return { success: true, hash: "", fee: "0" }; } } else { return { success: false, hash: "", fee: "0" }; } } }; export const estimateFee = async (params) => { const nacl = TonWeb.utils.nacl; const keyPair = nacl.sign.keyPair.fromSeed(params.secretKey); const fromAddress = new TonWeb.Address(params.fromAddress); const toAddress = new TonWeb.Address(params.toAddress); if (params.tokenAddress) { return { success: true, fee: "0.05" }; } else { return { success: true, fee: "0.01" }; } // if (params.tokenAddress) { // const tokenAddress = new TonWeb.Address(params.tokenAddress) // const provider = new TonWeb.HttpProvider(params.jsonRpcProvider) // const tonWeb = new TonWeb(provider) // const wallet = new tonWeb.wallet.all.v4R2(provider, { publicKey: keyPair.publicKey }) // // @ts-ignore // const jettonMinter = new TonWeb.token.jetton.JettonMinter(provider, { // address: tokenAddress.toString(true, true, false, params.testnet), // }) // const jettonWalletAddress = await jettonMinter.getJettonWalletAddress(fromAddress) // await sleep(params.delay) // const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonWeb.provider, { // address: jettonWalletAddress, // }); // const seqno = await wallet.methods.seqno().call() || 0 // await sleep(params.delay) // const r = await wallet.methods.transfer({ // secretKey: keyPair.secretKey, // toAddress: jettonWalletAddress.toString(true, true, false, params.testnet), // amount: TonWeb.utils.toNano("0.05"), // seqno, // payload: await jettonWallet.createTransferBody({ // // @ts-ignore // jettonAmount: TonWeb.utils.toNano(Number(params.amount).toString()), // toAddress: toAddress, // responseAddress: fromAddress // }), // sendMode: 3, // }).estimateFee() // console.log(r) // const gasCost = TonWeb.utils.fromNano( // ([ // r?.source_fees?.in_fwd_fee || 0, // r?.source_fees?.storage_fee || 0, // r?.source_fees?.gas_fee || 0, // r?.source_fees?.fwd_fee || 0 // ].reduce((a, b) => a + b, 0)).toString() // ) // return { // success: true, // fee: gasCost // } // } else { // const provider = new TonWeb.HttpProvider(params.jsonRpcProvider) // const tonWeb = new TonWeb(provider) // const wallet = new tonWeb.wallet.all.v4R2(provider, { publicKey: keyPair.publicKey }) // const seqno = await wallet.methods.seqno().call() || 0 // await sleep(params.delay) // const r = await wallet.methods.transfer({ // secretKey: keyPair.secretKey, // toAddress: toAddress.toString(true, true, false, params.testnet), // amount: TonWeb.utils.toNano(Number(params.amount).toString()), // seqno, // sendMode: 3, // }).estimateFee() // console.log(r) // const gasCost = TonWeb.utils.fromNano( // ([ // r?.source_fees?.in_fwd_fee || 0, // r?.source_fees?.storage_fee || 0, // r?.source_fees?.gas_fee || 0, // r?.source_fees?.fwd_fee || 0 // ].reduce((a, b) => a + b, 0)).toString() // ) // return { // success: true, // fee: gasCost // } // } }; export default { getBalance, transfer, estimateFee };