Appearance
Amount & quote
Transfer amounts on the public API are human-readable source crypto (the token the user is sending) for a resolved transfer plan. Fiat (currently USD) is available from rates on the balance and from getMinAmount / getQuote.
Minimum
ts
const min = await client.wallets.transfer.getMinAmount(plan);
// min.crypto — source token units, already ceiled to display decimals
// min.fiat — USD, ceiled to maxFiatDecimals (default 2), when rates are known| Field | Meaning |
|---|---|
crypto | Minimum in source token units (what the user enters) |
fiat? | Fiat value of that minimum when rates are known |
The source min is never below the token's display-dust (getTokenMinAmount — e.g. 0.000001 ETH at 6 display decimals). A fiat amount that converts to less than that dust fails below_min. For swap/bridge, the destination min is converted into source units via exchange rates, then ceiled so typing the shown value cannot fall below the true minimum.
Validate
validateAmount does not throw. It checks flow, parse, and min.
ts
const validation = await client.wallets.transfer.validateAmount({
plan,
amount, // source crypto string
});
if (!validation.ok) {
validation.code; // 'BELOW_MIN' | 'INVALID_AMOUNT' | 'WRONG_FLOW'
validation.message;
validation.minAmount;
}WRONG_FLOW is returned when plan.flow === 'unavailable'.
Recommended validation stack
- Sanitize the input (
sanitizeAmountInput/parseAmountInput) so the string is parseable (no grouping). validateAmount({ plan, amount })for flow / parse / min.getQuote({ plan, amount })whenplan.flowisswaporbridge— for receive amount, fees, and ETA. Direct can skip.- Pass the same amount into
submit. Quote is display-only.
These helpers live on @swapped/connect-sdk (same suite Coinbase uses). You do not need every helper on the wallets page — sanitize → validate → quote when needed is enough.
Crypto / fiat helpers
From @swapped/connect-sdk (same helpers Coinbase uses):
| Helper | Purpose |
|---|---|
convertCryptoToFiat({ amount, exchangeRate, decimals? }) | Crypto → fiat string. decimals defaults to maxFiatDecimals (then 2) |
convertCryptoToFiatCeil({ amount, exchangeRate, decimals? }) | Crypto → fiat, ceiled (used for min labels) |
convertFiatToCrypto({ amountFiat, exchangeRate, maxDecimals }) | Fiat → crypto |
validateAmountInput({ amount, minAmount, maxAmount, … }) | Field validation |
parseAmountInput / sanitizeAmountInput / formatAmountForInput | Input parsing |
ts
convertFiatToCrypto({
amountFiat: '100',
exchangeRate: 2000,
maxDecimals: 6,
})
// "0.05"WalletBalance.exchangeRate / fiatValue / formatted are the rate and display strings for the selected token. When min.fiat is missing, convertCryptoToFiatCeil with token.exchangeRate produces a fiat min from min.crypto.
React: useDualAmountInput keeps crypto and fiat fields in sync.
Quote
ts
const quote = await client.wallets.transfer.getQuote({
plan,
amount, // human-readable source crypto
});WalletTransferQuote:
| Field | Meaning |
|---|---|
flow | 'direct' | 'swap' | 'bridge' |
amountIn | { crypto, fiat? } — what the user sends. crypto is a plain decimal (0.00000004), never scientific (4e-8) |
amountOut? | { crypto, fiat?, network, symbol } — expected receive (swap/bridge). Same plain-decimal crypto contract |
networkFee? | { amount, symbol, tokenAddress } — display fee. Swap: fiat from the route; bridge: network fee USD. symbol can be 'USD' |
protocolFeeFiat? | Protocol fee in fiat when the quote exposes one |
estimatedTimeSeconds? | Estimated completion time in seconds |
raw? | Opaque payload from the swap/bridge quote API. Display / debug only |
An invalid or empty amount throws WALLET_TRANSFER_INVALID_AMOUNT. Quote fetch failures throw WALLET_TRANSFER_QUOTE_FAILED.
submit only needs plan and amount. See Submit.