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

# EIP-3009 Signing Reference

> Full reference for signEip3009Authorization and the underlying EIP-712 TransferWithAuthorization type.

`signEip3009Authorization` builds and signs a real [EIP-3009](https://eips.ethereum.org/EIPS/eip-3009) `TransferWithAuthorization` payload — ready to send as the `eip3009` scheme's `paymentPayload` to `/verify` or `/settle`, or to hand a merchant directly as an `X-PAYMENT` header.

<Warning>
  This performs a genuine EIP-712 signature. There is no mock mode — signing is pure local cryptography with no network dependency, so it works offline and never touches XentFi's servers.
</Warning>

## Signature

```ts theme={null}
function signEip3009Authorization(
  params: SignExactAuthorizationParams
): Promise<Eip3009SchemePayload>;
```

### Parameters

| Parameter         | Type                 | Required | Description                                                                                                                                   |
| ----------------- | -------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `account`         | `LocalAccount`       | ✅        | Any [viem](https://viem.sh) local account that implements `signTypedData` — from `privateKeyToAccount`, a hardware wallet adapter, etc.       |
| `to`              | `Address`            | ✅        | Recipient address (the merchant's `payTo`).                                                                                                   |
| `amount`          | `string`             | ✅        | Amount in the token's own human-readable units, e.g. `"2.50"` — converted to base units using `domain.tokenDecimals`.                         |
| `domain`          | `Eip3009TokenDomain` | ✅        | The token's real EIP-712 domain — see below.                                                                                                  |
| `validitySeconds` | `number`             | optional | How long the authorization stays valid for, in seconds from now. Default `300` (5 minutes).                                                   |
| `nonce`           | `Hex`                | optional | Supply your own bytes32 nonce for deterministic/idempotent authorizations; otherwise a random one is generated with `crypto.getRandomValues`. |

### `Eip3009TokenDomain`

```ts theme={null}
interface Eip3009TokenDomain {
  chainId: number;
  tokenAddress: Address;
  tokenName: string;
  tokenVersion: string;
  tokenDecimals: number;
}
```

### Returns — `Eip3009SchemePayload`

```ts theme={null}
interface Eip3009SchemePayload {
  scheme: "eip3009";
  from: Address;
  to: Address;
  value: string;        // token base units, as a decimal string
  validAfter: string;   // unix seconds
  validBefore: string;  // unix seconds
  nonce: Hex;            // bytes32
  signature: Hex;
}
```

## The underlying EIP-712 type

```ts theme={null}
const TRANSFER_WITH_AUTHORIZATION_TYPES = {
  TransferWithAuthorization: [
    { name: "from", type: "address" },
    { name: "to", type: "address" },
    { name: "value", type: "uint256" },
    { name: "validAfter", type: "uint256" },
    { name: "validBefore", type: "uint256" },
    { name: "nonce", type: "bytes32" },
  ],
} as const;
```

`buildEip3009Domain(token: Eip3009TokenDomain)` builds the matching EIP-712 `domain` object (`{ name, version, chainId, verifyingContract }`) if you need to construct or verify a signature manually rather than through `signEip3009Authorization`.

## Example: custom nonce for idempotency

```ts theme={null}
const payload = await signEip3009Authorization({
  account,
  to: "0xMerchantWalletAddress",
  amount: "2.50",
  domain: {
    chainId: 8453,
    tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    tokenName: "USD Coin",
    tokenVersion: "2",
    tokenDecimals: 6,
  },
  nonce: "0x0000000000000000000000000000000000000000000000000000000000000001",
});
```

<Tip>
  A deterministic `nonce` (derived from your own request/order ID, for example) lets you safely retry signing the *same* logical payment without risking a double-spend — the contract rejects a reused nonce for the same signer.
</Tip>

## Security notes

* `validBefore` is set from `validitySeconds` (default 5 minutes) — keep this short. A long-lived signed authorization is a bearer instrument until it either expires or is consumed.
* `validAfter` is always `0` in the current implementation (immediately valid).
* The signature never leaves the caller's process during signing — only the final `Eip3009SchemePayload` (which includes the signature, not the private key) is transmitted anywhere.

## Next steps

<CardGroup cols={2}>
  <Card title="Payer Guide" icon="bot" href="/x402/payer">
    See this used in a full 402 round trip.
  </Card>

  <Card title="API Reference" icon="code" href="/x402/api-reference">
    `X402FacilitatorClient` and the rest of the type surface.
  </Card>
</CardGroup>
