Skip to content

Send ERC20 and TRC20 Token Transfers

To send an ERC20, BEP20 or TRC20 token with Chaingateway, you post the sender, the recipient, the amount and the token’s contract address to the token endpoint of the chain, together with the wallet password or private key. A token transfer is a smart contract call, so the sender also needs the chain’s native coin to pay the fee: ETH, BNB, MATIC or TRX. The response returns the transaction hash.

For the API token, see Quickstart. On Ethereum, BNB Smart Chain and Polygon, the sending address must have been created with the Chaingateway API or imported into it. Otherwise the signing step fails. Create Addresses shows how to create one.

Token transfer: check the token balance, make sure the sender holds native coin for the fee, post the transfer with the contract address, read the transaction hash GET/api/v2/{chain}/balances/{address}/erc20/{contract} does the sender hold enough tokens? Sender holds native coin for the fee ETH, BNB, MATIC or TRX POST /api/v2/{chain}/transactions/erc20 from, to, amount, contractaddress, password orprivatekey Response: txid status 201
The balance check and the fee check come before the transfer.

Which endpoint sends a token on which chain?

Section titled “Which endpoint sends a token on which chain?”

Each chain has its own token endpoint, named after the token standard. The body is the same on all EVM chains.

BlockchainAPI routeStandard
Ethereum/api/v2/ethereum/transactions/erc20ERC-20
Binance Smart Chain/api/v2/bsc/transactions/bep20BEP20
Polygon/api/v2/polygon/transactions/erc20ERC-20
Arbitrum/api/v2/arbitrum/transactions/erc20ERC-20
Tron/api/v2/tron/transactions/trc20TRC20
Solana/api/v2/solana/transactions/SPLSPL

To run the request on a test network, add the header X-Network: testnet. The testnets are listed under Supported Networks. Bitcoin has no token endpoint.

Post the following fields to the route of your chain. The example sends an ERC20 token on Ethereum.

  • from: the sender’s address.
  • to: the recipient’s address.
  • amount: the amount of tokens to send.
  • contractaddress: the contract address of the token.
  • password: the wallet password, required when privatekey is not present.
  • privatekey: the private key of the sender, for addresses created without a password.

gas, gasprice, maxPriorityFeePerGas, maxFeePerGas and nonce are optional.

Terminal window
curl --request POST \
--url https://app.chaingateway.io/api/v2/ethereum/transactions/erc20 \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--data '{
"from": "0xYourSenderAddress",
"to": "0xRecipientAddress",
"amount": 100,
"contractaddress": "0xTokenContractAddress",
"password": "YourPassword"
}'

The code returns the transaction hash:

{
"status": 201,
"ok": true,
"message": "Succesfully created",
"data": {
"txid": "0x73344d178812d4919e9002c560781f288030edf72ece88823ef1c377dfb71f27"
}
}

The TRC20 request works almost like the ERC20 one. The route is /api/v2/tron/transactions/trc20, the addresses are Tron addresses, and you sign with password or privatekey. The OpenAPI file lists from, to, contractaddress and amount as required. The example uses the private key of an address that was created without a password.

Terminal window
curl --request POST \
--url https://app.chaingateway.io/api/v2/tron/transactions/trc20 \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--data '{
"from": "TYourSenderAddress",
"to": "TRecipientAddress",
"amount": 100,
"contractaddress": "TTokenContractAddress",
"privatekey": "YourPrivateKey"
}'

Create TRC20 Token Transactions walks through the whole TRC20 flow, including reading the contract and the self-signing endpoints.

How do I check a token balance before I send?

Section titled “How do I check a token balance before I send?”

Read the balance first, so that you do not send a transaction that will fail. On EVM chains, GET /api/v2/ethereum/balances/{address}/erc20/{contract_address} returns the balance of one token. GET /api/v2/ethereum/balances/{address}/erc20 lists the token balances of a wallet. On BNB Smart Chain the segment is bep20, and on Tron it is GET /api/v2/tron/balances/{address}/trc20/{contract_address}. GET /api/v2/ethereum/erc20/{contract_address} returns the contract information of a token.

Most failures are one of three causes, and each has a different message.

  • A wrong password returns status 401 with Wrong password provided.
  • A missing or malformed field returns status 422 with Data validation failed and the field name in errors.
  • A sender without enough native coin returns status 422 with the node’s message, for example insufficient funds for gas * price + value. On Tron the equivalent is balance is not sufficient.

The last cause surprises people who hold only tokens: the fee is paid in ETH, BNB, MATIC or TRX, never in the token. Read the Ethereum gas documentation for the fee model on EVM chains and TRON’s resource model for energy and bandwidth. If your TRON addresses hold tokens but no TRX, Sponsor TRC20 Fees lists the options.

NFT transfers use the ERC721 endpoints, for example POST /api/v2/ethereum/transactions/erc721. The body has the same signing fields as above, but instead of amount it takes tokenId, the id of the NFT. from, contractaddress, to and tokenId are required. GET /api/v2/ethereum/nfts/{contract_address}/owner/{token_id} returns the current owner, and .../uri/{token_id} returns the token URI. The standard is defined in EIP-721.