Transfer Tokens from Wallet to Wallet

In this tutorial, we will transfer tokens across two developer-controlled wallets. If you do not already have two wallets go to the create your first wallets tutorial, where we guide you through it step by step.

Note: The following tutorial uses the Polygon (MATIC) Testnet for illustration purposes. In production, you can create and use programmable wallets that support crypto tokens with the following blockchains and standards:

1. Get Gas Tokens

  1. Obtain MATIC tokens from the Polygon Faucet and send them to wallet 1's wallets.address
  2. Check wallet 1 balance using GET /wallets/{id}/balances
  3. Get MATIC tokenBalances.token.id from the response.
curl --request GET \
     --url 'https://api.circle.com/v1/w3s/wallets/{id}/balances' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer <API_KEY>'
{
  "data": {
    "tokenBalances": [
      {
        "token": {
          "id": "e4f549f9-a910-59b1-b5cd-8f972871f5db",
          "blockchain": "MATIC-MUMBAI",
          "name": "Polygon-Mumbai",
          "symbol": "MATIC-MUMBAI",
          "decimals": 18,
          "isNative": true,
          "updateDate": "2023-06-29T02:37:14Z",
          "createDate": "2023-06-29T02:37:14Z"
        },
        "amount": "0.2",
        "updateDate": "2023-08-03T22:22:07Z"
      }
    ]
  }
}

2. Transfer Tokens

Make a request to POST /developer/transactions/transfer with MATIC tokenId, Wallet 1's wallets.id, Wallet 2's wallets.address, as well as some predefined values for amount, and gas related request parameters.

curl --request POST \
     --url 'https://api.circle.com/v1/w3s/developer/transactions/transfer' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'authorization: Bearer <API_KEY>' \
     --data '
{
  "idempotencyKey": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
  "walletId": "ce714f5b-0d8e-4062-9454-61aa1154869b",
  "tokenId": "e4f549f9-a910-59b1-b5cd-8f972871f5db",
  "destinationAddress": "0xc90e058234d4b2db799d787a855ec68d801a53a3",
  "amounts": [
    ".01"
  ],
  "feeLevel": "MEDIUM",
  "entitySecretCiphertext": "XVXDshXQAjJSkDX1+9veL+pRYaPhYIab4os7SoLPwgXfDym6bF5fW7I07WAB4jSzkQombZ3bfDKEcLhg2C296WCuD7kJM8e6UNrzTeC3d6Pkv+BlOf45N8j/6njAGaBFIu9TVbmSSvK/Nxj0IwTOrEAumXyl2os/O0HWcj5xQMRVCx3p1JzJuwyZVgbgcsvMlzqOYuEo+rmAoPHwYQV5wgf0iYt+CHgsA8rLI/jUpQhRkwTxPXpETC//Qytj9nVfkB8YWMFfl5NMyjADiae5tQG20nP9pCR+cL7lRRQx8QUpZWZpo07v5usw7iTyakpDULi2KkKVI6TsoAMgpIyg6UUxIFFoIRVAW91jQTZ+YVGqmDBmX9TeVk+G/9Q2XGGgxsw0kmr7QCTe4asoCnTvGL1cdmwWKZO3ECZjk66MRB/ZF0YeNIb4HmebLvx4o4d6pkkdaGAfziPgz3GNE4Pz6fd3+t0R58Ha3rfd00kvYG04EnRBwM9mB2PXpo+qxLbbmNIIpm3DthbFRSnHALwMlPxNfieD9x2XB49W3JJhnt0gEMTLSG93cIFH2PCdDPET9ZHlyOaqNMJpLVzU//6w8s03QL4Y0D5j+G901hjKubwTafOQmVHRPOblhs8bakFOLprh6j+WePPtqcGC3vVyLKMObb8tOPAdfr700TdMviA="
}
'
{
  "data": {
    "id": "1af639ce-c8b2-54a6-af49-7aebc95aaac1",
    "state": "INITIATED"
  }
}

3. Check Transfer State

Make a request to GET /transactions/{id} to return available transactions.

curl --request GET \
     --url 'https://api.circle.com/v1/w3s/transactions/{id}' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer <API_KEY>'
{
  "data": {
    "transaction": {
      "id": "1af639ce-c8b2-54a6-af49-7aebc95aaac1",
      "blockchain": "MATIC-MUMBAI",
      "tokenId": "e4f549f9-a910-59b1-b5cd-8f972871f5db",
      "walletId": "ce714f5b-0d8e-4062-9454-61aa1154869b",
      "sourceAddress": "0xf5c83e5fede8456929d0f90e8c541dcac3d63835",
      "destinationAddress": "0xc90e058234d4b2db799d787a855ec68d801a53a3",
      "transactionType": "OUTBOUND",
      "custodyType": "DEVELOPER",
      "state": "COMPLETE",
      "amounts": [
        "0.01"
      ],
      "nfts": null,
      "txHash": "0xc0337cad6164f22eeb37af3e21488f77e7bc5ba4a92a2293e0a8bb8beaa61c88",
      "blockHash": "0xbcaf5d0dc5d50250a137808ca81eb4abebf13a639398c44660b35e387e5ad2d3",
      "blockHeight": 38738377,
      "networkFee": "0.000035910000189",
      "firstConfirmDate": "2023-08-07T14:41:02Z",
      "operation": "TRANSFER",
      "feeLevel": "MEDIUM",
      "estimatedFee": {
        "gasLimit": "21000",
        "baseFee": "0.000000016",
        "priorityFee": "1.709999993",
        "maxFee": "1.710000025"
      },
      "refId": "",
      "abiParameters": null,
      "createDate": "2023-08-07T14:40:54Z",
      "updateDate": "2023-08-07T14:42:04Z"
    }
  }
}

Once the transaction.state is COMPLETE you can rest assured that the token has moved from wallet 1 to wallet 2.

You can also check the transaction using the txHash on Polygon Mumbai explorer and inspect the balance of each wallet using GET /wallets/{id}/balances.