@chipi-stack/backend
v14.13.0
Published
Server SDK for gasless Starknet wallets — wallet provisioning, payments, SKU purchases, and crypto remittances
Readme
@chipi-stack/backend
Server-side SDK for Chipi Pay. Handles wallet creation, transactions, SKU purchases, and exchanges.
Install
npm install @chipi-stack/backendQuick Start
import { ChipiSDK } from "@chipi-stack/backend";
const sdk = new ChipiSDK({
apiPublicKey: process.env.CHIPI_API_PUBLIC_KEY!,
apiSecretKey: process.env.CHIPI_API_SECRET_KEY!,
});
const bearerToken = "your-bearer-token"; // From your auth provider (e.g., Clerk)
// Create a wallet
const wallet = await sdk.createWallet({
params: {
externalUserId: "user-123",
chain: "STARKNET",
encryptKey: "user-pin-or-passkey",
},
bearerToken,
});
// Transfer USDC
const tx = await sdk.transfer({
params: {
wallet: wallet.wallet,
token: "USDC",
recipient: "0x...",
amount: 10,
encryptKey: "user-pin-or-passkey",
},
bearerToken,
});Confirming a transaction
Every gasless write returns a transaction hash and nothing else, so
waitForTransaction answers the two questions that follow: did it succeed, and
what did it emit.
import { waitForTransaction } from "@chipi-stack/backend";
const receipt = await waitForTransaction(tx);
if (!receipt.success) {
throw new Error(receipt.revertReason ?? "reverted on chain");
}
// Raw events, decode against your own ABI.
const transferred = receipt.events.filter((e) => e.from_address === USDC);A revert comes back as a result (success: false plus revertReason), not
a throw, because a revert is a normal outcome you branch on. Only "we do not
know yet" throws, meaning a timeout or transport failure, where retrying is the
correct response.
Options: nodeUrl, retryIntervalMs (default 3000) and timeoutMs
(default 300000). nodeUrl is your preferred endpoint rather than the only one
tried, since reading a receipt is idempotent and falls through the RPC chain.
Treasuries
sdk.treasury drives a SHHH multisig from your own server. All three below need
a sk_, so keep them server-side.
// Discover a treasury instead of pinning its id in an env var.
const { items } = await sdk.treasury.list();
const ops = items.find((t) => t.name === "Ops Treasury");
// Require more signatures to borrow than to repay.
await sdk.treasury.setPolicy(ops.id, { sensitiveQuorum: 3 });
const policy = await sdk.treasury.getPolicy(ops.id);
// A transport bound to one treasury + owner, wireable into chipi-react's hooks.
const transport = sdk.treasury.forTreasury({ treasuryId: ops.id, ownerPubkey });A quorum can only raise requiredApprovals above the wallet's on-chain
threshold. The chain is the hard floor, so a quorum below it produces proposals
that reach approved and then revert at execute.
What you can ship
- Wallet-as-a-service APIs — provision and manage wallets for your users from your backend
- SKU marketplace (airtime, bill pay, gift cards) — integrate real-world purchases with crypto rails
- Crypto remittance backends — build cross-border payment services with stablecoin settlement
- Gasless payment processing for fintechs — accept and send USDC without your users paying gas
Have an idea? Tell us what you want to build
Documentation
Full docs at docs.chipipay.com
License
MIT
