Send Transfers
Send native coin to an address. One API for Bitcoin (satoshis) and EVM chains (wei). Single recipient or batch on UTXO.
sendTransfer moves native coin (BTC, ETH, Base ETH, etc.) from the session address to one or more recipients. Dispatched by session network.
import { sendTransfer } from '@oviato/connect';
const r = await sendTransfer({
recipient: { address: '0x742d35Cc...', amount: 10n ** 15n },
fee: 'auto',
});
if (r.status === 'success' && r.type === 'sendTransferSuccess') {
console.log('TxID:', r.data.txid);
console.log('Explorer:', r.data.explorerUrl);
}For ERC-20 / NFT / contract calls on EVM, use
evm.writeContract instead — sendTransfer is
native coin only.
Amount units per chain
| Chain | Unit | Type |
|---|---|---|
| Bitcoin | satoshis (1 BTC = 100 000 000 sats) | number |
| Ethereum, Base | wei (1 ETH = 10¹⁸ wei) | bigint (preferred), string, or number for small values |
// Bitcoin
await sendTransfer({
recipient: { address: 'bc1q...', amount: 10_000 }, // 0.0001 BTC
});
// EVM — use bigint for overflow safety
await sendTransfer({
recipient: { address: '0x...', amount: 10n ** 15n }, // 0.001 ETH
});Single vs batch recipients
await sendTransfer({
recipient: { address, amount },
fee: 'auto',
memo: 'Payment for services', // optional
});Works on Bitcoin + EVM.
Bitcoin natively supports multiple outputs in one transaction. Save on fees vs sending N separate txs.
await sendTransfer({
recipients: [
{ address: 'bc1q...', amount: 10000 },
{ address: 'bc1p...', amount: 5000 },
{ address: 'bc1q...', amount: 7500 },
],
fee: 'auto',
memo: 'Splitting a payment',
});Attempting recipients: [] on an EVM chain returns an error — multi-recipient doesn't exist in EVM.
Fee handling
Fees are chain-specific, but the API is unified via semantic tiers:
await sendTransfer({
recipient: { address, amount },
fee: 'fast', // or 'medium' | 'slow' | 'auto' | <number>
});auto(default) — sensible default, ≈mediumfast,medium,slow— explicit tiers. Map to fee multipliers per chain.<number>— raw fee rate. On Bitcoin it's sat/vB; on EVM it's wei gas-price (not recommended — prefer tiers).
The bridge UI shows three tiers with current cost estimates before the user confirms, and lets them pick inline.
The full response shape
type Result =
| { status: 'success'; type: 'sendTransferSuccess'; data: { txid, network, explorerUrl } }
| { status: 'error'; message: string };Always narrow on status:
const r = await sendTransfer({ recipient: { address, amount } });
if (r.status === 'success' && r.type === 'sendTransferSuccess') {
console.log(r.data.txid);
} else if (r.status === 'error') {
console.error(r.message);
}EVM writes return data.hash via evm.sendTransaction /
evm.writeContract. sendTransfer uses data.txid universally. Both
are the same 0x-prefixed hex — the field name is different for
historical reasons.
Memo / OP_RETURN
Bitcoin supports a small arbitrary payload per transaction via OP_RETURN:
await sendTransfer({
recipient: { address, amount },
memo: 'Invoice #1234',
});Max size: ~80 bytes. Larger memos are rejected.
On EVM, memo is ignored — sendTransaction's data field serves the same purpose but has different semantics (it's calldata, not a comment).
Full parameter list
| Field | Type | Notes |
|---|---|---|
recipient | { address, amount } | For single-recipient sends. XOR with recipients. |
recipients | [{ address, amount }, ...] | UTXO only. XOR with recipient. |
fee | 'auto' | 'fast' | 'medium' | 'slow' | number | Default 'auto'. |
memo | string | UTXO only. Max ~80 bytes. |
method | 'popup' | 'iframe' | How the approval UI opens. |
Gotchas
Amount is smallest unit, always. Bitcoin gives you satoshis, EVM gives
you wei. amount: 1 on Bitcoin is 1 satoshi (0.00000001 BTC), not 1 BTC.
Use parseUnits('1', 18) for ETH or 10000 for 0.0001 BTC.
- Dust outputs. On Bitcoin, amounts below the dust threshold (≈546 sats) are rejected.
- Insufficient funds. Not just
amount > balance, butamount + fee > balance. The SDK fetches a fee estimate before confirming. - Self-sends. Sending to your own address works — useful for testing. The fee still applies.
Preview before sending
To show a transaction summary before the user confirms (cost, USD value, decoded recipient), call rpc.prepareTx with the same params:
import { rpc } from '@oviato/connect';
const preview = await rpc.prepareTx({
recipient: { address, amount },
fee: 'auto',
publicKey: session.publicKey,
address: session.address,
});
console.log(preview.result.feeTotalUsd);Related
- EVM Writes — contract calls, token transfers, EIP-712
- UTXO → Sign PSBT — advanced Bitcoin signing via PSBTs