Quickstart (Builders)
Get from zero to a signed, submitted sweep in under 15 minutes.
Prerequisites
- Node.js 22+, pnpm or npm
- A builder account + API key — self-serve at dashboard.sweepster.xyz
viem(for signing):npm install viem
Step 1 — Get a builder account
Self-serve signup is at dashboard.sweepster.xyz:
- Connect the wallet that will own your payout address.
- Sign in with SIWE (Sign-In With Ethereum).
- If your wallet isn't a builder yet, you'll get a "Create a builder account" form — pick a name.
- You receive your API key once (save it) and land in the dashboard.
No admin step is required. New builders start at zero commission (builderBps = 0); to earn a markup, contact Sweepster to raise your cap. The returned builder looks like:
{
"builder": {
"id": "bld_abc123",
"name": "Acme Wallet",
"builderBps": 0,
"maxBuilderBps": 0,
"payoutAddress": "0xYourPayoutAddress"
},
"apiKey": "sk_live_..."
}Store the API key securely. It is shown only once. You can rotate it from the dashboard (the new key is also shown once). See the Builder Dashboard guide.
Step 2 — Request a quote
// POST https://api.sweepster.xyz/quote
const response = await fetch("https://api.sweepster.xyz/quote", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
owner: "0xUserWalletAddress",
tokenIn: "0xTokenAddressOnSourceChain",
amountIn: "1000000", // in token's smallest unit (e.g. 1 USDC = 1000000)
tokenOut: "0xTokenAddressOnDestChain",
destination: "0xDestinationWallet",
destChainId: 42161, // Arbitrum
tier: "tier1",
subscriptionActive: false,
userId: "user_unique_id",
apiKey: "sk_live_...", // your builder API key (optional — enables attribution)
}),
});
const { quote, order } = await response.json();
console.log("Quote expires at:", new Date(quote.expiresAtMs));
console.log("Total fees:", quote.total, "in token units");Step 3 — Sign two things off-chain (EIP-7702, gasless)
The gasless sweep needs the user to sign two off-chain messages — no gas, no approval, no allowance. See the Signing guide for buildDelegateTypedData.
import { createWalletClient, custom } from "viem";
import { base } from "viem/chains";
import { buildDelegateTypedData } from "./delegate"; // see Signing guide
const walletClient = createWalletClient({ chain: base, transport: custom(window.ethereum) });
const chainId = 8453; // source chain (Base)
// 1. EIP-712 signTypedData the SweepOrder (becomes the `bytes signature`)
const signature = await walletClient.signTypedData({
account: order.owner,
...buildDelegateTypedData(order, chainId),
});
// 2. Sign the EIP-7702 authorization delegating the EOA to the SweepDelegate impl
const signedAuth = await walletClient.signAuthorization({
account: walletClient.account,
contractAddress: quote.settlementAddress, // per-chain SweepDelegate impl
chainId,
});
const authorization = {
address: signedAuth.address,
chainId: signedAuth.chainId,
nonce: signedAuth.nonce,
r: signedAuth.r,
s: signedAuth.s,
yParity: signedAuth.yParity ?? 0,
};Step 4 — Submit
Submit the quote id, the order-digest signature, and the EIP-7702 authorization. The relayer (Kryard) broadcasts the type-4 set-code transaction and pays the gas.
// POST https://api.sweepster.xyz/intents
const submitRes = await fetch("https://api.sweepster.xyz/intents", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ quoteId: quote.id, signature, authorization }),
});
const intent = await submitRes.json();
console.log("Intent ID:", intent.id, "Status:", intent.status);The
authorizationis required —POST /intentsreturns422without it. There is no Permit2 fallback.
Step 5 — Poll status
// GET https://api.sweepster.xyz/intents/:id
async function pollIntent(id: string) {
const TERMINAL = ["delivered", "failed"];
while (true) {
const res = await fetch(`https://api.sweepster.xyz/intents/${id}`);
const intent = await res.json();
console.log(intent.status, intent.txHash);
if (TERMINAL.includes(intent.status)) break;
await new Promise((r) => setTimeout(r, 3000));
}
}
await pollIntent(intent.id);