# Quickstart

Sponsor a gasless batch in a few lines. You need a Kryard **organization id** and an
**API key** (public + private), plus the relayer's `signWith` key id and a deployed
`KryardDelegate` address for your chain.

## Install

::: code-group

```bash [npm]
npm i @kryard/sdk viem
```

```bash [GitHub Packages]
# add to .npmrc first:
#   @kryard:registry=https://npm.pkg.github.com
#   //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
npm i @kryard/sdk viem
```

:::

::: info
The X-Stamp signer ships built-in (MIT, `@noble`-based) — no external SDK required.
`viem` is a peer dependency.
:::

## Sponsor a batch

### 1. Create the relay client

The relayer org's API key stamps each request.

```ts
import { KryardRelayClient, createApiKeyStamper } from "@kryard/sdk";

const client = new KryardRelayClient({
  baseUrl: "https://api.kryard.com",
  organizationId: process.env.KRYARD_ORG!,
  stamper: createApiKeyStamper({
    apiPublicKey: process.env.KRYARD_API_PUBLIC_KEY!,
    apiPrivateKey: process.env.KRYARD_API_PRIVATE_KEY!,
  }),
});
```

### 2. Adapt the user's wallet

Implement the `UserSigner` interface over the user's wallet.

```ts
import { createWalletClient, http, type Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
import type { UserSigner } from "@kryard/sdk";

const account = privateKeyToAccount(process.env.USER_PK as Hex);
const wallet = createWalletClient({ account, chain: sepolia, transport: http() });

const signer: UserSigner = {
  address: account.address,
  signDigest: (digest) => account.signMessage({ message: { raw: digest } }),
  async signAuthorization({ contractAddress, chainId }) {
    const a = await wallet.signAuthorization({ account, contractAddress, chainId });
    return { address: a.address, chainId: a.chainId, nonce: a.nonce, r: a.r, s: a.s, yParity: a.yParity ?? 0 };
  },
};
```

### 3. Sponsor the batch

Gasless for the user.

```ts
import { sponsorExecute, type Call } from "@kryard/sdk";

const calls: Call[] = [{ to: TOKEN, value: 0n, data: transferCalldata }];

const tx = await sponsorExecute({
  client, signer,
  chainId: 11155111,                 // Sepolia
  signWith: process.env.KRYARD_SIGN_WITH!,
  delegateAddress: KRYARD_DELEGATE,  // deployed KryardDelegate on this chain
  calls,
  nonce: BigInt(Date.now()),         // single-use delegate nonce
});
console.log(tx.id, tx.txHash);
```

### 4. Poll to completion

```ts
let status = tx;
while (!["confirmed", "failed", "expired"].includes(status.status)) {
  await new Promise((r) => setTimeout(r, 4000));
  status = await client.get(tx.id);
}
```

## Next steps

- [Pay gas in any token](/relay/erc20-gas) — let users settle gas in an ERC-20.
- [Custom delegate](/relay/sponsor-call) — use your own 7702 delegate via `sponsorCall`.
