Usage
Installation, quick start, and usage examples for @tetherto/wdk-wallet-ton-gasless
Installation
To install the @tetherto/wdk-wallet-ton-gasless package, follow these instructions:
npm install @tetherto/wdk-wallet-to-gaslessQuick Start
Importing from @tetherto/wdk-wallet-ton-gasless
@tetherto/wdk-wallet-ton-gaslessWalletManagerTonGasless: Main class for managing wallets with gasless features
WalletAccountTonGasless: Use this for full access accounts with gasless transactions
WalletAccountReadOnlyTonGasless: Use this for read-only accounts
Creating a New Gasless Wallet
import WalletManagerTonGasless, {
WalletAccountTonGasless,
WalletAccountReadOnlyTonGasless
} from '@tetherto/wdk-wallet-ton-gasless'
// Use a BIP-39 seed phrase (replace with your own secure phrase)
const seedPhrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
// Create gasless wallet manager with TON RPC and TON API endpoints, and paymaster token config
const wallet = new WalletManagerTonGasless(seedPhrase, {
tonClient: {
url: 'https://toncenter.com/api/v3',
secretKey: 'your-api-key' // Optional
},
tonApiClient: {
url: 'https://tonapi.io/v3',
secretKey: 'your-ton-api-key' // Optional
},
paymasterToken: {
address: 'EQ...' // Paymaster token contract address
}, // Paymaster Jetton master contract address
transferMaxFee: 10000000 // Maximum fee for transfer operations (in paymaster Jetton base units)
})
// Get a full access account
const account = await wallet.getAccount(0)
// Convert to a read-only account
const readOnlyAccount = await account.toReadOnlyAccount()Managing Multiple Accounts
import WalletManagerTonGasless from '@tetherto/wdk-wallet-ton-gasless'
// Assume wallet is already created
// Get the first account (index 0)
const account = await wallet.getAccount(0)
const address = await account.getAddress()
console.log('Account 0 address:', address)
// Get the second account (index 1)
const account1 = await wallet.getAccount(1)
const address1 = await account1.getAddress()
console.log('Account 1 address:', address1)
// Get account by custom derivation path
const customAccount = await wallet.getAccountByPath("0'/0/5")
const customAddress = await customAccount.getAddress()
console.log('Custom account address:', customAddress)Checking Balances
Owned Account
For accounts where you have the seed phrase and full access:
import WalletManagerTonGasless from '@tetherto/wdk-wallet-ton-gasless'
// Assume wallet and account are already created
// Get native TON balance (in nanotons)
const balance = await account.getBalance()
console.log('Native TON balance:', balance, 'nanotons')
// Get Jetton token balance
const jettonAddress = 'EQ...'; // Jetton contract address
const jettonBalance = await account.getTokenBalance(jettonAddress);
console.log('Jetton token balance:', jettonBalance);
// Get paymaster Jetton balance
const paymasterBalance = await account.getPaymasterTokenBalance()
console.log('Paymaster Jetton balance:', paymasterBalance)Read-Only Account
For addresses where you don't have the seed phrase:
import { WalletAccountReadOnlyTonGasless } from '@tetherto/wdk-wallet-ton-gasless'
// Use the public key directly
const publicKey = '...'; // Replace with the actual public key
// Create a read-only account
const readOnlyAccount = new WalletAccountReadOnlyTonGasless(publicKey, {
tonClient: {
url: 'https://toncenter.com/api/v3',
secretKey: 'your-api-key' // Optional
},tonApiClient: {
url: 'https://tonapi.io/v2',
secretKey: 'your-ton-api-key' // Optional
},
paymasterToken: {
address: 'EQ...' // Paymaster Jetton contract address
}
})
// Check balances
const balance = await readOnlyAccount.getBalance()
console.log('Native TON balance:', balance)
// Check paymaster token balance
const paymasterBalance = await readOnlyAccount.getPaymasterTokenBalance()
console.log('Paymaster token balance:', paymasterBalance)
// Check any other token balance
const tokenBalance = await readOnlyAccount.getTokenBalance('EQC...')
console.log('Token balance:', tokenBalance)Sending Transactions
⚠️ Direct transaction sending using sendTransaction() is not supported in WalletAccountTonGasless. This is a gasfree implementation that handles transactions through a gasfree provider instead of direct blockchain transactions.
For sending tokens, please use the transfer() method instead.
Jetton Token Transfers (Gasless)
Transfer Jetton tokens and estimate fees using WalletAccountTonGasless. Requires TON Center client configuration.
// Gasless transfer of Jettons (fee paid in paymaster Jetton)
const result = await account.transfer({
token: 'EQ...', // Jetton master contract address
recipient: 'EQ...', // Recipient's TON address
amount: 1000000000 // Amount in Jetton's base units
}, {
paymasterToken: { // Optional: override default paymaster token
address: 'EQ...'
},
transferMaxFee: 1000000 transferMaxFee: 1000000 // Optional: maximum allowed fee
})
console.log('Transfer hash:', transferResult.hash);
console.log('Transfer fee:', transferResult.fee, 'nanotons');
// Quote gasless transfer fee
const quote = await account.quoteTransfer({
token: 'EQ...', // Jetton contract address
recipient: 'EQ...', // Recipient's TON address
amount: 1000000 // Amount in Jetton's base units
})
console.log('Transfer fee estimate:', transferQuote.fee, 'nanotons')Message Signing and Verification
Sign and verify messages using WalletAccountTonGasless.
// Sign a message
const message = 'Hello, TON!'
const signature = await account.sign(message)
console.log('Signature:', signature)
// Verify a signature
const isValid = await account.verify(message, signature)
console.log('Signature valid:', isValid)Fee Management
Retrieve current fee rates using WalletManagerTonGasless.
// Get current fee rates
const feeRates = await wallet.getFeeRates();
console.log('Normal fee rate:', feeRates.normal, 'nanotons');
console.log('Fast fee rate:', feeRates.fast, 'nanotons');Memory Management
Clear sensitive data from memory using dispose methods in WalletAccountTonGasless and WalletManagerTonGasless.
// Dispose wallet accounts to clear private keys from memory
account.dispose()
// Dispose entire wallet manager
wallet.dispose()Complete Examples
Complete Wallet Setup
import WalletManagerTonGasless from '@tetherto/wdk-wallet-ton-gasless'
async function setupWallet() {
try {
// Use a BIP-39 seed phrase (replace with your own secure phrase)
const seedPhrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
// Create gasless wallet manager
const wallet = new WalletManagerTonGasless(seedPhrase, {
tonClient: {
url: 'https://toncenter.com/api/v3',
secretKey: 'your-api-key' // Optional
},
tonApiClient: {
url: 'https://tonapi.io/v2',
secretKey: 'your-tonapi-key' // Optional but recommended
},
paymasterToken: {
address: 'EQ...' // REQUIRED: Paymaster token address
},
transferMaxFee: 1000000000 // Optional: Maximum fee in nanotons
})
// Get first account
const account = await wallet.getAccount(0)
const address = await account.getAddress()
console.log('Wallet address:', address)
// Check balances
const balance = await account.getBalance()
const paymasterBalance = await account.getPaymasterTokenBalance()
console.log('TON balance:', balance, 'nanotons')
console.log('Paymaster token balance:', paymasterBalance)
return { wallet, account, address, balance }
} catch (error) {
console.error('Failed to setup wallet:', error)
throw error
}
}Multi-Account Management
async function manageMultipleAccounts(wallet) {
try {
const accounts = []
// Create 5 accounts
for (let i = 0; i < 5; i++) {
const account = await wallet.getAccount(i)
const address = await account.getAddress()
const balance = await account.getBalance()
const paymasterBalance = await account.getPaymasterTokenBalance()
accounts.push({
index: i,
address,
balance,
paymasterBalance
})
}
return accounts
} catch (error) {
console.error('Failed to manage accounts:', error)
throw error
} finally {
// Clean up when done to remove sensitive data from memory
wallet.dispose()
}
}Advanced Transaction Example
async function sendAdvancedGaslessTransfer(account) {
try {
// Check paymaster token balance first
const paymasterBalance = await account.getPaymasterTokenBalance()
console.log('Paymaster token balance:', paymasterBalance)
// Get transfer quote first
const quote = await account.quoteTransfer({
token: 'EQ...', // Jetton master contract address
recipient: 'EQ...', // Recipient's TON address
amount: 1000000000 // Amount in Jetton's base units
})
console.log('Estimated fee (paymaster token):', quote.fee)
// Execute gasless transfer
const result = await account.transfer({
token: 'EQ...',
recipient: 'EQ...',
amount: 1000000000
}, {
paymasterToken: { // Optional: override default paymaster
address: 'EQ...'
},
transferMaxFee: 2000000000 // Optional: override max fee
})
console.log('Transfer hash:', result.hash)
console.log('Actual fee (paymaster token):', result.fee)
return result
}catch (error) {
console.error('Transfer failed:', error)
throw error
}
}Token Transfer with Validation
async function transferJettonWithValidation(account, jettonAddress, recipient, amount) {
try {
// Validate Jetton address (TON format)
if (!jettonAddress.startsWith('EQ')) {
throw new Error('Invalid Jetton address format')
}
// Validate recipient address (TON format)
if (!recipient.startsWith('EQ')) {
throw new Error('Invalid recipient address format')
}
// Check Jetton balance
const balance = await account.getTokenBalance(jettonAddress)
if (balance < amount) {
throw new Error('Insufficient Jetton balance')
}
// Check paymaster token balance
const paymasterBalance = await account.getPaymasterTokenBalance()
console.log('Paymaster token balance:', paymasterBalance)
// Get transfer quote (fee is in paymaster token units)
const quote = await account.quoteTransfer({
token: jettonAddress,
recipient,
amount
})
console.log('Transfer fee estimate (paymaster token):', quote.fee)
// Execute transfer if fee is acceptable
const result = await account.transfer({
token: jettonAddress,
recipient,
amount
})
console.log('Transfer hash:', result.hash)
console.log('Actual fee (paymaster token):', result.fee)
return result
} catch (error) {
console.error('Transfer failed:', error)
throw error
}
}Error Handling and Memory Management
async function safeTransferExample(account, wallet) {
try {
// Check balances first
const jettonBalance = await account.getTokenBalance('EQ...')
const paymasterBalance = await account.getPaymasterTokenBalance()
const transferAmount = 1000000000
if (jettonBalance < transferAmount) {
throw new Error('insufficient jetton balance')
}
if (paymasterBalance < 1000000) { // Minimum paymaster balance check
throw new Error('insufficient paymaster balance')
}
// Get fee estimate
const quote = await account.quoteTransfer({
token: 'EQ...',
recipient: 'EQ...',
amount: transferAmount
})
console.log('Estimated fee (paymaster token):', quote.fee)
// Execute transfer
const result = await account.transfer({
token: 'EQ...',
recipient: 'EQ...',
amount: transferAmount
})
console.log('Transfer successful:', result.hash)
return result
} catch (error) {
if (error.message.includes('insufficient jetton balance')) {
console.error('Please add more Jetton tokens to your wallet')
} else if (error.message.includes('insufficient paymaster balance')) {
console.error('Please add more paymaster tokens for gas fees')
} else if (error.message.includes('invalid address')) {
console.error('The recipient address is invalid')
} else if (error.message.includes('max fee')) {
console.error('The transfer fee exceeds your configured maximum')
} else {
console.error('Transfer failed:', error.message)
}
throw error
} finally {
// Always clean up sensitive data
account.dispose()
wallet.dispose()
}
}
