Skip to content

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 viem
bash
# 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.

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

Wallet infrastructure for gasless, sponsored transactions — a Turnkey-compatible signer and a managed EIP-7702 relay.