Investor: Swap tokens
This guide explains how to integrate with our Token Swaps, which allows qualified investors to execute delivery-versus-delivery (DvD) token swap transfers which ensures secure and compliant transfers between parties. For detailed explanations on all types of security token transfers, please view this article.
Swaps can involve any combination of ERC-3643 and ERC-20 tokens. However, for ERC-3643 tokens, both sender and recipient must be qualified and compliant for the specific token. ERC-20 tokens are permissionless and do not require qualification. For detailed parameter specifications and error codes, please refer to the Swagger documentation.
In this article, we will use the testing environment in the path, please note that you may be using a different environment.
Prerequisites:
To complete this use case, you will need to authenticate your request(s). You can generate your token by following these steps:
- Make sure to leverage an existing account, e.g. Agent, Owner, etc.
- Sign into your Servicing portal to disable your 2FA.
- Navigate to the "Getting API access" page to generate the required JWT, thanks to your credentials.
- Add the JWT to the header of your request.
Complete Swap Transfer Workflow
Step 1: Getting the tokenId
Before you can interact with the swaps endpoints, you must first obtain the tokenId associated with the tokens you want to use. This ID is retrieved from the endpoint:
GET /v2/assets/investor/tokens/me
Each token listed includes a unique id, this id will serve as the tokenId when making requests to the swaps endpoints.
Step 2: Getting the tokenId of counterpart tokens
On Tokeny ecosystem we use tokens as counterpart payment of different operations with TREX tokens. Examples:
- ERC20 stable coins: USDT, USDC, EURC, etc.
- ERC20 native tokens: ETH, POL, AVAX, etc.
- TREX stable coins: KYPAY, etc.
Before you can interact with the swaps endpoints, you must first obtain the tokenId associated with the counterpart tokens you want to use. This ID is retrieved from the endpoint:
GET /v2/assets/payment-tokens
Each token listed includes a unique id, this id will serve as the tokenId when making requests to the swaps endpoints.
Step 3: Check Existing Allowances
GET /v2/assets/investor/tokens/{tokenId}/allowances?senderAddress=<wallet_address>&type=DVD
Check if the wallet already has sufficient allowances for the token to be swapped.
Response: Returns current allowances for the specified token and wallet
Step 4: Set Allowances (if needed)
POST /v2/assets/investor/tokens/{tokenId}/allowances
If the previous check reveals that there is not enough allowance, it is required to set or increase the allowance for each token to be swapped.
New allowances will replace older ones. If there is “ amount : 6” allowed, and you send another allowance of 6, it will remain 6.
Request Body:
{
"senderAddress": "\<wallet_address>",
"amount": "\<token_amount>",
"type": "DVD" // Use DVD for delivery-versus-delivery swaps
}
Response: Returns a task_id used in step 4 and a transaction payload that must be signed by the token investor.
Step 5: Sign and Submit the Allowance Transaction
Refer to the guide based on the specific sign and broadcast solution your API integration requires by visiting the following link: Blockchain signature flow.
You can only complete transfers that you have initiated. Additionally, include the taskId returned in the previous endpoint's response when calling the transaction logging endpoint.
Logging the transaction is essential to reconcile on-chain and off-chain flows. Since the user handles blockchain interactions on their own, we use the taskId to:
- Identify the workflow uniquely.
- Maintain a consistent link between off-chain logic and on-chain activity.
- Ensure traceability and reliability.
Option A: Sign and Broadcast Yourself
Sign the transaction payload with your private key.
Broadcast, on your end, the signed transaction to the blockchain.
Log the transaction hash:
POST /v2/assets/investor/tokens/{tokenId}/allowances/{allowanceId}/transactions
You can use the allowanceId retrieved in the answer body of the previous step.
With Payload:
{
"taskId": "\<task_id>",
"txHash": "\<transaction_hash>"
}
Option B: Sign and Let Tokeny Broadcast
Sign the transaction payload with your private key
Send the signed payload for broadcasting:
POST /v2/assets/investor/tokens/{tokenId}/allowances/{allowanceId}/payloads
With payload:
{
"taskId": "\<task_id>",
"signedPayload": "\<signed_transaction_data>"
}
Step 6: Initiate Swap Transfer
POST /v2/assets/investor/swaps
After setting the necessary allowances, the sender creates a new swap request by providing:
- Source token details
- Destination token details
- Amount to swap
- Recipient wallet information
Response: Returns a transaction payload that must be signed by the sender.
Step 7: Sign and Submit the Swap Transaction
Refer to the guide based on the specific sign and broadcast solution your API integration requires by visiting the following link: Blockchain signature flow.
You can only complete transfers that you have initiated. Additionally, include the taskId returned in the previous endpoint's response when calling the transaction logging endpoint.
Logging the transaction is essential to reconcile on-chain and off-chain flows. Since the user handles blockchain interactions on their own, we use the taskId to:
- Identify the workflow uniquely.
- Maintain a consistent link between off-chain logic and on-chain activity.
- Ensure traceability and reliability.
Option A: Sign and Broadcast Yourself
- Sign the transaction payload
- Broadcast the signed transaction
- Log the transaction hash:
POST /v2/assets/investor/swaps/{swapId}/transactions
Option B: Sign and Let Tokeny Broadcast
- Sign the transaction payload
- Send the signed payload:
POST /v2/assets/investor/swaps/{swapId}/payloads
Step 8: Recipient - Retrieve Existing Swaps (Optional)
This endpoint allows you to query existing swap requests associated with a specific tokenId. You can use it to review the status of any pending, completed, or cancelled swaps before initiating a new one.
The response will include a unique swapId for each swap. This swapId is required in a later step when submitting the approve transaction, so make sure to store or reference it appropriately.
GET /v2/assets/investor/swaps?tokenId={{token_id}}
Step 9: Recipient - Check Existing Allowances
GET /v2/assets/investor/tokens/{tokenId}/allowances?senderAddress=<recipient_wallet_address>&type=DVD
Recipient checks if their wallet has sufficient allowances for their token to be swapped.
Step 10: Recipient - Set Allowances (if needed)
POST /v2/assets/investor/tokens/{tokenId}/allowances
If the previous check reveals that there is not enough allowance, the recipient should sets or increases the allowance for their token.
Request Body:
{
"senderAddress": "\<recipient_wallet_address>",
"amount": "\<token_amount>",
"type": "DVD"
}`
Response: Returns a transaction payload that must be signed.
Step 11: Recipient - Sign and Submit the Allowance Transaction
The recipient follows the same signing process as in Step 4.
Step 12: Recipient - Approve or Reject the Swap
Option A: Approve the Swap
POST /v2/assets/investor/swaps/{swapId}/approve
The recipient approves the swap request.
Option B: Reject the Swap
POST /v2/assets/investor/swaps/{swapId}/reject
Response: For approval, returns a transaction payload that must be signed.
Step 13: Recipient - Sign and Submit Approval Transaction
If approved, the recipient signs and processes the approval transaction following the same process as in Step 4.
Step 14: Monitor Swap Status
GET /v2/assets/investor/swaps
Both parties can check the status of the swap to confirm completion.
Status Transitions
A swap workflow transitions through these states:
CREATED
- Initial state after swap initiationPENDING_APPROVAL
- Waiting for recipient actionAPPROVED
- Recipient has approved the swapCOMPLETED
- Swap has been fully executed on blockchainCANCELLED
- Swap was cancelled by the initiatorREJECTED
- Swap was rejected by the recipientFAILED
- An error occurred during the blockchain execution or processing of the swap, preventing its successful completion
Cancellation Flow
At any point before completion, the initiator can cancel the swap:
Step 1: Request Cancellation
POST /v2/assets/investor/swaps/{swapId}/cancel
Response: Returns a transaction payload that must be signed.
Step 2: Sign and Submit the Cancellation Transaction
Option A: Sign and Broadcast Yourself
- Sign the cancellation transaction payload
- Broadcast the signed transaction
- Log the transaction hash:
POST /v2/assets/investor/swaps/{swapId}/transactions
With payload:
{
"taskId": "\<task_id>",
"txHash": "\<transaction_hash>"
}
Option B: Sign and Let Us Broadcast
- Sign the cancellation transaction payload
- Send the signed payload:
POST /v2/assets/investor/swaps/{swapId}/payloads
With Payload:
{
"taskId": "\<task_id>",
"signedPayload": "\<signed_transaction_data>"
}
Updated 1 day ago