Skip to main content

Quickstart

This guide walks you through creating an account and earning yield on Compound — the most common integration flow. By the end, you’ll have a working sub-account earning USDC yield on Base.

Prerequisites

  • A Legend Prime Account with a query key (contact us to get set up)
  • An EOA private key (for signing transactions)

1. Install the SDK

npm install legend-prime viem

2. Initialize the client

import { LegendPrime } from "legend-prime";

const client = new LegendPrime({
  queryKey: process.env.LEGEND_QUERY_KEY,
});

3. Create a sub-account

Each sub-account has its own on-chain wallet. You provide the signer’s Ethereum address — the private key stays with you.
curl -X POST https://prime-api.legend.xyz/accounts \
  -H "Authorization: Bearer $LEGEND_QUERY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "signer_type": "eoa",
    "signer_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18"
  }'
Response:
{
  "external_id": "acc_2o0yiljtp378",
  "signer_type": "eoa",
  "signer_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
  "legend_wallet_address": "0xc40897f38bc3d4e4d17f9daf46d2a13b4c47642f",
  "created_at": "2025-06-15T10:30:00Z"
}
The legend_wallet_address is the sub-account’s on-chain wallet. Fund this address with USDC before proceeding.

4. Create an earn plan

A plan describes what you want to do. Legend generates the on-chain transaction details and returns an EIP-712 digest for signing.
curl -X POST https://prime-api.legend.xyz/accounts/acc_2o0yiljtp378/plan/earn \
  -H "Authorization: Bearer $LEGEND_QUERY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "1000000",
    "asset": "USDC",
    "network": "base",
    "protocol": "compound"
  }'
Response:
{
  "plan_id": "pln_71mcui082png",
  "chart": {
    "quark_operation_actions": [...],
    "eip712_data": {
      "digest": "0x8a3f...b7c2",
      "domain_separator": "0x...",
      "hash_struct": "0x..."
    }
  },
  "expires_at": "2025-06-15T10:32:00Z"
}
Plans expire after 2 minutes. Sign and execute before expires_at or create a new plan.

5. Sign the plan

The signer approves the plan by signing the EIP-712 digest. This proves they authorize the on-chain transaction.
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`);

const digest = plan.chart.eip712_data.digest;
const signature = await signer.sign({ hash: digest });

6. Execute the plan

Send the signature back to Legend. This triggers the on-chain transaction.
curl -X POST https://prime-api.legend.xyz/accounts/acc_2o0yiljtp378/plan/execute \
  -H "Authorization: Bearer $LEGEND_QUERY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "plan_id": "pln_71mcui082png",
    "signature": "0x1a2b3c..."
  }'
Response:
{
  "plan_id": "pln_71mcui082png",
  "quark_intent_id": 42,
  "status": "executing"
}

7. Verify the result

Poll the activities endpoint to confirm the transaction landed.
curl https://prime-api.legend.xyz/accounts/acc_2o0yiljtp378/activities \
  -H "Authorization: Bearer $LEGEND_QUERY_KEY"
Response:
{
  "activities": [
    {
      "id": 1,
      "activity_type": "quark_operation_executed",
      "activity_status": "pending",
      "activity_metadata": [
        {
          "action_type": "COMET_SUPPLY",
          "asset_symbol": "USDC",
          "amount": "1000000",
          "chain_id": "8453"
        }
      ],
      "occurred_at": "2025-06-15T10:30:15Z"
    }
  ]
}
For real-time updates instead of polling, use the events endpoint with poll=true for long-polling.

Full example

Here’s the complete flow in one script:
import { LegendPrime } from "legend-prime";
import { privateKeyToAccount } from "viem/accounts";

const client = new LegendPrime({
  queryKey: process.env.LEGEND_QUERY_KEY,
});

// 1. Create account
const account = await client.accounts.create({
  signerType: "eoa",
  signerAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
});

// 2. Create earn plan
const plan = await client.plan.earn(account.external_id, {
  amount: "1000000",
  asset: "USDC",
  network: "base",
  protocol: "compound",
});

// 3. Sign
const signer = privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`);
const signature = await signer.sign({
  hash: plan.chart.eip712_data.digest,
});

// 4. Execute
const result = await client.plan.execute(account.external_id, {
  planId: plan.plan_id,
  signature,
});

console.log(`Executing: ${result.plan_id}`);

// 5. Poll for confirmation
for (let i = 0; i < 30; i++) {
  const { activities } = await client.accounts.activities(account.external_id);
  if (activities.length > 0) {
    console.log(`Done: ${activities[0].activity_type}`);
    break;
  }
  await new Promise((r) => setTimeout(r, 2000));
}

Next steps