Skip to content

Getting started ​

Two paths, same library: install the package and call the product API, or install the binary and type commands. Most teams do both — the CLI is the fastest way to see what a call will do before you automate it.

Install ​

The package is published to GitHub Packages, a registry scoped to Swarm-AI-Labs. Point the scope at it and install by version:

ini
# .npmrc
@swarm-ai-labs:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
sh
bun add @swarm-ai-labs/turnkey-extensions
# or: npm i @swarm-ai-labs/turnkey-extensions

GITHUB_TOKEN needs the read:packages scope. In GitHub Actions the built-in secrets.GITHUB_TOKEN already has it — no PAT required.

The package is ESM-only and unbundled: dist/ mirrors src/ one file per module, so your bundler tree-shakes at module granularity. Chain SDKs are optional peer dependencies — importing /hyperliquid never pulls in TON, Sui or NEAR.

Import the subpath, not the root barrel

import { … } from "@swarm-ai-labs/turnkey-extensions" re-exports every chain, so one symbol drags the rest into your graph. The product API lives at /runtime; everything else has its own subpath.

Who signs ​

Every write needs an identity: one primitive (signRawPayload) from which the viem account, the EIP-712 signer and the address book are all derived. Pick the backend that matches where your code runs.

ts
import { turnkeyApiKeyIdentity } from "@swarm-ai-labs/turnkey-extensions/runtime";

const identity = turnkeyApiKeyIdentity({
  apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY!,
  apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY!,
  organizationId: process.env.TURNKEY_ORG_ID!,
});
ts
import {
  otpLogin,
  turnkeySessionIdentity,
} from "@swarm-ai-labs/turnkey-extensions/runtime";

const session = await otpLogin({
  initiator,
  email: "you@example.com",
  promptCode: async () => askTheUserForTheCode(),
});
const identity = turnkeySessionIdentity(session);
ts
import { turnkeyKitIdentity } from "@swarm-ai-labs/turnkey-extensions/runtime";

// `client` is the @turnkey/react-wallet-kit client.
const identity = turnkeyKitIdentity(client, organizationId);
ts
import { turnkeyBinaryIdentity } from "@swarm-ai-labs/turnkey-extensions/runtime/node";

const identity = turnkeyBinaryIdentity({ keyName: "default" });

Your first calls ​

ts
import { createSwarm } from "@swarm-ai-labs/turnkey-extensions/runtime";

const swarm = createSwarm({
  identity,
  policy: { capUsd: 500, limits: { maxLeverage: 5 } },
});

// Reads: no key is touched.
const holdings = await swarm.portfolio.holdings({ view: { hideZero: true } });
console.log(holdings.totalUsd);

// Writes: plan first. This signs nothing.
const preview = await swarm.perps.open({
  coin: "ETH",
  side: "buy",
  notionalUsd: 250,
});
console.log(preview.plan.steps, preview.data.plan.liquidationPx);

// The same call, for real.
const placed = await swarm.perps.open({
  coin: "ETH",
  side: "buy",
  notionalUsd: 250,
  mode: "live",
});

mode defaults to "plan" on every operation that can move money. A preview and a receipt come back in the same shape, so one renderer handles both. Read the execution contract before the first "live".

Configure endpoints ​

Every RPC and API endpoint is read through getConfig(), with mainnet defaults baked in — the package works zero-config. Override once at startup:

ts
import { configure } from "@swarm-ai-labs/turnkey-extensions/config";

configure({
  rpc: {
    sol: process.env.SOL_RPC_URL,
    evm: { 1: process.env.ETH_RPC_URL },
  },
  // Empty ⇒ same-origin proxy paths (`/api/…`) — a browser only. Off the
  // browser there is no origin to be relative to, so an empty inventory base
  // is refused by name rather than attempted; set it to call upstreams directly.
  apiBases: { inventory: "/api/inventory", indexer: "" },
  prices: { indexerType: "custom" }, // "public" opts out to CoinGecko only
});

Or use the CLI ​

sh
npm i -g @swarm-ai-labs/turnkey-extensions

swarm login --email you@example.com   # email OTP into a Turnkey sub-org
swarm holdings                        # the whole wallet, valued
swarm positions                       # every venue, one table
swarm market hyperliquid buy --coin ETH --notional 250   # preview only

Writes are dry runs until --confirm, and --confirm is refused without a SWARM_BUDGET_USD cap:

sh
SWARM_BUDGET_USD=500 swarm market hyperliquid buy --coin ETH --notional 250 --confirm

The full command list, the safety model and the flags are in the CLI reference.

Where to go next ​

Released under the MIT License.