Skip to content

Capabilities Reference — @swarm-ai-labs/turnkey-extensions

Every public capability of the package, grouped by subpath export. These are the building blocks. If you are looking for "how do I read my portfolio" rather than "which function reads a TON jetton balance", start with the product API in SDK.md — or, at the terminal, CLI.md.

For design rationale see ARCHITECTURE.md; for runnable snippets see examples/.

Chain coverage: EVM (any chain id; Ethereum, Base, Arbitrum, Optimism, BSC, Polygon, Avalanche, … via the catalog), Bitcoin, Solana, TRON, TON, Sui, NEAR. Integrations: Turnkey (signing), Hyperliquid (perps), Polymarket (prediction markets), Sparkling Inventory/Indexer, Aurora Intents swap widget, NEAR Intents (1Click), Uniswap v3, gas.zip, LI.FI, CoinGecko, 0G Compute.

Module map

SubpathCapability
. (root)Barrel of everything below except react, polymarket, prices, zgcompute, holdings, adi
./configEndpoint/runtime configuration (configure / getConfig)
./typesShared chain & wallet types
./formatCurrency / percent / address formatting
./validatePer-network recipient address validation
./catalogEVM network catalog, swap-token lists, explorer & logo URL builders
./signersTurnkey signer adapters (EIP-1193, Solana, NEAR derivation, EVM tx prep)
./sendersNative-coin send flows per chain (prepare → confirm)
./balancesMulti-chain native + token balance reads with cache/retry
./pricesMerged price layer (Sparkling Indexer → CoinGecko fallback)
./holdingsPortfolio valuation (computeHoldingsTotals, 24h delta) + list view (applyHoldingsView)
./adiADI PredictStreet: markets, book, orders (place/cancel/open), vault deposit/withdraw, balances
./hyperliquidPerps: market data, positions, order planning + placement, TP/SL, leverage, isolated margin, dead-man switch, book-walk pricing, WebSocket feeds, Arbitrum USDC bridge, withdrawals
./polymarketCLOB client, L1/L2 auth, orders, Safe proxy + relayer, market data
./inventorySparkling inventory client (tokens, pairs, chains, deployments)
./indexerTicker search, price graph, wallet summary, portfolio total, balances
./swapSwap providers (1Click, Uniswap v3, gas.zip, LI.FI) + Aurora swap-widget bridge + NEAR Intents (NEP-413) signing
./activityMulti-chain on-chain activity feed with opaque cursors
./zgcompute0G Compute broker + TEE-verifiable chat over a Turnkey wallet
./signalsEnvy AI signals: live feed, SSE transitions, strategy catalogue + rules, equity curves, presentation labels
./venueOne position/order model across Hyperliquid, Polymarket and ADI; failure-isolating sweep; rebalance planning + route journal
./executionOrder slicing (TWAP/ladder/iceberg) with derived client order ids, a resumable journal, a client-side trailing stop
./strategyDeclarative recipe schema, shared firing logic, backtest over historical closes
./alertsCondition grammar, edge-triggered firing with cooldown, live metric reader, delivery channels
./riskStanding limits that outlive one invocation (daily loss, order notional, leverage, withdrawal whitelist)
./paperPaper trading ledger: fill application, book replay, mark-to-market
./screenScreeners: perp funding (annualised) and prediction-market price inconsistency
./cowCoW Protocol limit orders: EIP-712 order building, integer price maths, order-book client
./cexBinance USD-M futures as a VenueAdapter; HMAC-SHA256 request signing over Web Crypto
./evmeth_call revert check and an anvil-forked transaction simulation
./walletBatch payout parsing, ERC-20 allowance model, stuck-transaction replacement maths
./chartTerminal line charts, sparklines, time-axis labels
./progressTxProgress — the live status contract every write path reports through
./runtimeThe product API — createSwarm, markets, identity, store, policy, operations (see SDK.md)
./runtime/nodefsStore(), turnkeyBinaryIdentity() — the parts needing node:fs / node:child_process
./reactReact hooks/providers (accounts, Hyperliquid, search, price graph)

./config — configuration

Every RPC/API endpoint in the library is read through getConfig(). Mainnet defaults are baked in, so the package works zero-config; override once at app startup.

  • configure(partial) — deep-merge a partial config; trailing slashes are normalized; safe to call repeatedly to layer overrides.
  • getConfig() — the active TurnkeyExtensionsConfig.
  • resetConfig() — restore baked-in defaults (tests).
  • Types: TurnkeyExtensionsConfig, RpcConfig, ApiBasesConfig, PricesModeConfig, DeepPartial.

Configurable endpoints and their defaults:

KeyDefaultUsed by
rpc.solSolana mainnet-betabalances, senders, activity
rpc.nearfree.rpc.fastnear.combalances, senders
rpc.tronapi.trongrid.iobalances, senders, activity
rpc.tonV2 / rpc.tonV3toncenter v2 / v3balances, senders, activity
rpc.suiSui mainnet full nodebalances, senders, activity
rpc.btcMempoolmempool.space/apibalances, senders, activity
rpc.evm[chainId]per-chain override → catalog fallbackeverything EVM
apiBases.inventorySparkling inventory stage hostinventory
apiBases.indexer"" (same-origin proxy)indexer search/price-graph
apiBases.coingeckoCoinGecko simple APIprices
apiBases.customIndexerSparkling Indexer stage hostprices, indexer balances/summary
apiBases.nearblocksapi.nearblocks.io/v1NEAR activity
prices.indexerType"custom" ("public" = CoinGecko-only)prices

./types — shared types

  • DepositChainId — deposit/withdraw chain slug ("ethereum", "solana", …).
  • ChainKey — canonical signable chains: ethereum | bitcoin | solana | tron | ton | sui.
  • WalletAccount — re-export of the Turnkey kit type (type-only, erased at build).
  • EvmCaip2 — CAIP-2 ids accepted by Turnkey's EthTransaction.

Chain helpers (root export)

From src/chains.ts, exported via the root barrel:

  • EVM_CHAIN_IDS — deposit-chain slug → EVM chain id map.
  • isEvmNetwork(network) — whether the slug is an EVM chain.
  • nativeSymbolForNetwork(network) / isNativeSymbolForNetwork(network, symbol) — native coin symbol resolution (incl. legacy GRAM/TON routing).
  • NATIVE_DECIMALS / nativeDecimals(network) — native coin decimals.
  • networkLabelFor(network) — human-readable chain label.

(src/cache.ts's createPromiseCache is internal — it backs the inventory client's caches but is not part of the public surface.)

./format — formatting

  • formatUsd(value, opts?) — USD amount formatting.
  • formatUsdPrice(value) — price formatting (small-price precision).
  • formatCompactUsd(value) — compact $1.2M-style output.
  • splitCurrency(value) — split into integer/fraction parts for styled UIs.
  • formatSignedPercent(value) — signed percent label.
  • signColor(value) + POSITIVE_COLOR / NEGATIVE_COLOR — up/down coloring.
  • formatAddress(address) — middle-truncated address.
  • setActiveCurrencyProvider(fn) / ActiveCurrency — plug in a non-USD display currency (rate + symbol) that all formatters honor.

./validate — address validation

  • isValidAddressForNetwork(network, address) — pragmatic per-network shape check catching "wrong format / wrong network" mistakes:
    • EVM: viem.isAddress (checksum not required)
    • Bitcoin: legacy/P2SH base58 + bech32 bc1…
    • Solana: base58, 32–44 chars
    • TRON: T + 33 base58check chars
    • TON: user-friendly (EQ/UQ/kQ/0Q + base64url) or raw wc:hex
    • Sui: 0x + 64 hex
    • NEAR: named account or 64-hex implicit
    • Unknown chains pass (don't block a potentially valid send).

./catalog — network & token catalog

EVM networks (cryptoNetworks.ts):

  • POPULAR_EVM_NETWORKS / EvmNetworkDefinition — curated EVM network list (chain id, name, RPC, explorer, logo…). DEFAULT_EVM_CHAIN_ID.
  • findEvmNetwork(chainId) — catalog lookup.
  • isEvmTestnetChain(chainId) — testnet detection.
  • getDefaultEthRpcUrlForChain(chainId) / getDefaultEthRpcUrl(chainId) — RPC resolution (config override → catalog).
  • explorerTxUrlEthereum(chainId, txHash) / explorerTxUrlForKind(...) — explorer deep links.
  • buildTrustWalletLogoUrl(chainKey) / buildTrustWalletTokenLogoUrl(chainKey, contract) — TrustWallet asset-repo logo URLs; getNetworkLogoMetaFromCatalog(...) / NetworkLogoMeta — chain logo metadata.
  • getDefaultSolRpcUrl(useDevnet) / getBtcMempoolApiBase(useTestnet) — config-aware non-EVM endpoint helpers.

Swap tokens (evmSwapTokens.ts):

  • swapTokensForEvmChain(chainId) / currentWalletSwapTokens(chainId) — per-chain swappable token lists (EvmSwapToken).
  • wethAddressForEvmChain(chainId) — wrapped-native address.
  • SEPOLIA_USDC_ADDRESS / SEPOLIA_USDC_DECIMALS — testnet USDC constants.

./signers — Turnkey signer adapters

  • TurnkeySigning — structural interface over the Turnkey kit client (type-only import; any compatible client works — no runtime kit dependency).
  • createTurnkeyEip1193Provider({...})Eip1193Like — EVM EIP-1193 provider backed by Turnkey signing (works with viem/ethers/widget stacks).
  • createTurnkeySolanaProvider({...}) — Solana wallet-adapter-style provider over Turnkey (CreateTurnkeySolanaProviderInput).
  • nearImplicitFromSolanaAddress(addr) / nearPublicKeyFromSolanaAddress(addr) — NEAR implicit account + ed25519 public key derived from the Solana (ed25519) Turnkey address.
  • prepareTurnkeyEthSendTransaction(input) / prepareTurnkeyEvmTransaction(input) — build an EVM transaction (gas, nonce, fees) and return a prepared object whose confirm step signs & broadcasts via Turnkey (PreparedTurnkeyEthSend, PreparedTurnkeyEvmTransaction).
  • sendEvmContractCall({account, chainId, to, data, value?})EvmSendResult — prepare, sign and broadcast one contract call; the sender is account.address. Throws EvmBroadcastError when the RPC refuses it. waitForEvmReceipt(chainId, txHash) waits for it to be mined, and viemChainFor(chainId) resolves the chain both use.
  • turnkeyViemAccountFor({client, organizationId, address})LocalAccount — a viem account backed by Turnkey, built synchronously from a known address (no round-trip, unlike createAccount).

./senders — native-coin sending

Uniform two-phase send across all supported chains:

ts
const sender = senderForNetwork(network); // null if unsupported
const prepared = await sender.prepare(input); // fees estimated, tx built
const { txHash } = await prepared.confirm(); // signed via Turnkey + broadcast
  • senderForNetwork(network) — factory: all EVM slugs share evmSender; non-EVM slugs map to their sender.
  • Concrete senders: evmSender, solanaSender, bitcoinSender, tronSender, tonSender, nearSender, suiSender.
  • Contract types: NetworkSender, SendInput (account, toAddress, amount, symbol, network, Turnkey client…), PreparedSend, SendResult, AccountChain, TurnkeySigning, HandleSendTransactionParams.
  • Shared utils: toBaseUnits / fromBaseUnits (decimal ↔ base units per network), explorerTxUrl(network, txHash), accountAddress(account), ed25519SignatureBytes(sig), strip0x(v), plus config-aware endpoint getters (solRpcUrl, btcMempoolApi, nearRpcUrl, tronApiBase, tonCenterApi, suiRpcUrl).

./balances — balances & legacy prices

All reads are cached (BALANCE_TTL_MS) and retried; EVM/SOL reads try the Sparkling Indexer first (one shared /v1/balance call per chain) and fall back to raw RPC.

Native balances:

  • fetchEvmNativeAmount(chainId, address) — any EVM chain.
  • fetchBtcAmount(address) — via mempool.space.
  • fetchSolAmount(address) · fetchNearAmount(accountId) · fetchTronAmount(address) · fetchTonAmount(address) · fetchSuiAmount(address).

Token balances:

  • fetchErc20Amount(chainId, contract, decimals, address) — ERC-20.
  • fetchTronTokenAmount(...) — TRC-20 (constant-call balanceOf).
  • fetchNearTokenAmount(...) — NEP-141 (ft_balance_of).
  • fetchTonTokenAmount(master, decimals, owner) — TON jettons (toncenter v3).
  • fetchSuiTokenAmount(coinType, decimals, owner) — Sui coins.

Cache & plumbing:

  • clearBalanceCache() — drop all cached balances (incl. the indexer cache); pull-to-refresh / post-swap.
  • fetchWithRetry, rpc, cachedBalance, weiToNumber, BALANCE_TTL_MS — reusable low-level helpers.

Pair resolution & portfolio:

  • resolvePairs(pairs, addresses, { testnet? }) — resolve chain:SYMBOL pairs against the inventory into ResolvedPairs (namespace, decimals, deployment). fetchBalancesForPairs(pairs, addresses, { testnet? }) reads + prices them into a PortfolioResult; readAmount(pair) reads a single pre-resolved pair (the routing every fetcher shares — reuse it for a fixed portfolio scan).
  • parsePairs, PairSyntaxError, UnknownPairError, resolveTokenAlias, TOKEN_ALIASES, isContractAddress.

Chain overlay (chains the mainnet inventory can't supply):

  • overlayChainsFor(testnet), hydrateOverlayChains(chains), testnetConfig(chainIds), TESTNET_CHAINS, ADI_MAINNET_CHAIN — a local registry giving ADI (chainId 36900) on every run and a testnet variant of every chain. In testnet mode resolvePairs resolves entirely from it, so adi:USDC and <chain>:<SYMBOL> --testnet read without an inventory entry.

Legacy price helper (kept for the source app):

  • fetchPricesForSymbols(symbols) + COINGECKO_IDS, PriceInfo — direct CoinGecko read. New code should prefer ./prices.

./holdings — portfolio valuation & view

Pure, headless layer above ./balances — no React, no network.

  • computeHoldingsTotals(resolved, prices) — value each { symbol, amount } against a PriceInfo map into HoldingsTotals: per-asset priceUsd/valueUsd /change24h, a totalUsd (settles to $0, never null, when unpriceable), and a totalUsd24hAgo for the 24h delta.
  • applyHoldingsView(assets, view) — network filter + zero-balance toggle + sort (balance | price | popular, either direction; unvalued assets sort last).
  • Types/const: HoldingsView, DEFAULT_HOLDINGS_VIEW, HoldingsSortKey, HoldingsSortDir, SortableHolding, HoldingAmountLike, ValuedHolding, HoldingsTotals.

./prices — merged price layer

Sparkling Indexer first, CoinGecko fallback, stablecoins defaulting to $1. Subpath-only (not in the root barrel — its COINGECKO_IDS/PriceInfo would clash with the legacy helpers in ./balances).

  • fetchPrices(symbols)PricesResponse — merged symbol→price map with 24h change (PriceInfo), per-provider result metadata (ProviderResult).
  • fetchTokenPrices(refs) — price by token coordinates (TokenPriceRef, chain + address) rather than symbol.
  • Providers, callable directly: fetchCoinGeckoPrices(symbols), fetchCustomPrices(symbols), fetchCustomPricesByAddress(coords) (TokenCoord).
  • Mode/config helpers: resolveIndexerType(), useCustomIndexer(), coingeckoBase(), customBase(), PRICES_REVALIDATE_SEC.
  • Data: COINGECKO_IDS, CUSTOM_PRICE_TOKENS (CustomToken), STABLECOINS, NATIVE_TOKEN_ADDRESS; types IndexerType, PriceMap.

./hyperliquid — perps

Clients (@nktkas/hyperliquid):

  • getHyperliquidTransport() / getHyperliquidInfo() — shared HTTP transport + info client.
  • getHyperliquidExchange(wallet) — exchange (trading) client over any abstract wallet (e.g. a Turnkey viem account).

Market data (perps.ts):

  • fetchPerpMarket(symbol)PerpMarket — metadata + live context (mark, funding, OI, leverage caps…).
  • fetchMidPrice(coin) — cheap poll for the live chart tip.
  • fetchCandleSeries(coin, range)CandleSeries; CHART_RANGES, CHART_RANGE_KEYS, ChartRangeKey; buildLiveLabels(timestamps).
  • Presentation: perpIconSrc(symbol), formatFunding, computeDayChange / formatDayChange (DayChange), formatFundingCountdown(nowMs).

Order math (orderMath.ts):

  • coinSizeFromUsd, roundPerpPx, marketPx, perpOrderSizingFromUsd (PerpOrderSizing), minUsdForPerpOrderNotional, ceilUsdToCents.
  • leverageLadder(maxLeverage) / nearestLadderValue.
  • positionMargin, liquidationPrice, estimateFee.
  • Constants: MIN_ORDER_USD, MARKET_MAX_SLIPPAGE.

Arbitrum USDC bridge (bridge.ts):

  • HL_BRIDGE2, ARBITRUM_USDC, ARBITRUM_CHAIN_ID, USDC_DECIMALS, MIN_DEPOSIT_USDC.
  • usdcToBaseUnits(amount), buildUsdcTransferData(...) — deposit tx calldata.
  • validateDepositAmount({...})DepositValidation.

Deposit execution (deposit.ts) — the composition around those pure helpers:

  • depositToHyperliquid({account, amountUsdc, walletUsdc?, waitForConfirmation?}){txHash, amountUsdc} — gas check, validation, send, wait. Refusals throw HyperliquidDepositError carrying a DepositFailureReason (no-gas | empty | below-min | insufficient) rather than a sentence, so the CLI and a UI word them for their own audience.
  • fetchArbitrumUsdc(address) → native USDC the wallet holds on Arbitrum.

Order context (context.ts):

  • fetchPerpOrderContext({address, asset, withBook?})PerpOrderContextResult — the five reads buildPerpOrderPlan needs, plus the derived current leverage, margin mode and other positions' maintenance margin. Returns the raw account and market alongside the context, because the close path reads the position rather than the context. An optional read that fails degrades to null; no live market throws PerpMarketUnavailableError.

Order responses:

  • interpretPerpOrderResponse(res)PerpOrderPlacement — normalize the exchange response (filled / resting / error).

./polymarket — prediction markets

Subpath-only (name collisions with other modules). Everything needed to trade the Polymarket CLOB from a Turnkey EVM wallet on Polygon:

  • Client: getPolymarketClobClient(input) (PolymarketClobClientInput), POLYMARKET_CLOB_HOST.
  • Collateral: orders settle in pUSD, not USDC.e — POLYMARKET_PUSD_ADDRESS, polymarketSettlementAddress(), fetchPredictionPusdBalance(owner). USDC.e remains the deposit asset (POLYMARKET_USDC_ADDRESS, polymarketCollateralAddress(), fetchPredictionUsdcBalance(owner)); it is wrapped into pUSD by the onramp. Also POLYMARKET_CHAIN_ID, POLYMARKET_USDC_DECIMALS.
  • Deposit Wallets (the only wallet type that can trade since 2026-05-04): deriveDepositWallet(signer), createDepositWallet(signer, opts) — deployed by the relayer on builder credentials alone, with no signature from the user — isDepositWalletDeployed(...), execDepositWalletBatch(...) (gasless batch), depositWalletBatchTypedData(...), buildDepositWalletApprovalCalls(), DEPOSIT_WALLET_FACTORY, DEPOSIT_WALLET_BEACON.
  • Deposit Wallet signing (ERC-7739 / POLY_1271): depositWalletOrderTypedData(...), wrapDepositWalletSignature(...), exchangeDomainSeparator(...), orderContentsHash(...), ORDER_TYPE_STRING, SIGNATURE_TYPE_DEPOSIT_WALLET.
  • Onramp: fetchDepositAddresses(wallet), fetchEvmDepositAddress(wallet), parseDepositAddresses(raw), BRIDGE_BASE — per-chain deposit addresses that convert incoming USDC/USDC.e into pUSD.
  • Account lifecycle — build on this, not on the pieces below:fetchPolymarketAccount({eoa, account}) → status + readiness verdict; onboardPolymarketAccount(ctx) (deploy + approvals, idempotent); fundPolymarketAccount({amountUsd, route}) with route: "bridge" | "uniswap"; wrapWalletCollateral(...); withdrawFromPolymarket({amountUsd, to, token}). Everything environment-specific is injected — signing as a viem LocalAccount, broadcasting as an EvmSender + EvmConfirmer, transports and builderCreds as options — so a CLI, a server and a browser share one implementation. Progress arrives via onStep (PolymarketStep).
  • Server proxy (a browser cannot reach the relayer, CLOB or bridge — all CORS-closed, and the relayer needs credentials that must not ship to a browser): forwardPolymarketRequest(config, request), plus the bound relayerProxy(creds), clobProxy(paths), bridgeProxy(builderCode?). RELAYER_PROXY_PATHS / BRIDGE_PROXY_PATHS are the allow-lists, and needsBuilderAuth(path) encodes which requests are signed — including that /v1/* signatures must cover the query string, which returns 401 otherwise.
  • Readiness: assessPolymarketReadiness(input) (pure) and fetchClobCollateral(account) — distinguishes "no wallet", "unfunded", "funded in the wrong token" and "the exchange cannot see it", which the CLOB's own error messages do not.
  • Protocol constants (clob.ts): CLOB_BASE, CTF_EXCHANGE_V2, NEG_RISK_EXCHANGE_V2, USDC, CONDITIONAL_TOKENS, exchange EIP-712 domain, exchangeFor(negRisk), roundingFor(tickSize).
  • Auth: clobAuthTypedData(...) + CLOB_AUTH_MESSAGE (L1 EIP-712 login), deriveClobCreds(...)ClobCreds (L2 API creds), hmacL2(...) (L2 request signing).
  • Orders: buildPolymarketOrder(args) (BuildOrderArgsPostOrder), ORDER_TYPES (EIP-712 order struct).
  • Safe (LEGACY proxy wallet — pre-2026-05-04 accounts; holds funds but the CLOB refuses its orders): deriveSafeAddress(...) + SAFE_FACTORY, SAFE_MULTISEND, SAFE_INIT_CODE_HASH; Safe tx plumbing — safeTxStructHash, splitAndPackSig, encodeMultisend, aggregateSafeTx (SafeInnerTx, OP_CALL, OP_DELEGATE_CALL).
  • Approvals: buildApprovalTxns() + USDC_SPENDERS, CTF_OPERATORS, PRIMARY_USDC_SPENDER, PRIMARY_CTF_OPERATOR.
  • Relayer (gasless Safe ops): isSafeDeployed(...), deploySafe(...), execSafeBatch(...), waitForRelayerTx(...) (RelayerOptions, WaitForRelayerTxOptions, PolymarketBuilderCreds, RELAYER_BASE).
  • Market data (Gamma API): fetchTopEvent(...), fetchOutcomeSeries(...), fetchLatestPrice(...), parseEvent(raw) (PmMarket, PmOutcome, OutcomeSeries, RawEvent, RawEventMarket); chart ranges CHART_RANGES, CHART_RANGE_KEYS, ChartRange, rangeToParams(...) (RangeParams); presentation formatProbability(price), formatCloses(endDate); GAMMA_BASE.
  • Transport: directTransport(base) (PolymarketTransport, PolymarketProxyRequest) — call upstreams directly or route through your own proxy.

./adi — ADI PredictStreet

Prediction markets with per-user on-chain vaults, an off-chain orderbook, and EIP-712-signed orders on ADI (chainId 36900). The partner API key never enters the package — pass creds (apiKey, userWallet) / a transport per call, the same injectable model as ./polymarket. Signing is caller-injected.

  • Environment: fetchAdiContracts() reads the live exchange/USDC addresses + chain id from the platform (never hardcode). ADI_CHAIN_ID, ADI_RPC_URL, ADI_TESTNET_API_BASE, adiChain (viem).
  • Market data (public): fetchAdiMarkets, fetchAdiMarket (by slug), fetchAdiOrderbook.
  • Orders: buildOrder (pure EIP-712 build; orderDomain, ORDER_EIP712_TYPES, computeOrderAmounts, parseUnits6, randomSalt, OrderSide, SignatureType) → placeAdiOrder(input, signTypedData). Lifecycle: cancelAdiOrder, cancelAdiOrders (≤100), cancelAllAdiOrders, fetchAdiOpenOrders, fetchAdiOrderHistory.
  • Portfolio: fetchAdiVault, fetchAdiPositions, fetchAdiBalances (spendable/unsettled/locked/quarantined per token).
  • Vault funds: depositToAdiVault({ account, … }) (approve + deposit). Withdrawals (dual-signed WithdrawERC20): buildWithdrawTypedData (pure) → withdrawFromAdiVault(params, signWithdraw), plus fetchAdiDepositSources (cleared destinations), fetchAdiWithdrawals, fetchAdiWithdrawal, fetchAdiWithdrawalFee, cancelAdiWithdrawal.
  • Errors: AdiError (carries the upstream reject code; a 2xx carrying a rejection still throws, so a refused order is never mistaken for a placed one).

./signals — Envy AI signals

Read-only client for the envy-stream proxy, the strategy engine behind the AI screens. A strategy is a set of entry/exit rules evaluated upstream on 15-minute candles; a firing rule becomes a signal. Envy executes nothing — acting on a signal is a Hyperliquid perp order the caller places (./hyperliquid).

The proxy holds the house subscription key server-side, so no credential leaves this package. It has no public host: apiBases.envyStream is "" by default (version segment included when set, e.g. https://envy-dev.edgetrad.ing/v1), and every call is a no-op returning null / [] until it is set — envyConfigured() reports which.

  • Feed: getSignals(limit = SIGNALS_LIMIT) — newest first across every owned strategy; 200 is the proxy's cap, a recent window of a durable history rather than "everything". describeSignal(strategyId, coin, rule) returns the one /describe rule that fired, with the coin's risk frame folded in.
  • Stream: streamSignals({ signal }) — an async generator of [event, payload] over SSE (snapshot, open, refresh, close; ping swallowed). The snapshot replays on every connect, so a consumer must be idempotent per signal id. Reconnect policy is the caller's; a socket quiet for STREAM_READ_TIMEOUT_MS (60s, against a 15s heartbeat) ends the generator. parseSseChunk is exported for callers driving their own transport.
  • Catalogue: listStrategies({ category, window, limit }) (ranked by PnL; category is a display label filtered client-side via inCategory, because upstream categories are comma-joined free text), getStrategy (falls back to a listing scan on 503 catalogue_incomplete), describeStrategy / describe, openPositions (the strategy's virtual book, not the user's), strategyCoinCount / strategyCoinCounts (capped at DESCRIBE_CONCURRENCY).
  • Equity: getEquityCurve, getEquity, equitySparks (first SPARK_ROWS rows only, SPARK_CONCURRENCY at a time — the key is shared app-wide and must not be spent on decoration).
  • Parsers: signalFromRow, signalsFromPayload, strategiesFromPayload, descriptionFromPayload, equityFromPayload — pure and defensive; a row missing id or coin is dropped rather than half-rendered.
  • Labels: signalSide, priceLabel (precision steps with magnitude, matching formatUsdPrice), signalFiredLabel, startedLabel, riskBand (grades on max drawdown; an unproven strategy grades High), strategySubtitle, axisLabels, allocationSharePct (upstream allocationPct is a budget slice, not a share — a single-coin strategy reports 250).
  • Acting on one: planSignalTrade({ signal, market, availableUsd, amountUsd }) is a pure function returning the whole trade ticket — side, the leverage clamp (strategy × coin × SIGNAL_MAX_LEVERAGE), the market order's protective limit and exact px/sz, the margin the position commits, and a single blocker (expirednot_tradableno_amountbelow_mininsufficient_margin) or ready. signalPerpOrderRequest(plan) hands a ready plan to ./hyperliquid's existing pipeline. Helpers: signalSideFor, formatCountdown, amountForPercent / percentForAmount.
    • below_min compares the notional the exchange will see after size flooring, never the typed amount, and minOrderUsd reports what to type instead (SPRK-529).
    • insufficient_margin compares amountUsd / leverage against the free collateral — what the exchange actually enforces.
    • There is deliberately no executeSignalTrade: submission belongs to the two paths that already exist, so a third cannot bypass the CLI's spend cap.
  • Caching: successful payloads for 120s, failures for 15s under a separate memo so a dead upstream is dialled once, not once per row. clearEnvyCache() drops both.
  • Nothing throws. An unreachable proxy, a 401 (the proxy's own key), a 4xx/5xx or unparseable JSON all read as an empty result. Where that ambiguity matters — a terminal must not report "no signals" for a proxy that is simply down — getSignalsOrNull / listStrategiesOrNull return null instead, sharing the same cache entry as their []-returning siblings.

./inventory — Sparkling inventory client

  • searchTicker(query) — resolve one ticker from free text.
  • getTokenInformation(id) — canonical token info (TokenInformation).
  • listTokens() / listPairs() / listChains() — full listings (keyset pagination walked to the end).
  • loadInventoryUniverse() / prefetchInventoryUniverse() — cached combined load of tokens+deployments (InventoryUniverse); prefetch swallows errors.
  • resolveDeploymentForSymbol(symbol, chain) — pick the best deployment (verification tier, non-bridge preference).
  • loadChains — cached chain list.
  • Plumbing: inventoryRequest<T>(...) (InventoryRequestOptions), InventoryError (alias InventoryClientError).
  • Types: Token, Deployment, Pair, Chain, ProviderMapping, TokenWithRelations, InventoryPage<T>, TokensPage, EntityStatus, ….

./indexer — Sparkling indexer client

  • searchTickers(query, opts)TickerSearchResponse — ticker search (TickerSearchItem; throws with the server error code).
  • getTokenPriceGraph(opts)PriceGraphResponse — price series (Timeframe, PriceGraphPoint); works through a same-origin proxy or direct.
  • fetchWalletSummary(...)WalletSummaryResult — per-chain wallet USD totals; fails fast (8s) so callers can fall back. WALLET_SUMMARY_CHAINS.
  • Portfolio: EVM_INDEXER_CHAINS, sumWalletTotals(values), combinePortfolioTotal({...}) (EvmIndexerNetwork, IndexerChain).
  • Balances backing ./balances: fetchIndexerBalances(...) (IndexerBalances), indexerEvmNativeAmount, indexerErc20Amount, indexerSolAmount (null = "fall back to RPC", not zero), indexerEvmSlug, clearIndexerBalanceCache(), INDEXER_BALANCE_CHAINS.

./swap — swap providers, Aurora bridge & NEAR Intents

Provider layer

Four venues behind one SwapProvider interface. They do not share a way of moving funds — 1Click hands out a deposit address, everything else hands back a transaction to sign — so SwapExecution keeps the two models apart instead of pretending they are one shape.

ProviderReach
1clickcross-chain only, 34 chains from NEAR Intents' own registry
uniswapsame-chain only, on the 7 chains with a verified v3 deployment
gaszipnative coin → native coin, cross-chain, 190+ EVM chains
lifiEVM ↔ EVM, 69 chains, same-chain and cross-chain (Stargate/gas.zip)
  • quoteAllSwaps(req, { providers? })QuoteSweep — quote every provider concurrently; routes best-first, refusals with a reason per venue, both in a deterministic order.
  • quoteSwap(req, opts?)SwapRoute — the single best route, or an error naming every refusal.
  • rankRoutes(routes) — the ordering: raw toAmount descending, ties broken by durationSec. Deliberately not USD: every provider is quoted for the same destination asset, so the integers compare directly, while USD would import noise from whichever price feed each provider happens to use.
  • planSwap(route, ctx)SwapExecution{ kind: "evm-call", chainId, to, data, value } or { kind: "deposit", address, chain, amountBase }. PlanContext carries oneClickJwt when 1Click needs it.
  • listSwapProviders() / findSwapProvider(name) / SWAP_PROVIDERS — the registry.
  • routableBy(req, providers?) — names of providers whose supports() accepts the pair. Local and synchronous, so a failure message can teach without a network round trip.
  • resolveChain(slug, opts?)ResolvedChain — the layered chain vocabulary: Sparkling inventory first, then the local EVM catalog. This is what lets a provider reach a chain the inventory has never heard of.
  • resolveEvmSwapToken(...) / fetchTokenDecimals(...) / EvmTokenUnresolved — ticker or contract address → a token with fetched decimals. Assuming 18 is right for native coins and wrong by six orders of magnitude for USDC.
  • Types: SwapRequest, SwapEndpoint, SwapRoute, SwapExecution, SwapProvider, PlanContext, QuoteSweep, ProviderInfo, and SwapUnsupported (a provider declining, with the reason shown to the user).
  • gas.zip: gasZipQuoteUrl(...), GAS_ZIP_MIN_USD. Its quote URL takes the native chain id while the deposit calldata carries gas.zip's own short code; swapping them returns "Insufficent Liquidity", which reads as a market condition and is not one.
  • LI.FI: LIFI_NATIVE (the zero address names a chain's own coin), LifiToken.

1Click (NEAR Intents)

fetchOneClickTokens / clearOneClickTokenCache, resolveOneClickAssetResolvedAsset, fetchOneClickQuote (dry for a real quote that moves nothing), liveDepositAddress, fetchOneClickStatus, oneClickBlockchainFor, ONE_CLICK_CHAIN_ALIASES / ONE_CLICK_SYMBOL_ALIASES, OneClickError.

Uniswap v3 (same-chain)

hasUniswapDeployment(chainId) / uniswapChainIds() / uniswapDeployment(), quoteFeeTier and bestUniswapQuote over UNISWAP_V3_FEE_TIERS, minimumOut, buildSwapCall / buildApproveCall / fetchAllowance, UniswapError.

Aurora bridge

  • buildAuroraTurnkeyProviders({...}) — EVM + Solana providers for the Aurora Intents swap widget from a single Turnkey session (wire into the widget's providers config).
  • QUOTE_REFRESH_MS / QUOTE_REFRESH_SECONDS — quote refresh cadence.
  • NEAR Intents (NEP-413):
    • hashNep413(input) — deterministic 32-byte signing digest (golden-tested against the defuse SDK).
    • tokenDiffIntent(...) / Intenttoken_diff swap intent (defuse asset ids → signed deltas).
    • signNearIntent(input)SignedNearIntent — sign with a Turnkey wallet (SignNearIntentInput).
    • publishNearIntent(...) — publish to the solver relay.
    • INTENTS_CONTRACT, SOLVER_RELAY_BASE.

./activity — on-chain activity feed

Paged per-chain fetchers returning ActivityPage ({ items, nextCursor } of normalized ActivityItems: direction, amount, symbol, counterparty, time, tx link). Cursors are opaque and chain-specific; pass nextCursor back to continue.

  • fetchEvmActivity(chainId, address, opts?) — native (txlist) or, with contract, ERC-20 transfers (tokentx); Etherscan-compatible or Blockscout backends (txListApiBase(chainId)).
  • fetchBtcActivity(address, opts?) — mempool.space, incl. unconfirmed on page 1.
  • fetchTronActivity(address, opts?) — native or TRC-20 (TronGrid fingerprint cursor).
  • fetchTonActivity(address, opts?) — TON transfers + jetton transfers.
  • fetchSolActivity(address, opts?) — SOL / SPL token balance deltas.
  • fetchSuiActivity(address, opts?) — from/to digests merged (mergeSuiItems).
  • fetchNearActivity(account, opts?) — via nearblocks (native + FT).
  • Pure mappers, usable against your own upstream responses: mapExplorerRows, mapBtcTxs, mapTronTrc20Rows, mapTronNativeRows, mapTonTxs, mapTonJettonTransfers, mapSolTxs, mapSuiTxs, mapNearTxns, mapNearFtTxns, tronAddressToHex; row types (ExplorerRow, BtcTx, SolTx, …) and constants (PAGE_SIZE, tx-URL prefixes, SUI_COIN_TYPE).

./zgcompute — 0G Compute (AI inference)

Subpath-only; heavy peers (@0gfoundation/0g-compute-ts-sdk, ethers, openai) load lazily.

  • Brokers: createZGBroker(eip1193, chainId) (browser wallet), createZGBrokerFromAccount(viemAccount, env) (CLI/server), createZGBrokerFromSigner(signer) (raw ethers), createZGReadOnlyBroker(env) (public reads, no wallet) — ZGBroker, ZGReadOnlyBroker, Eip1193Like.
  • Networks: ZgEnv ("mainnet" | "testnet"), zgChainId(env), zgRpcUrl(env), zgEnvForChainId(id), zgContracts(env); constants ZG_MAINNET_CHAIN_ID (16661), ZG_TESTNET_CHAIN_ID (16602), ZG_NEURON_PER_OG, ZG_MIN_LEDGER_FUND (3), ZG_MIN_TRANSFER (1), ZG_DEFAULT_FUND_AMOUNT — the MAINNET minimums, and the fallback for fetchZgLimits.
  • Limits: fetchZgLimits(env)ZgLimits — the deployment's own MIN_ACCOUNT_BALANCE / MIN_TRANSFER_AMOUNT (mainnet 3/1 0G, testnet 0.1/0.01), cached per env; suggestedFundAmount(limits), clearZgLimitsCache(). Anything deciding whether an amount is allowed must use these, not the mainnet constants.
  • fundZgLedgerViaContract({account, env, amount, exists})ZgFundResult — opens or tops up the ledger by calling the contract directly, which is what makes testnet funding possible: the SDK's own funding methods refuse anything below a hardcoded 3 0G.
  • transferZgFundViaContract({account, env, provider, amount}) — open or top up a provider sub-account at a chosen amount; zgServiceName(env, service) reads the registry name (inference-v1.0) the ledger's transferFund expects. ZG_PROVIDER_MIN_LOCKED (1 0G) is what the provider's proxy demands before it serves a request — a floor no client change can lower.
  • Ledger: fetchZgLedger(broker)ZgLedger (total / locked / available plus per-provider ZgSubAccounts for inference and fine-tuning); fundZgLedger, refundZgLedger, retrieveZgFunds({service, provider}), deleteZgLedger; getAvailableFund, isFunded, isNoLedgerError. Amounts are ZgAmount { og, neuron }neuronToOg, zgAmount.
  • Portfolio: fetchZgLedgerHolding(broker) / zgLedgerHolding(ledger)ZgLedgerHolding on network ZG_LEDGER_NETWORK ("0g-compute"), ready for computeHoldingsTotals. Committed funds, not the wallet's on-chain 0G.
  • Providers: listZgProviders({env|broker, search})ZGProvider[] with prices per 1M tokens, TEE flag and health; pickProvider(broker), findZgProvider(address).
  • Inference: ensureProviderAcknowledged, isProviderAcknowledged, getZgServiceMetadata, getZgRequestHeaders (may transfer funds on-chain), verifyZgResponsetrue | false | null.
  • Fine-tuning: listZgFineTuningProviders(env)ZgFineTuningProvider[]. Read-only by construction — running a job needs the raw private key the SDK reads off an ethers.Wallet, which Turnkey does not expose.
  • streamChat(opts)StreamChatResult — OpenAI-client streaming chat against a 0G provider endpoint with TEE verification (ChatTurn).
  • checkZgFunding({address, env, amount})ZgFundingCheck — what a top-up costs the wallet before anything signs: native 0G held, amount, gas reserve (ZG_GAS_RESERVE_OG), shortfall, canFund, and the chain/coin to send. isInsufficientFundsError(err) classifies the failure if one still happens.
  • zgAttestation(result)"ok" | "invalid" | "unverified" | null — the one claim a UI can honestly make about a reply. null means say nothing (no attestation was on offer); a check that could not run is unverified, never invalid.
  • runZgTurn(broker, opts)ZgTurnResult — one whole turn: the funding gate, provider pick + acknowledgement, headers, the streamed reply, attestation. The order is the point — acknowledging and minting headers sign transfers, so the balance is checked before the user is asked for a signature. Refusals are results (unfunded, empty), not exceptions, and a verification that itself errors leaves verified: null + verifyError rather than discarding a reply that was already paid for.
  • Lazy loaders: loadZgSdk() (ZGSdk), loadEthers(), loadOpenAI().

./venue — one model across venues

The only place that says what a position and an order have in common, so a portfolio view does not have to know three dialects. Adapters translate; they do not recompute — the arithmetic already lives in ./hyperliquid, ./polymarket and ./adi.

  • Types: UnifiedPosition, UnifiedOrder, UnifiedFill, CollateralView, VenuePnl, VenueCapabilities, CancelSelector, VenueAdapter, VenueContext (signer is a THUNK, so a public read never mints a key).
  • Adapters: hyperliquidAdapter, polymarketAdapter, adiAdapter, ALL_VENUES.
  • sweepVenues(adapters, ctx, read)VenueSweep<T> — concurrent reads where a failure becomes THAT VENUE's problem, never the sweep's. "Holds nothing" and "could not be asked" are different answers and never render alike.
  • sortPositions, totalPositions, totalResting — missing numbers are counted (unpriced), never summed as zero.
  • selectVenues(adapters, filter) — an unknown name is returned, not ignored.
  • parseWindow("7d" | "30s" | "2w") → ms.
  • fillsToCsv(fills) / csvCell — RFC 4180 quoting, because a prediction-market question contains commas.
  • planRebalance({target, usd, source?, collateral})RebalancePlan — the route as existing commands. Refuses an unreadable source balance (unknown is not "enough") and a target whose settlement chain is only known at runtime.
  • Route journal: newRouteJournal, nextStep (a SENT step comes back before any pending one — resume waits, it never skips), hasSettled, recordStep, routeProgress, settleChecksFor. Settlement is a BALANCE question, which survives a dropped receipt in a way a transaction hash does not.

./execution — order slicing & supervision

  • planSlices(parent, parentId)SlicePlan — TWAP (timed), ladder (immediate), iceberg (sequential). Notionals sum EXACTLY to the parent; the last slice absorbs the remainder.
  • cloidFor(parentId, index) — a DERIVED client order id (24 hex of parent + 8 of index). This is what makes resume safe: a child resent after a crash carries the same id and the exchange refuses the duplicate.
  • Journal: newJournal, outstanding (a sent child counts as done — its cloid is spent), recordSent, cancel, progress. A parent with any rejected child finishes failed, never done.
  • Trailing stop: startTrail, updateTrail, parseDistance. The stop only moves favourably, and a tick that both sets a new extreme and breaches the old stop TRIGGERS — it is one price, not two.

./strategy — recipes & backtest

  • parseStrategy(json)Strategy — strict, and separate from running, so a bad recipe fails at strategy check rather than at 3am. A rule fires ONCE unless "maxFires": null (DEFAULT_MAX_FIRES).
  • describeStrategy(strategy) — one line per rule, with its firing budget.
  • shouldFire(rule, state, value, now) — delegates the edge/cooldown decision to ./alerts rather than reimplementing it, so a live run and a backtest cannot disagree about what "has crossed" means.
  • backtest({strategy, series, feeRate})BacktestResult — trades, equity curve, realized/fees/open. Returns CAVEATS alongside the numbers, and puts a rule it cannot replay in unsupported rather than dropping it.

./alerts — threshold rules

  • parseCondition("price:BTC < 90000") / formatCondition / compare — strict grammar (SOURCE_METRICS); a rule that parsed into something other than what was meant would look armed and never fire.
  • decide(rule, actual, now)Verdict — EDGE-triggered with a cooldown. An actual of null leaves the state UNTOUCHED: recording "false" would re-arm the edge and invent a crossing.
  • liveReader({adapters, ctx}) — prices, venue position metrics and perp funding, cached per sweep.
  • deliver(rule, value, deps) — sequential, and a failed channel is reported: an alert nobody received looks exactly like one that never fired.

./risk — standing limits

  • checkDailyLoss, checkOrderNotional, checkLeverage, checkWithdrawTarget (case-insensitive — an EVM address is the same address in any casing), isEmpty, describeLimits.
  • Each check is separate so it can be applied where its information exists: the CLI runs the first three before signing and the notional one per reservation.

./paper — paper trading ledger

  • applyFill(positions, fill) — opening, adding (average in), reducing (realize) and FLIPPING through zero are handled separately; one formula for all four is where a paper book drifts from a real one.
  • bookFromFills, markToMarket (an unpriced coin marks null, never zero), PAPER_CAVEATS, PAPER_FEE_RATE.

./screen — finding opportunities

  • screenFunding(markets, filter) / toFundingRow — ANNUALISED, because an hourly rate hides the point; ranked by |APR| because a negative rate is as tradable from the other side; open interest valued in USD because coin units put a memecoin above BTC.
  • screenEdge(markets, filter) — prediction markets whose outcome prices do not sum to 1. A market with an unquoted outcome is DROPPED, not ranked as underpriced. EDGE_CAVEATS, DEFAULT_MIN_EDGE.
  • parseRate("20%" | "0.2" | "20").

./cow — CoW Protocol limit orders

  • buildLimitOrder(...)CowOrder; buyAmountFor(...) in integer maths, on the number that decides whether an order is worth signing.
  • cowDomain(chainId), COW_ORDER_TYPES, GPV2_SETTLEMENT, GPV2_VAULT_RELAYER — the relayer is what must be APPROVED; approving settlement instead is the classic integration bug, where the signature is valid and the order simply sits.
  • postLimitOrder, fetchCowOrders, cancelCowOrders, COW_NETWORKS.
  • toTokenUnits / fromTokenUnits — explicit decimals, unlike the network-based pair in ./senders.

./wallet — batch payouts, allowances, stuck transactions

  • parsePayouts(text) / splitCsvLine / summarize — one bad row refuses the WHOLE file, listing every problem: a half-executed payout is worse than none, because the output cannot say which half went.
  • isUnlimited (anything ≥ 2^128 — several contracts approve 2^255, and calling those "limited" overstates safety), formatAllowance, revokeCallData, allowanceCallData, byRisk, APPROVE_ABI.
  • bumpFees / planReplacement — a replacement must clear the node's minimum or the original stays stuck while the operator believes otherwise. A cancel sends 0 to the wallet's OWN address.

./cex — centralized exchanges

Binance USD-M futures, chosen because a futures position maps ONTO UnifiedPosition — entry, leverage, liquidation, unrealized — rather than into it. Spot balances would have to be reported as positions with a null entry, which is a shape, not a position.

  • binanceAdapter — a full VenueAdapter: positions, orders, cancel, collateral, windowed PnL from the income ledger, per-symbol fills.
  • fetchBinanceFunding() — PUBLIC, no key. Divided by BINANCE_FUNDING_INTERVAL_HOURS at the boundary, because Binance quotes per 8-hour interval and Hyperliquid quotes hourly; comparing them as printed overstates Binance eightfold.
  • fetchBinancePermissions(credentials) — what the key may actually do, asked of the exchange. The CLI refuses to store a key that can withdraw.
  • hmacSha256Hex, toQuery (insertion order — the signature covers the exact string sent), signedQuery. Web Crypto, so src/ stays browser-safe.
  • toUnifiedPosition / toUnifiedOrder — Binance returns every symbol including flat ones, and a zero row is dropped rather than shown as a position; a 0 liquidation price means "cannot be liquidated" and becomes null rather than reading as "liquidates at zero".

./evm — will this transaction work?

Two answers to two different questions.

  • preflight(client, {from, to, data, value})eth_call against the LIVE chain. Free, instant, nothing to install: "would this revert right now?". A node that cannot be reached returns ok: true, because refusing a transaction over a diagnostic that could not run turns a diagnostic into a gate.
  • decodeRevert / revertDataFromError(string), Panic(uint256) and a custom-error selector. The data is found through viem's typed error chain (BaseError.walkRawContractError), never scraped from a message: a client's message embeds the request it sent, so the first hex in it is the CALLDATA, and reading that reports a revert for a call that succeeded.
  • anvilArgs / forkRpcUrl / receiptStatus / describeFork — the pure parts of running a transaction on a forked chain, which answers what eth_call cannot: gas used, state changes, and several transactions in sequence. The outcome is success | reverted | unknown, never a boolean: a fork can accept a transaction and produce no readable receipt, and calling that either "succeeded" or "reverted" states a result it never gave.

./chart — terminal charts

  • renderLineChart(values, opts) — a flat series draws on one row instead of dividing by zero.
  • downsample(values, width) — averages each bucket; sampling would drop the spike the chart was drawn to show.
  • sparkline(values, width), buildTimeLabels.

./react — React bindings

Optional peers: react, @turnkey/react-wallet-kit (+ @turnkey/viem for the viem hook). Non-React consumers never pull React.

  • useTurnkeyAccounts({...})ChainAccount[] — the session's per-chain accounts (address, chain key, format).
  • useTurnkeyViemAccount() — a viem Account backed by Turnkey signing.
  • useHyperliquidAddress()HyperliquidAddress | null — the EVM address used for Hyperliquid.
  • usePlacePerpOrder() — place a perp order (PlacePerpOrderArgs, PerpOrderSideLabel). Plans through buildPerpOrderPlan first, so the order is validated before it is signed.
  • useHyperliquidExchangeClient(address)HyperliquidExchangeClientState — a Turnkey-signed ExchangeClient, built synchronously.
  • useHyperliquidDeposit(account) — deposit USDC from Arbitrum onto the exchange.
  • useHyperliquidPerps({ intervalMs, byVolume })AsyncState<PerpMarket[]> — the polled perp board. A failed poll keeps the rows already on screen.
  • useHyperliquidMargin(address, { intervalMs })AsyncState<number> — the polled free collateral. A null address is the resting state, not an error.
  • useSignals({ limit, intervalMs })AsyncState<EnvySignal[]> — the polled Envy feed.
  • useSignalStream({ enabled, reconnectMs })SignalStreamState — the live set over SSE, held in a Map keyed by signal id so the proxy's replayed snapshot overwrites rather than duplicates. Reconnects; never connects at all without apiBases.envyStream.
  • useSignalTrade({ signal, amountUsd, address, account })SignalTradeState — the market, the collateral, the planSignalTrade result and open(), composed. Submission goes through usePlacePerpOrder.
  • useTickerSearch(query, opts?)TickerSearchState — debounced indexer ticker search.
  • useTokenPriceGraph(...)TokenPriceGraphState — price-graph data for a token/timeframe.
  • chainFromAddressFormat(addressFormat)ChainKey | null — map a Turnkey address format to a chain key.
  • useZgBroker(eip1193, env)AsyncState<ZGBroker> — the 0G broker for a connected wallet, rebuilt only when the wallet or network changes.
  • useZgLedger(broker, {pollMs})UseZgLedgerResult — balances plus funded, fund(amount) and funding. A missing ledger is data, not an error.
  • useZgProviders(env, search?)AsyncState<ZGProvider[]> — public listing, usable before a wallet is connected.
  • useZgChat(broker, provider, {verify})UseZgChatResult — streaming reply, abort(), and a three-state verified (true | false | null).
  • useTurnkeyZgBroker(env)TurnkeyZgBroker — the broker for the wallet the Turnkey kit holds, built on the first ensureBroker() rather than on mount, so rendering a chat costs nothing until someone sends. The resolved broker is published as state for useZgLedger to hang off.
  • useSwapPanel({rail, slippageBps, oneClickJwt, onError})UseSwapPanelResult — quote/review/sign for any rail: "auto" sweeps all and keeps the best route, or pin "1click" | "uniswap" | "gaszip" | "lifi". Reports refusals per rail so a dead end can say which venue declined and why. runSwapRoute(...) is the shared plan-and-sign step underneath.
  • useZgRefuel(env)UseZgRefuelResult — getting native 0G into a wallet that has none: the chains where it already holds gas, a gas.zip quote into 0G, and refuel() to sign it. gas.zip is the only rail here that reaches 0G at all (1Click doesn't list the chain, Uniswap can't leave its own).
  • useZgConversation({env, onError, verify})UseZgConversationResult — a chat whose transcript stays with the app: ask(messages, sink) opens the reply on the first token (so a turn that fails before any output leaves no orphaned bubble), returns an outcome (replied / unfunded / empty / failed / aborted) instead of throwing, and exposes attestationById, needsFunding and fund. This is the one to reach for in a UI.
  • useZgAssistant(env)UseZgAssistantResult — broker + ledger + runZgTurn behind one ask(messages, {onToken}). Turns are serialized (acknowledgement and header minting sign from the same address, so overlapping turns would race nonces) and the provider is pinned per wallet after the first turn. The app above keeps only its transcript.

Cross-cutting behaviors

  • Caching. Balance reads share a TTL cache (BALANCE_TTL_MS); the indexer balance path caches one /v1/balance per chain; inventory universe/chains use in-flight-deduped promise caches. clearBalanceCache() / clearIndexerBalanceCache() force fresh reads.
  • Indexer-first, RPC-fallback. EVM/SOL balances try the Sparkling Indexer and silently fall back to raw RPC (null from the indexer path means "fall back", never "zero").
  • Retry. Upstream HTTP goes through fetchWithRetry.
  • No host env. Endpoints come only from configure() — never NEXT_PUBLIC_*.
  • No kit lock-in. Turnkey signing is the structural TurnkeySigning interface; any compatible client works.
  • Tree-shaking. Subpath exports + sideEffects: false; chain SDKs are optional peers, so unused chains never enter the bundle. The root barrel excludes react, polymarket, prices, and zgcompute (name collisions / optional-dep isolation) — import those from their subpaths.

Peer-dependency matrix

Hard deps: viem (peer), @noble/curves, @scure/*, borsh. Everything else is an optional peer — install only what you use:

CapabilityInstall
EVM signing / Hyperliquid@turnkey/viem, viem
Solana@solana/web3.js, @turnkey/solana
NEAR@near-js/crypto, @near-js/providers, @near-js/transactions
TON@ton/core, @ton/ton, @ton/crypto
Sui@mysten/sui
Trontronweb
Hyperliquid@nktkas/hyperliquid
Polymarket@polymarket/clob-client-v2
Aurora swap (./swap)@aurora-is-near/intents-swap-widget*
0G Compute (./zgcompute)@0gfoundation/0g-compute-ts-sdk, ethers, openai
React hooks (./react)react, react-dom, @turnkey/react-wallet-kit

Released under the MIT License.