Documentation Index Fetch the complete documentation index at: https://docs.dfns.co/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers how to create transfers, handle different asset types, and monitor transfer status using the Dfns API and SDK.
Prerequisites
Service account or authenticated user with Wallets:Transfers:Create permission
Dfns SDK installed and configured
Wallet with sufficient balance for the transfer and gas fees
Creating a native token transfer
Send native tokens (ETH, MATIC, SOL, etc.):
import { DfnsApiClient } from '@dfns/sdk'
const dfns = new DfnsApiClient ({
baseUrl: 'https://api.dfns.io' ,
// Your signer configuration
})
const transfer = await dfns . wallets . createTransfer ({
walletId: 'wa-xxx-xxx' ,
body: {
kind: 'Native' ,
to: '0x1234...recipient' ,
amount: '1000000000000000000' // 1 ETH in wei
}
})
console . log ( 'Transfer ID:' , transfer . id )
console . log ( 'Status:' , transfer . status )
Request parameters
Parameter Required Description kindYes Transfer type: Native, Erc20, Erc721, etc. toYes Recipient address amountYes Amount in base units (wei for ETH) externalIdNo Your reference ID for tracking
Creating an ERC-20 token transfer
Send ERC-20 tokens:
const transfer = await dfns . wallets . createTransfer ({
walletId: 'wa-xxx-xxx' ,
body: {
kind: 'Erc20' ,
contract: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' , // USDC
to: '0x1234...recipient' ,
amount: '1000000' // 1 USDC (6 decimals)
}
})
Token amounts are in base units. USDC has 6 decimals, so 1 USDC = 1000000. ETH has 18 decimals, so 1 ETH = 1000000000000000000.
Creating an NFT transfer
Transfer ERC-721 NFTs:
const transfer = await dfns . wallets . createTransfer ({
walletId: 'wa-xxx-xxx' ,
body: {
kind: 'Erc721' ,
contract: '0x...nft-contract' ,
to: '0x1234...recipient' ,
tokenId: '123'
}
})
Transfer with external ID
Use external IDs for your own tracking:
const transfer = await dfns . wallets . createTransfer ({
walletId: 'wa-xxx-xxx' ,
body: {
kind: 'Native' ,
to: '0x1234...recipient' ,
amount: '1000000000000000000' ,
externalId: 'payout-2024-001' // Your reference
}
})
Checking transfer status
Get the status of a transfer:
const transfer = await dfns . wallets . getTransfer ({
walletId: 'wa-xxx-xxx' ,
transferId: 'tr-xxx-xxx'
})
console . log ( 'Status:' , transfer . status )
// 'Pending', 'Broadcasted', 'Confirmed', 'Failed'
Transfer statuses
Status Description PendingTransfer created, may be awaiting approval BroadcastedTransaction sent to the network ConfirmedTransaction confirmed on the blockchain FailedTransaction failed
Listing transfers
List transfers for a wallet:
const transfers = await dfns . wallets . listTransfers ({
walletId: 'wa-xxx-xxx'
})
for ( const transfer of transfers . items ) {
console . log ( ` ${ transfer . id } : ${ transfer . status } ` )
}
Handling policy approvals
If a transfer triggers a policy that requires approval, the transfer enters a Pending state:
const transfer = await dfns . wallets . createTransfer ({
walletId: 'wa-xxx-xxx' ,
body: {
kind: 'Native' ,
to: '0x1234...recipient' ,
amount: '100000000000000000000' // Large amount
}
})
if ( transfer . status === 'Pending' ) {
console . log ( 'Transfer requires approval' )
// The transfer will execute automatically once approved
}
See managing policies for working with approvals programmatically.
Monitoring with webhooks
Subscribe to transfer events for real-time updates:
// Subscribe to events
await dfns . webhooks . createWebhook ({
body: {
url: 'https://your-app.com/webhooks/dfns' ,
events: [
'wallet.transfer.broadcasted' ,
'wallet.transfer.confirmed' ,
'wallet.transfer.failed'
],
status: 'Enabled'
}
})
Handle webhook events:
app . post ( '/webhooks/dfns' , async ( req , res ) => {
const event = req . body
switch ( event . kind ) {
case 'wallet.transfer.confirmed' :
await handleTransferConfirmed ( event . data )
break
case 'wallet.transfer.failed' :
await handleTransferFailed ( event . data )
break
}
res . status ( 200 ). send ( 'OK' )
})
See webhooks guide for complete webhook setup.
Polling for status
Alternative to webhooks - poll for transfer status:
async function waitForConfirmation ( walletId : string , transferId : string ) {
while ( true ) {
const transfer = await dfns . wallets . getTransfer ({
walletId ,
transferId
})
if ( transfer . status === 'Confirmed' ) {
return transfer
}
if ( transfer . status === 'Failed' ) {
throw new Error ( `Transfer failed: ${ transfer . error } ` )
}
// Wait before checking again
await new Promise ( resolve => setTimeout ( resolve , 5000 ))
}
}
See transaction monitoring for polling best practices.
Error handling
Handle common errors:
try {
const transfer = await dfns . wallets . createTransfer ({
walletId: 'wa-xxx-xxx' ,
body: {
kind: 'Native' ,
to: '0x1234...recipient' ,
amount: '1000000000000000000'
}
})
} catch ( error ) {
if ( error . status === 403 ) {
console . error ( 'Permission denied' )
} else if ( error . status === 400 ) {
console . error ( 'Invalid request:' , error . message )
} else if ( error . message . includes ( 'insufficient balance' )) {
console . error ( 'Insufficient balance for transfer' )
} else {
console . error ( 'Error creating transfer:' , error )
}
}
Transfer API Complete API reference
Monitor transactions Polling patterns
Set up webhooks Real-time notifications
Manage policies via API Handle policy approvals