Quickstart

The path below has no venue-specific branches: the server says what needs signing, activate() signs it. A compiled, CI-checked version ships in the SDK as examples/multi-venue.ts.

Install

The SDK is published to GitHub Packages. Add to your project's .npmrc:

@zifrovoy-wallet:registry=https://npm.pkg.github.com

Then install (requires a GitHub token with read:packages):

npm install @zifrovoy-wallet/copy-trading

The five calls

import { CopyTradingClient, createWalletAuthHeaders } from '@zifrovoy-wallet/copy-trading'

const client = new CopyTradingClient({
  baseUrl: API_URL,
  apiKey: PARTNER_KEY,
  // Owner-scoped routes need the user's signature too. Build this ONCE and
  // reuse it β€” it holds the monotonic timestamp counter that prevents replay
  // rejections.
  getAuthHeaders: createWalletAuthHeaders({ address: userAddress, signer: personalSigner }),
})

// 1. What can you offer? Entitlements are per-partner, so ask rather than assume.
const venues = await client.listVenues()

// 2. Who is worth copying? Graded, not ranked by PnL.
const leaders = await client.listLeaders({ venue: venues[0].id, mirrorableOnly: true })

// 3. Create the agent.
const { agentId } = await client.createAgent({
  venue: venues[0].id,
  smartAccountAddress: userAddress,
  leaderWalletAddress: leaders[0].address,
  riskConfig: { maxUsd: '500', copyPercent: 10 },
})

// 4. One call, every venue. Walks whatever steps that venue needs.
await client.activate(agentId, signer)

// 5. Same feed shape everywhere.
const { executions } = await client.listExecutions(agentId)

What signer must implement

Only signTypedData is required everywhere. The rest are requested per venue, and a venue that needs one you did not provide fails immediately with a message naming the method β€” not with a signature error from inside an adapter.

  • Name
    signTypedData
    Type
    required
    Description

    Needed by all venues.

  • Name
    signMessage
    Type
    per venue
    Description

    Needed by Polymarket (proxy delegation).

  • Name
    sendTransaction
    Type
    per venue
    Description

    Needed by spot (enabling the smart session on-chain).

Perps in three calls

Hyperliquid needs no smart-account infrastructure β€” any EOA that can signTypedData, one signature loop, no gas. Hyperliquid is not an EVM chain, so its strategies are catalogued under chainId: 0.

import { CopyTradingClient, PerpsCopyClient } from '@zifrovoy-wallet/copy-trading'

const perps = new PerpsCopyClient({
  api: client,
  signer: { signTypedData: (payload) => wallet.signTypedData(payload) },
})

// 1. pick a leader
const strategies = await client.listStrategies(0)

// 2. create the agent, sign the Hyperliquid approvals, submit them
const { agentId } = await perps.activate({
  smartAccountAddress: userAddress,
  strategyId: 'perps-copytrade-hyperliquid',
  leaderWalletAddress: '0x…',
  maxUsd: '1000', // per-trade cap
  copyPercent: '100', // share of the leader's size, whole percent 0–100
  maxLeverage: 3,
})

// 3. show the user what it did
const { executions } = await client.listExecutions(agentId)

Spot

Spot copying installs an ERC-7579 smart session: a scoped, expiring permission that lets the backend's session key call swap routers on the user's behalf and nothing else. It cannot transfer tokens out, and it stops working on its own at validUntil.

Activation is wallet-specific. The SDK handles API calls, session policy shapes and the enable/revoke sequence; you provide a SpotSessionAdapter (build/install/revoke sessions in your wallet stack), a TransactionSender, and your actionPolicies.

Was this page helpful?