Quickstart
This walks the whole path once: create an MPC vault, derive a wallet, fund it on a testnet, send value, and watch it confirm. Everything here runs on the sandbox, which is testnet-only — no real value moves.
Before you start
Section titled “Before you start”- An API key seed for the sandbox. You receive your first key at onboarding; from there you can mint more (see Authentication).
- Node 18+ and the SDK:
npm install @xkova/mpcKeep the seed in an environment variable — it is the secret that authorizes every request.
export XKOVA_API_SEED=<your 32-byte seed, hex>The five calls
Section titled “The five calls”import { XkovaMpcClient } from "@xkova/mpc";
const xkova = new XkovaMpcClient({ baseUrl: "https://api.mpc-dev.xkova.com", seedHex: process.env.XKOVA_API_SEED!,});
// 1. Create a vault — an MPC key held as shares. Returns as `creating`.const vault = await xkova.createVault({ tier: "self", name: "treasury" });
// 2. Key generation is asynchronous. Wait for `active`.let v = vault;while (v.status === "creating") { await new Promise((r) => setTimeout(r, 1000)); v = await xkova.getVault(vault.id);}
// 3. Derive an EVM wallet under the vault (instant).const wallet = await xkova.createWallet(vault.id, { chain: "avalanche_c" });console.log("Fund this address on Fuji:", wallet.address);
// 4. Send native value. Returns a Transaction in `created`.const tx = await xkova.sendNative({ wallet, chainId: 43113, // Avalanche Fuji to: "0x000000000000000000000000000000000000dEaD", amount: "5000000000000000", // 0.005 AVAX, in wei idempotencyKey: "quickstart-001",});
// 5. Poll to a terminal state (or use webhooks instead).let t = tx;const done = ["confirmed", "final", "failed", "rejected"];while (!done.includes(t.state)) { await new Promise((r) => setTimeout(r, 2000)); t = await xkova.getTransaction(tx.id);}console.log(t.state, t.chain_tx_hash);Between step 3 and step 4, send some test AVAX to the printed address from the Avalanche Fuji faucet. The send in step 4 will stay in early states until the wallet is funded.
What just happened
Section titled “What just happened”- No private key was ever assembled. The vault’s key exists only as shares; the signature in step 4 was computed jointly. See How it works.
- You authorized an exact transaction.
sendNativebuilt a canonical intent, signed it with your API key, and submitted it — so the recipient and amount are locked to what you approved. - The send was asynchronous. Step 4 returned a
createdtransaction; it reachedbroadcastand thenconfirmedon its own timeline.
- Authentication — how request signing works, and how to mint and revoke keys.
- Send on EVM — native, ERC-20/721/1155, and raw contract calls.
- Webhooks — get told when a transaction settles instead of polling.
- Go to production — moving off the sandbox.