# 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.

Source: https://docs.layerhop.com/guides/trade-history

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?

```bash
curl https://api.layerhop.com/v1/portfolio/0x2222222222222222222222222222222222222222/trades
```

```json
{
  "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.
- `role` says which side the wallet was on: `sender` (it paid), `recipient` (it received) or `both`.
- Amounts are integer strings in base units. The decimals are `null` for a token LayerHop doesn't know.
- `srcVerified` / `dstVerified` say whether each token is listed (LayerHop's curated list, or verified / popular on a provider list). An unlisted token's symbol is `null` and it has no USD value: show it by its address, since anyone can deploy a token called "USDC".
- `srcTxVerified` is `true` when the source transaction was checked on chain when it was reported (sent by the order's sender to the transaction LayerHop built).
- `filledAt` is 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 `srcAmountUsd` of the buys. Where that is `null`, 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?

```bash
curl https://api.layerhop.com/v1/orders/q_0b5c6a4e-2f1d-4b8a-9c3e-7d6f5a4b3c2d/card
```

The 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](/guides/referrals)); 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](/api-reference) for the full schemas.
