Trade history and trade cards
Read a wallet's filled LayerHop swaps with their USD value at fill from GET /v1/portfolio/{address}/trades, and share a verified trade card for any filled order with GET /v1/orders/{quoteId}/card.
Every swap routed through LayerHop is an order. Once an order fills, two public, read-only endpoints expose it: GET /v1/portfolio/{address}/trades lists a wallet's filled swaps (the LayerHop app's Portfolio uses it for cost basis and PnL on any device), and GET /v1/orders/{quoteId}/card returns the data for a shareable "verified on-chain" trade card. Neither needs an API key; the usual per-IP rate limit applies.
Note
Only swaps made through LayerHop appear (orders built with
POST /v1/orders), not a wallet's other on-chain activity. Test-mode orders are never included.
How is the USD value at fill recorded?#
When an order turns filled, the API values both sides of that order with its price service (the same prices as GET /v1/prices), usually within a minute of the fill, and stores them with the order as srcAmountUsd (input) and dstAmountUsd (output). It is the USD value of the user's own swap, not a market data feed. Only listed tokens are valued (on LayerHop's curated list, or verified / popular on a provider list), because whoever deploys an unlisted token can make up its price. A side is null when it wasn't recorded: the order filled before this existed, the token had no price at the time, or the token is unlisted. Values are not back-filled later, so a null stays null.
How do I list a wallet's filled trades?#
curl https://api.layerhop.com/v1/portfolio/0x2222222222222222222222222222222222222222/trades{
"address": "0x2222222222222222222222222222222222222222",
"trades": [
{
"quoteId": "q_0b5c6a4e-2f1d-4b8a-9c3e-7d6f5a4b3c2d",
"provider": "relay",
"role": "both",
"srcChainId": 8453,
"srcToken": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"srcSymbol": "USDC",
"srcDecimals": 6,
"srcVerified": true,
"srcAmount": "25000000",
"srcAmountUsd": 25,
"dstChainId": 7565164,
"dstToken": "So11111111111111111111111111111111111111112",
"dstSymbol": "SOL",
"dstDecimals": 9,
"dstVerified": true,
"dstAmount": "131250000",
"dstAmountUsd": 24.9,
"srcTxHash": "0x5f2c…b2c4",
"srcTxVerified": true,
"dstTxHash": "3xQm…3Xx",
"filledAt": "2026-10-25T09:14:03.000Z"
}
]
}- The newest 200 filled orders where the address is the sender or the recipient, newest first. EVM addresses match in any case (they are stored lowercased); Solana addresses match exactly.
rolesays which side the wallet was on:sender(it paid),recipient(it received) orboth.- Amounts are integer strings in base units. The decimals are
nullfor a token LayerHop doesn't know. srcVerified/dstVerifiedsay whether each token is listed (LayerHop's curated list, or verified / popular on a provider list). An unlisted token's symbol isnulland it has no USD value: show it by its address, since anyone can deploy a token called "USDC".srcTxVerifiedistruewhen the source transaction was checked on chain when it was reported (sent by the order's sender to the transaction LayerHop built).filledAtis when LayerHop saw the fill.- Cached for 30 seconds per address (a full 200-trade history isn't cached). An address that isn't an EVM or Solana wallet is
INVALID_PARAMS.
Which transaction hashes does it show?#
Anyone can look up any address, so a trade only shows the side that address took part in:
role |
srcTxHash |
dstTxHash |
|---|---|---|
both (the wallet paid and received) |
shown | shown |
sender (it paid someone else) |
shown | null (it would reveal the recipient) |
recipient (someone else paid it) |
null (it would reveal the sender), srcTxVerified: false |
shown |
The other party's address is never returned.
How does the app compute PnL from it?#
The Portfolio page in the LayerHop app merges these trades with the swaps kept in the browser (one row per quoteId) and shows, per token bought:
- Cost: the sum of
srcAmountUsdof the buys. Where that isnull, it uses today's price of the token paid with and marks the figure with~(an approximation). - Average cost: cost ÷ amount bought.
- Unrealized PnL: the amount still held at today's price, minus its average cost.
- Total change: value now + sell proceeds − cost.
You can do the same with the fields above. Today's prices come from GET /v1/prices.
How do I get a trade card?#
curl https://api.layerhop.com/v1/orders/q_0b5c6a4e-2f1d-4b8a-9c3e-7d6f5a4b3c2d/cardThe answer has the same fields as a trade above without role: tokens, chains, amounts, USD values at fill (or null), filledAt, both transaction hashes, the trust checks (srcVerified, dstVerified, srcTxVerified) and the provider. It never includes a wallet address. Unknown, unfilled and test-mode orders return ORDER_NOT_FOUND (404). Cards are cached for 5 minutes.
In the app, every filled swap can be shared as a card at https://app.layerhop.com/card/<quoteId>: a page with links to the source and destination transactions on their block explorers, and a matching share image for X and Telegram. Share trade card appears on the swap success screen and on filled rows of the Activity page. The link carries the sharer's wallet as ?r= (see Referral links); the card itself still shows no address.
The card says Verified on-chain only when srcTxVerified is true, otherwise Recorded by LayerHop. A token that isn't listed shows as Unlisted token with its short address instead of its symbol, and the card shows a USD value only from a listed token. If you render cards yourself, apply the same checks.
Tip
A card proves the swap happened: the explorer links show the transactions on chain. The amounts on the card come from LayerHop's order record, so check them against the explorer if it matters.
See the API reference for the full schemas.
Last updated