Transfer funds
ChainGate lets you transfer funds from your wallet to any valid recipient address across supported blockchains. Whether you're using a UTXO-based chain (like Bitcoin, Litecoin, or Dogecoin) or an EVM-based chain (like Ethereum), the API provides a consistent flow: create a transfer, review fees, and sign + broadcast.
Every blockchain transaction incurs a fee. Always ensure you have enough funds to cover both the transaction amount and its fee.
If your wallet is encrypted, the askForPassword callback will be triggered when signing the transaction during signAndBroadcast().
Basic transaction flow
import { newWallet, ChainGate } from 'chaingate'
const { wallet } = newWallet()
const cg = new ChainGate({ apiKey: 'your-api-key' })
// 1. Connect wallet to a network
const bitcoin = cg.connect(cg.networks.bitcoin, wallet)
// 2. Create an amount
const amount = cg.networks.bitcoin.amount('0.001')
// 3. Create a transfer (fetches fees, balance, and UTXOs automatically)
const tx = await bitcoin.transfer(amount, 'bc1q...')
// 4. Review recommended fees
const fees = tx.recommendedFees()
console.log('Normal fee enough funds?', fees.normal.enoughFunds)
// 5. Set fee tier and sign + broadcast
tx.setFee(fees.normal)
const broadcasted = await tx.signAndBroadcast()
console.log('TX ID:', broadcasted.transactionId)
// 6. Wait for confirmation (optional)
const cancel = broadcasted.onConfirmed((details) => {
console.log('Confirmed in block', details.blockHeight)
})
// Stop waiting at any time:
// cancel()
Sending an amount specified in fiat
If you prefer to send the fiat equivalent of an amount (e.g., "$25 worth of BTC"):
// Convert 25 USD to BTC at current rates
const amount = await cg.networks.bitcoin.amountFromCurrency('usd', 25)
const tx = await bitcoin.transfer(amount, 'bc1q...')
const fees = tx.recommendedFees()
tx.setFee(fees.normal)
const broadcasted = await tx.signAndBroadcast()
Supported fiat currencies
amountFromCurrency() accepts more than 120 fiat currencies identified by their ISO 4217 3-letter codes:
usd, eur, gbp, jpy, cny, aud, cad, chf, inr, brl, mxn, and many more.
// Send the equivalent of 100 EUR in ETH
const amount = await cg.networks.ethereum.amountFromCurrency('eur', 100)
Recommended fees
When you create a transfer, ChainGate automatically fetches recommended fee levels. Use tx.recommendedFees() to inspect them:
Available fee tiers
| Tier | Description |
|---|---|
low | Cheapest option, but slower confirmation |
normal | A balanced option for typical transactions |
high | Higher fee for faster confirmation |
maximum | Highest fee for the fastest possible confirmation |
Each tier includes:
enoughFunds(boolean) — Whether the wallet can cover the amount + fee.estimatedConfirmationSecs(number) — Estimated seconds until confirmation.
UTXO-specific properties
feePerKbSat(bigint) — Fee rate in satoshis per kilobyte.estimatedFeeSat(bigint | null) — Estimated total fee in satoshis.
EVM-specific properties
maxFeePerGas(bigint) — Maximum fee per gas in wei.maxPriorityFeePerGas(bigint) — Priority fee (tip) per gas in wei.
Setting a fee tier
Pass a tier object from recommendedFees() to setFee():
const fees = tx.recommendedFees()
tx.setFee(fees.high) // Use the "high" priority tier
Custom fees
Instead of using a recommended tier, you can set custom fee parameters:
UTXO custom fee
tx.setFee({ feePerKbSat: 15000n })
EVM custom fee
tx.setFee({
maxFeePerGas: 30_000_000_000n, // 30 gwei
maxPriorityFeePerGas: 2_000_000_000n, // 2 gwei
gasLimit: 50_000n // optional gas limit override
})
Checking funds
Always verify you have enough funds before broadcasting:
if (tx.enoughFunds()) {
const broadcasted = await tx.signAndBroadcast()
} else {
console.log('Insufficient funds')
}
Waiting for confirmation
After broadcasting, you can wait for the transaction to be confirmed on-chain:
const broadcasted = await tx.signAndBroadcast()
const cancel = broadcasted.onConfirmed((details) => {
console.log('Confirmed in block', details.blockHeight)
console.log('TX ID:', details.transactionId)
})
// Cancel polling at any time:
cancel()
EVM Ethereum example (full)
const cg = new ChainGate({ apiKey: 'your-api-key' })
const eth = cg.connect(cg.networks.ethereum, wallet)
const amount = cg.networks.ethereum.amount('0.05')
const tx = await eth.transfer(amount, '0xRecipient...')
const fees = tx.recommendedFees()
console.log('Normal fee:', fees.normal.maxFeePerGas, 'wei')
tx.setFee(fees.high)
const broadcasted = await tx.signAndBroadcast()
console.log('TX ID:', broadcasted.transactionId)
Estimated transaction size
For UTXO transactions, you can check the estimated size (in virtual bytes) at the current fee rate:
const size = tx.estimatedSizeBytes()
console.log('Estimated size:', size, 'vbytes') // null if not enough funds
Key points
- Uniform API:
transfer(),recommendedFees(),setFee(),signAndBroadcast()work for all networks. - Create amounts: Use
network.amount()for crypto amounts,network.amountFromCurrency()for fiat amounts. - Fee tiers: Pass a tier object from
recommendedFees()(e.g.fees.normal,fees.high) tosetFee(). Each tier includesenoughFundsandestimatedConfirmationSecs. - Custom fees: Pass an object with manual fee parameters to
setFee()for UTXO ({ feePerKbSat }) or EVM ({ maxFeePerGas, maxPriorityFeePerGas, gasLimit? }). - Transaction size: Use
estimatedSizeBytes()on UTXO transactions to get the virtual size at the current fee rate. - Confirmation tracking: Use
broadcasted.onConfirmed()to be notified when the transaction is mined. - Signing happens at broadcast:
signAndBroadcast()handles signing internally. Encrypted wallets prompt for the password at this point.