/initWithdraw
-
GET | POST /initWithdraw
{ to, ownerAddress, amount, token }→{ to, data, gas, gasPrice, nonce }POST Data:
{
"to" : "0x5432....5432",
"tokenAddress" : "0x0000000000000000000000000000000000000000"
"amount" : "134.00",
"ownerAddress": "0x23341....2343432",
"chainId" : 1,
"contractType" : "payment"
}Where:
- to - recipient address
- tokenAddress - address of the token
- amount - human readable amount
- contractType - check contract types page for more information
Response:
{
"nonce" : 1,
"gas" : "0x123",
"gasPrice" : "0x123323",
"data" : "0x2df....Adsd",
"to" : "0x123...123"
}Please note that you have the ability to verify the accuracy of a transaction and confirm that it has been properly constructed. However, trust is still necessary before doing so.
Please sign the transaction like you did it before and prepare rawTx
Depending on the target VM (TVM vs EVM), use the recommended SDK to sign and broadcast the transaction.
TVM (TRON)
Use TronWeb to sign and broadcast the transaction returned by your backend.
import TronWeb from 'tronweb'
import fetch from 'node-fetch'
/**
* Initialize transfer on TRON, sign and broadcast the transaction
*
* @param {string} ownerAddress - The TRON address initiating the transfer (e.g. "TXYZ...").
* @param {string} privateKey - The private key of the owner (hex string, no 0x prefix).
* @param {string} token - Token address or "TRX" for native token.
* @param {string} chainId - TRON network key (e.g. "mainnet" or "shasta").
*/
async function withdrawTVM(ownerAddress, privateKey, token, chainId) {
const basePath = 'https://api.feemaker.io' // your backend endpoint
const rpcMap = {
mainnet: 'https://api.trongrid.io/jsonrpc',
shasta: 'https://api.shasta.trongrid.io/jsonrpc'
}
// 1) Ask backend for an unsigned transaction
const params = new URLSearchParams({
chainId,
tokenAddress: token,
ownerAddress,
to: ownerAddress, // example
value: String(100_000_000) // 100 TRX in SUN for demo
})
const url = `${basePath}/initWithdraw?${params.toString()}`
const response = await fetch(url)
if (!response.ok) throw new Error(`Backend error: ${response.status}`)
const { transaction: rawTx } = await response.json()
// Verify the correctness of payload here
// 2) Sign and broadcast with TronWeb
const fullHost = rpcMap[chainId].replace('/jsonrpc', '')
const tronWeb = new TronWeb({ fullHost, privateKey })
const signedTx = await tronWeb.trx.sign(rawTx, privateKey)
const result = await tronWeb.trx.sendRawTransaction(signedTx)
if (result.code === 'CONTRACT_VALIDATE_ERROR') {
throw new Error(`Validation failed: ${result.message}`)
}
return result.txid || result.txID
}
// Example usage
;(async () => {
const owner = 'TXYZ123abcDEF456ghiJKL789mnoPQRstu'
const pk = 'your_private_key_here'
const token = 'TRX'
const chain = 'shasta'
const txid = await withdrawTVM(owner, pk, token, chain)
console.log('TRON TXID:', txid)
})()
EVM (Ethereum-compatible)
Use ethers to sign and broadcast the transaction returned by your backend.
import { ethers } from 'ethers'
import fetch from 'node-fetch'
/**
* Initialize transfer on EVM, sign and broadcast the transaction
*
* @param {number|string} chainId - EVM chain id (e.g. 1, 11155111).
* @param {string} rpcUrl - JSON-RPC endpoint for the chain.
* @param {string} privateKey - Sender's private key (0x-prefixed hex).
* @param {string} ownerAddress - Sender address.
* @param {string} tokenAddress - ERC-20 address or 0x000...000 for native.
* @param {string} value - Amount (wei for native, token units per backend contract).
* @param {string} to - Recipient address.
*/
async function withdrawEVM({ chainId, rpcUrl, privateKey, ownerAddress, tokenAddress, value, to }) {
const basePath = 'https://api.feemaker.io' // your backend endpoint
// 1) Ask backend for an unsigned transaction
const response = await fetch(`${basePath}/initWithdraw`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ chainId, tokenAddress, ownerAddress, value, to })
})
if (!response.ok) throw new Error(`Backend error: ${response.status}`)
const transaction = await response.json()
// Veriry the correctness of payload here
// 2) Prepare signer
const provider = new ethers.JsonRpcProvider(rpcUrl)
const wallet = new ethers.Wallet(privateKey, provider)
const sent = await wallet.sendTransaction(transaction)
const receipt = await sent.wait()
if (!receipt || receipt.status !== 1) throw new Error('Transaction failed')
return sent.hash
}
// Example usage
;(async () => {
const chainId = 11155111 // Sepolia
const rpcUrl = 'https://rpc.sepolia.org'
const privateKey = '0xyour_private_key_here'
const ownerAddress = '0xYourAddress'
const tokenAddress = '0x0000000000000000000000000000000000000000' // native ETH
const value = '1000000000000000' // 0.001 ETH in wei
const to = '0xRecipientAddress'
const hash = await withdrawEVM({ chainId, rpcUrl, privateKey, ownerAddress, tokenAddress, value, to })
console.log('EVM tx hash:', hash)
})()
Important: You must have some ETH or TRX (depending on the network) in the owner wallet to pay gas/energy and the withdrawal fee. If the balance is insufficient, the transaction will be reverted and you will need to top up the address to continue withdrawal operations. All incoming transactions and their storage are fully safe and free. Operational funds are needed only for withdrawals.