Skip to content

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.

  • 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:
Terminal window
npm install @xkova/mpc

Keep the seed in an environment variable — it is the secret that authorizes every request.

Terminal window
export XKOVA_API_SEED=<your 32-byte seed, hex>
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.

  • 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. sendNative built 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 created transaction; it reached broadcast and then confirmed on 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.