
getTransfersByAddress: Parsed Solana Transfer History in 1 Call
getTransfersByAddress is a new Helius-exclusive Solana RPC method that returns parsed, human-readable token and SOL transfer records for a wallet address — with native filters for mint, time, amount, slot, direction, and counterparty.
It's the perfect counterpart to getTransactionsForAddress (gTFA). Where gTFA returns full transaction payloads, getTransfersByAddress returns concise transfer objects: who sent what, to whom, when, and how much.
Why do we need a transfer-specific RPC method?
Most wallet, payments, and portfolio products don't need the entire transaction payload. They need transfers.
So, what do they do? Each team writes a different version of the same transfer parser, and unfortunately most get the edge cases wrong.
Until now, building a clean Solana transfer history required devs to:
- Pull signatures with
getSignaturesForAddress - Fetch each signature with
getTransaction - Parse pre/post balances, token balances, and inner instructions
- Reconstruct transfers, handle SPL Token vs Token-2022 fee semantics, and untangle WSOL wrap/unwrap noise
- Repeat across multiple pages, handle retries, and store results
Even with the getTransactionsForAddress method collapsing steps 1 and 2 into one call, steps 3–5 still fall on the developer.
Now, getTransfersByAddress does this work for you and returns the result as a structured list.
getTransfersByAddress Response
Each transfer object includes the signature, slot, block time, transfer type, sender, recipient, mint, amount (raw and UI), decimals, confirmation status, and precise instruction indices so you can map each transfer back to the source transaction.
{
"signature": "<TX_SIGNATURE>",
"slot": 315073428,
"blockTime": 1736159420,
"type": "transfer",
"fromUserAccount": "<SENDER_WALLET>",
"toUserAccount": "<RECIPIENT_WALLET>",
"fromTokenAccount": "<SENDER_TOKEN_ACCOUNT>",
"toTokenAccount": "<RECIPIENT_TOKEN_ACCOUNT>",
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "2500000",
"decimals": 6,
"uiAmount": "2.5",
"confirmationStatus": "finalized",
"transactionIdx": 35,
"instructionIdx": 1,
"innerInstructionIdx": 0
}The type field tells you exactly what happened — transfer, transferFee, mint, burn, wrap, unwrap, changeAccountOwner, or withdrawWithheldFee — so you don't have to infer behavior from raw program data.
Why is parsing Solana transfers difficult?
A transfer in a Solana transaction isn't a single concept.
It's a category that hides a half-dozen edge cases, and getting any of them wrong corrupts your data.
SOL vs. WSOL
Native SOL and Wrapped SOL look like the same asset to a user, but they live in different parts of a transaction.
Native SOL moves through pre/post lamport balances on system accounts. WSOL moves through SPL token balances on token accounts.
A user swapping on Jupiter may wrap SOL into WSOL, swap WSOL for USDC, then never unwrap — leaving a WSOL token account behind.
From the user's perspective, they spent SOL. From the network’s perspective, there were three transfers and a wrap.
Worse, the wrap itself isn't a transfer to a different owner — it's the same wallet moving lamports into its own token account. Counting it as a transfer double-counts the user's activity.
Token-2022 Transfer Fees
Token-2022 introduced TransferCheckedWithFee, where the sender's debit doesn't match the recipient's credit.
The difference is withheld in the recipient's token account as a fee, payable later to a fee authority via withdrawWithheldFee.
A naive parser sees one transfer and gets the amount wrong. A careful parser detects the fee extension, split the instruction into a transfer plus a withheld-fee accrual, and track the fee account separately.
Mints and Burns
Tokens minted into an account have no sender. Burned tokens have no recipient. Both look like "transfers" in pre/post balance deltas, but conflating them with wallet-to-wallet transfers distorts counterparty analytics — you'd see wallets "receiving" funds from the zero address and "sending" funds into the void.
getTransfersByAddress represents these as mint and burn types with fromUserAccount or toUserAccount set to null, so you can include or exclude them depending on what you're building.
Benefits of getTransfersByAddress
The getTransfersByAddress method accepts filters that previously required pulling and parsing entire transaction histories client-side.
Search by Mint
Return only transfers for a specific token.
{
"jsonrpc": "2.0",
"id": "1",
"method": "getTransfersByAddress",
"params": [
"<WALLET_ADDRESS>",
{ "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }
]
}Search by Amount
Filter by raw amount with gt, gte, lt, lte comparisons. Useful for surfacing whales, ignoring dust (i.e., accounts with insignificant token amounts), or flagging unusual activity.
{
"params": [
"<WALLET_ADDRESS>",
{
"mint": "So11111111111111111111111111111111111111112",
"filters": {
"amount": { "gte": 1000000000, "lt": 10000000000 }
}
}
]
}Search by Time
Block time is supported as a Unix-timestamp range. Slot ranges work the same way for slot-precise queries.
{
"params": [
"<WALLET_ADDRESS>",
{
"filters": {
"blockTime": { "gte": 1735718400, "lt": 1738396800 }
}
}
]
}Search by Counterparty
Combine with and direction parameters to query transfers between two specific wallets, in either direction.
{
"params": [
"<WALLET_ADDRESS>",
{
"with": "<COUNTERPARTY_WALLET>",
"direction": "in"
}
]
}SOL Mode
Because native SOL and WSOL appear differently on Solana, but usually mean the same thing to a user, the getTransfersByAddress method exposes a solMode parameter.
merged (default)
WSOL is treated as native SOL.
Wrap and unwrap rows are excluded, and querying by the native SOL mint returns both native SOL and WSOL transfers.
separate
In this mode, WSOL is preserved as a distinct mint, and wrap and unwrap lifecycle rows are included for full auditability.
Most product use cases will often want merged. Reconciliation, accounting, and protocol-level analytics often want separate.
Pagination and Ordering
Standard cursor-based pagination via paginationToken, up to 100 records per page. sortOrder accepts asc and desc.
{
"jsonrpc": "2.0",
"id": "1",
"method": "getTransfersByAddress",
"params": [
"<WALLET_ADDRESS>",
{ "limit": 50, "paginationToken": "315069220:308:2:1" }
]
}When to Use getTransfersByAddress
getTransfersByAddress and getTransactionsForAddress are similar, but serve distinct purposes.
Need | Method |
|---|---|
Parsed token and SOL transfers, with filters |
|
Full transaction payloads or non-transfer activity |
|
Just signatures |
|
Real-time streaming of transfers |
Get Started
The getTransfersByAddress method is available today on all paid plans starting with the Developer plan. It costs 10 credits per request and is part of your standard RPC rate limit group.
Use it with your existing Helius RPC URL:
const response = await fetch("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getTransfersByAddress",
params: ["<WALLET_ADDRESS>"]
})
});
const data = await response.json();
console.log(data.result.data);Read the API reference for full parameter and response details.
Related Articles
Subscribe to Helius
Stay up-to-date with the latest in Solana development and receive updates when we post


