Sending transaction
Building transaction using TON blockchain to send inscriptions using GRAM-20 protocol.
import { Address, beginCell, internal, loadStateInit, toNano } from "@ton/core";
import { WalletContractV3R2, TonClient, WalletContractV4 } from "@ton/ton";
import { mnemonicToWalletKey } from "@ton/crypto";
import { configDotenv } from "dotenv";
type TransferParams = {
recipient: Address;
value: string;
memo?: string;
}
async function getTransferInscriptionMsg(client: TonClient, rootAddress: Address, userAddress: Address, params: TransferParams) {
let tick = '';
let protocolFee = 0n;
while(true) {
try {
const rootData = await client.runMethod(rootAddress, 'get_root_data', []);
const tokenData = await client.runMethod(rootAddress, 'get_token_data', []);
rootData.stack.skip(2);
tick = rootData.stack.readString();
tokenData.stack.skip(5);
protocolFee = tokenData.stack.readBigNumber();
break;
} catch {
await sleep(300);
}
}
let userData;
while(true) {
try {
userData = await client.runMethod(rootAddress, 'get_user_data', [
{ type: 'slice', cell: beginCell().storeAddress(userAddress).endCell() },
]);
break;
} catch {
await sleep(300);
continue;
}
}
const userStateInit = loadStateInit(userData.stack.readCell().beginParse());
const userContractAddress = userData.stack.readAddress();
let userSCState;
while(true) {
try {
userSCState = await client.getContractState(userContractAddress);
break;
} catch {
await sleep(300);
continue;
}
}
const userSCActive = userSCState.state === 'active';
let transferPayload = '';
if (params.memo) {
transferPayload = `data:application/json,{"p":"gram-20","op":"transfer","tick":"${tick}","amt":"${params.value}","to":"${params.recipient.toString({bounceable: true})}","memo":"${params.memo}"}`;
} else {
transferPayload = `data:application/json,{"p":"gram-20","op":"transfer","tick":"${tick}","amt":"${params.value}","to":"${params.recipient.toString({bounceable: true})}"}`;
}
if (!userSCActive) {
return internal({
to: userContractAddress,
value: toNano(0.007),
init: userStateInit,
body: beginCell().storeUint(0, 32).storeStringTail(transferPayload).endCell(),
})
} else {
return internal({
to: userContractAddress,
value: toNano(0.006),
body: beginCell().storeUint(0, 32).storeStringTail(transferPayload).endCell(),
})
}
}
async function main() {
configDotenv();
const transferParams: TransferParams = {
recipient: Address.parse(''),
value: '1',
// memo: 'test'
}
const rootTokenAddress = Address.parse('');
const client = new TonClient({
endpoint: 'https://toncenter-v4.gram20.com/jsonRPC'
});
if (process.env.WALLET_VERSION !== 'V3R2' && process.env.WALLET_VERSION !== 'V4R2') {
throw new Error('Invalid wallet type');
}
if (!process.env.WALLET_MNEMONIC) {
throw new Error('Mnemonic not found');
}
const keys = await mnemonicToWalletKey(process.env.WALLET_MNEMONIC.split(' '));
let wallet: WalletContractV3R2 | WalletContractV4;
if (process.env.WALLET_VERSION === 'V3R2') {
wallet = WalletContractV3R2.create({
workchain: 0,
publicKey: keys.publicKey,
});
} else {
wallet = WalletContractV4.create({
workchain: 0,
publicKey: keys.publicKey,
});
}
console.log(`Wallet address: ${wallet.address.toString()}`)
const contract = client.open(wallet);
const transferMsg = await getTransferInscriptionMsg(client, rootTokenAddress, wallet.address, transferParams);
// console.log(`--- Transfer message ---`);
// console.log(transferMsg);
await contract.sendTransfer({
seqno: await contract.getSeqno(),
secretKey: keys.secretKey,
messages: [transferMsg],
});
}
main()
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Last updated