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
bash
npm i @kryard/sdk viembash
# add to .npmrc first:
# @kryard:registry=https://npm.pkg.github.com
# //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
npm i @kryard/sdk viemINFO
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 — let users settle gas in an ERC-20.
- Custom delegate — use your own 7702 delegate via
sponsorCall.