> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gauntlet.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Attribution with SDK

> How the Gauntlet SDK tracks on-chain volume back to your integration using ERC-8021 builder codes, and how to monitor attributed activity.

Attribution links on-chain deposit and withdrawal volume back to your integration — enabling fee sharing and volume reporting in the Developer Portal. The SDK embeds attribution automatically on every transaction it builds.

## Setup

**You must request a builder code from Gauntlet** — it is not self-serve. Request one as part of your partnership onboarding. The Gauntlet indexer must recognize your specific code for volume to be counted against your integration; using an arbitrary string will append bytes to calldata but attribution will not be tracked.

Your builder code is separate from your API key — you may receive them together or at different stages of onboarding.

Once you have it, set `builderCode` on `GauntletClient`:

```typescript theme={null}
import { GauntletClient, AttributionMode } from '@gauntlet-xyz/sdk'

const client = new GauntletClient({
  evmClients: { ... },
  wallet: walletClient,
  builderCode: 'your-builder-code',          // issued by Gauntlet — request from the partnerships team
  attributionMode: AttributionMode.PUBLIC,   // default — no need to set explicitly
})
```

Without `builderCode`, `AttributionMode.PUBLIC` appends nothing and transactions are unattributed.

## How It Works

The SDK encodes attribution as an ERC-8021 calldata suffix appended to every transaction. It does not affect contract execution — the Gauntlet indexer reads it to attribute the volume.

**ERC-8021 format:**

```
0x{builderCode as UTF-8 hex}{byte length (1 byte)}{schema ID: 00}{16-byte marker: "8021" × 8}
```

For example, builder code `"acme"` (4 bytes) becomes `0x61636d650400` followed by the 16-byte marker `80218021802180218021802180218021`.

## Sending Transactions

How attribution is carried depends on which submission path you use.

### Path 1 — `step.payload` + `sendTransaction`

Attribution is **baked into `payload.data`** — the full calldata is already `{ABI-encoded call}{attribution suffix}`. The wallet receives a single opaque hex string and sends it as-is. Attribution cannot be lost regardless of what wallet or provider you use.

```typescript theme={null}
for (const step of steps) {
  // payload.data = ABI calldata + attribution suffix, pre-concatenated
  await walletClient.sendTransaction(step.payload)
}
```

**Best for:** backend scripts, server-side signing, embedded wallets (Privy, Dynamic, passkey signers), any flow that uses `eth_sendRawTransaction` directly, or anywhere you want `eth_call` pre-simulation on the exact calldata that will be broadcast.

### Path 2 — `step.tx` + `writeContract`

Attribution is in `step.tx.attribution` as standalone bytes. You must pass it as `dataSuffix` to `writeContract` — wagmi appends it to the ABI-encoded calldata before sending. **If `dataSuffix` is omitted or the EIP-1193 provider strips it, the transaction succeeds on-chain but volume is not attributed.**

```typescript theme={null}
for (const step of steps) {
  await walletClient.writeContract({
    address: step.tx.address,
    abi: step.tx.abi,
    functionName: step.tx.functionName,
    args: step.tx.args,
    account: step.tx.account,
    dataSuffix: step.tx.attribution, // ← required for attribution; omitting silently drops it
  })
}
```

**Best for:** browser wallets via wagmi (MetaMask, Coinbase Wallet, WalletConnect), or when you need wagmi's type-safe simulation hooks (`simulateContract`).

**Note:** Most major EIP-1193 providers used with wagmi honor `dataSuffix`. If you're using a custom or obscure provider, verify it forwards unknown `WriteContractParameters` fields before relying on this path for attribution.

## Attribution Modes

```typescript theme={null}
enum AttributionMode {
  PUBLIC  = 'public',   // ERC-8021 builder code appended — default
  ENCODED = 'encoded',  // not yet implemented
  PRIVATE = 'private',  // not yet implemented
}
```

Currently only `PUBLIC` is supported. `ENCODED` and `PRIVATE` throw `UnimplementedFeatureError` if used.

## Monitor Attributed Activity

<Note>
  Monitoring attribution is under development and not currently available.
</Note>

### Initialize

```typescript theme={null}
import { GauntletClient } from '@gauntlet-xyz/sdk'

const client = new GauntletClient({
  apiKey: process.env.GAUNTLET_API_KEY,
})
```

### Query Attributed Activity

```typescript API theme={null}
const API_BASE_URL = 'https://api.gauntlet.xyz'
const API_KEY = process.env.GAUNTLET_API_KEY!

const { data: txns } = await fetch(
  `${API_BASE_URL}/v1/users/0xUserWallet/transactions?limit=20`,
  { headers: { Authorization: `Bearer ${API_KEY}` } },
).then(r => r.json())
// returns:
// [
//   {
//     type: "deposit",
//     vault_id: "8453:0x000000000001cdb57e58fa75fe420a0f4d6640d5", // chain_id:address
//     amount: "1000.00",
//     timestamp: "2026-01-15T10:30:00Z"
//   },
//   ...
// ]

const { data: events } = await fetch(
  `${API_BASE_URL}/v1/events?type=deposit&limit=100`,
  { headers: { Authorization: `Bearer ${API_KEY}` } },
).then(r => r.json())
// returns:
// [
//   {
//     vault_id: "8453:0x000000000001cdb57e58fa75fe420a0f4d6640d5",
//     amount: "1000.00",
//     sender: "0x...",
//     timestamp: "2026-01-15T10:30:00Z"
//   },
//   ...
// ]
```

Use the vault's `chain_id:address` string (e.g. gtBTC on Ethereum is `1:0xeff0ae5b39271b33f448cd408b51dc8aa72a672b`) to filter events by vault: `GET /v1/events?vault_id=1:0xeff0ae5b39271b33f448cd408b51dc8aa72a672b`.

Use **transactions** for user-facing activity and confirmations. Use **events** for monitoring, reconciliation, and reporting.

### Trend Activity Over Time

```typescript API theme={null}
const params = new URLSearchParams({
  field: 'amount',
  agg: 'sum',
  grain: 'day',
  type: 'deposit',
  limit: '30',
})

const { data: points } = await fetch(
  `${API_BASE_URL}/v1/events/timeseries?${params}`,
  { headers: { Authorization: `Bearer ${API_KEY}` } },
).then(r => r.json())
// returns:
// [
//   { timestamp: "2026-03-01", value: "1500000" },
//   { timestamp: "2026-03-02", value: "1200000" },
//   ...
// ]
```

### Monitoring Options

| Approach                  | Best for                                                    |
| ------------------------- | ----------------------------------------------------------- |
| **API**                   | Product analytics, reporting, reconciliation — fastest path |
| **Developer Portal**      | Internal ops review and quick checks                        |
| **On-chain verification** | Trustless audit or custom indexers                          |

### On-Chain Verification

For trustless monitoring, read events directly from the gtUSDa vault on Base:

```typescript theme={null}
import { createPublicClient, http, parseAbiItem } from 'viem'
import { base } from 'viem/chains'

const client = createPublicClient({
  chain: base,
  transport: http(process.env.RPC_URL_BASE!),
})

const depositEvent = parseAbiItem(
  'event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares)'
)

const GTUSDA_VAULT = '0x000000000001CdB57E58Fa75Fe420a0f4D6640D5'

const logs = await client.getLogs({
  address: GTUSDA_VAULT,
  event: depositEvent,
  fromBlock: 'latest',
})
// returns:
// [
//   {
//     args: {
//       sender: "0x...",
//       assets: 1000000n,
//       shares: 968000000000000000000n
//     },
//     blockNumber: 12345678n,
//     transactionHash: "0x..."
//   }
// ]
```

## What's Next

<CardGroup cols={2}>
  <Card title="Attribution without SDK" icon="code" href="/attribution/attribution-without-sdk">
    Add attribution manually using Privy embedded wallets or wagmi.
  </Card>

  <Card title="SDK Reference" icon="book" href="/sdk/reference">
    Full result shape, type definitions, and error reference.
  </Card>

  <Card title="Deposit Your First Dollar" icon="arrow-right-arrow-left" href="/guides/developer/earn/deposits-and-withdrawals">
    SDK-based deposit and withdrawal flow using the Gauntlet SDK.
  </Card>

  <Card title="Deployed Vaults" icon="file-contract" href="/contract-reference/deployed-vaults">
    gtUSDa contract addresses for on-chain verification.
  </Card>
</CardGroup>
