# Funding and cross-chain

Source: https://www.scanner.net/docs/api/reference/funding

> Trace a wallet's funding chain hop by hop, and look up its bridge transfers to and from other chains.

Two ways to follow money into and out of a wallet: back up its funding chain, and across bridges to other chains.

3 routes. Every path below is served under `https://api.scanner.net`, and every request carries the key header, so those two are not repeated per route. Shared errors, limits and streaming are in [Requests and errors](/docs/api/reference/conventions).

Funding chain stream [#funding-chain-stream]

```http
GET /funding-chain/stream
```

Walks a wallet's funding back one hop at a time: who funded it, who funded that wallet, and so on, until it reaches a labelled entity, a KOL wallet, a wallet with no funder, a loop, or the depth limit. Answers with [server-sent events](/docs/api/reference/conventions#streaming-routes). Works on Solana and Robinhood Chain; the chain is taken from the address.

| Parameter  | In    | Type    | Required | Notes                                                                                                                           |
| ---------- | ----- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `address`  | query | string  | yes      | A Solana address, or a `0x` address for Robinhood Chain.                                                                        |
| `maxDepth` | query | integer | no       | Hops to walk. Up to 50 on Solana and 8 on Robinhood Chain, which are also the defaults. Larger values are lowered to the limit. |

```bash
curl -N "https://api.scanner.net/funding-chain/stream?address=WALLET_ADDRESS&maxDepth=20" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Events:**

* `start`: `{ address, maxDepth, cached }`.
* `layer`: `{ node }`, once per hop. Depth 0 is the wallet you asked about. Each node has `address`, `depth`, `fundedAmount`, `fundedAsset`, `fundedDate`, `signature`, `isBundled`, `bundleGroupIds` and `entity` when labelled. On Robinhood Chain all layers arrive together when the trace finishes.
* `terminal`: `{ reason, terminalDepth, node }`. `reason` is `labeled`, `kol`, `depth`, `loop` or `no_funder`. Robinhood Chain traces end with `labeled`, `no_funder` or `depth`.
* `complete`: `{ chain: { holderAddress, chain: [...] }, tracedAt }`, with `tracedAt` in unix milliseconds.
* `error`: `{ error, code }`, with code `TIMEOUT` or `INTERNAL_ERROR`.

**Cost:** 1 scan for a live trace, charged before it starts. A trace of the same address with the same `maxDepth` from the last 24 hours is replayed free, with `cached: true`. A different `maxDepth` is a separate trace. A failed trace is refunded, unless the connection was closed after layers had arrived.

| Status | Code                   | When                          |
| ------ | ---------------------- | ----------------------------- |
| 400    | `MISSING_ADDRESS`      | No `address`.                 |
| 400    | `INVALID_ADDRESS`      | Not a Solana or `0x` address. |
| 402    | `INSUFFICIENT_CREDITS` | Not enough scans left.        |

The two `400` bodies are `{ "success": false, "error", "code" }`, without `requestId`.

Cross-chain lookup [#cross-chain-lookup]

```http
GET /cross-chain/{address}
```

Bridge transfers to and from a wallet, gathered from bridge providers. Works for Solana and `0x` addresses.

| Parameter | In    | Type   | Required | Notes                                                                                 |
| --------- | ----- | ------ | -------- | ------------------------------------------------------------------------------------- |
| `address` | path  | string | yes      | A Solana address or a `0x` address.                                                   |
| `stored`  | query | string | no       | `1` returns only what Scanner has already stored, without asking the providers. Free. |

```bash
curl "https://api.scanner.net/cross-chain/WALLET_ADDRESS" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "address", "transfers", "complete", "providers", "checkedAt", "missing", "cached" }`.

* `transfers`: newest first, at most 500. Each has `id`, `source` (the bridge), `status` (`pending`, `success`, `failed`, `refunded` or `unknown`), `createdAtMs`, `sender`, `receivers`, `src` and `dst` legs (`chain`, `chainName`, `tokenSymbol`, `amount`, `txHash`), `amountUsd` and `direction` (`in`, `out` or `self`).
* `complete`: `false` when some providers didn't answer. `providers` gives `answered` and `total`, and `missing` how many failed. Use [Retry](#cross-chain-retry) to ask the missing ones again.
* `cached`: `true` when the answer came from a recent lookup.

A provider failure gives an incomplete result, not an error.

**Cost:** 1 scan for a live search, charged up front. It is refunded when no provider answered. `stored=1` and cached answers are free.

| Status | Code                   | When                          |
| ------ | ---------------------- | ----------------------------- |
| 400    | `MISSING_ADDRESS`      | Empty address.                |
| 400    | `INVALID_ADDRESS`      | Not a Solana or `0x` address. |
| 402    | `INSUFFICIENT_CREDITS` | Not enough scans left.        |

Cross-chain retry [#cross-chain-retry]

```http
POST /cross-chain/{address}/retry
```

Asks again only the providers that failed in the wallet's latest live lookup, and returns the merged result. Free. No body.

| Parameter | In   | Type   | Required | Notes                               |
| --------- | ---- | ------ | -------- | ----------------------------------- |
| `address` | path | string | yes      | A Solana address or a `0x` address. |

```bash
curl -X POST "https://api.scanner.net/cross-chain/WALLET_ADDRESS/retry" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** the same shape as the [lookup](#cross-chain-lookup), with `cached: false`.

Each wallet can be retried once every 30 seconds. The limit is per wallet, shared by every caller.

| Status | Code              | When                                                                                                           |
| ------ | ----------------- | -------------------------------------------------------------------------------------------------------------- |
| 400    | `INVALID_ADDRESS` | Not a Solana or `0x` address.                                                                                  |
| 409    | `CONFLICT`        | There is no live lookup to retry, or retrying isn't available right now. The body includes `retryable: false`. |
| 429    | `RATE_LIMITED`    | The wallet was retried less than 30 seconds ago. The body includes `retryAfterSeconds`.                        |
| 503    | `UPSTREAM_ERROR`  | The bridge index didn't answer.                                                                                |
