> For the complete documentation index, see [llms.txt](https://docs.symm.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.symm.io/trader-documentation/building-a-trading-bot/part-1-one-time-on-chain-setup.md).

# Part 1: one-time on-chain setup

## Part 1: One-time on-chain setup

Part 1 is signed by your Owner EOA and only needs to run once; you'll repeat step 4 whenever you rotate the session key. It gets you from a wallet holding USDC to a session key that's allowed to trade.

### 0. Configure the SDK

Point the SDK at HyperEVM and give it your registered affiliate address (this is the affiliate address of the [frontend builder](/trader-documentation/glossary-of-terms.md#frontend-builder)).

```typescript
import { createConfig, SymmioSupportedChainId } from "@symmio/trading-core";
import { createPublicClient, http } from "viem";

const publicClient = createPublicClient({
  transport: http("https://rpc.hyperliquid.xyz/evm"),
});

const config = createConfig({
  symmioConfig: {
    [SymmioSupportedChainId.HYPER_EVM]: {
      addresses: { affiliatesAddress: "0xYourRegisteredAffiliate" },
    },
  },
  defaultChainId: SymmioSupportedChainId.HYPER_EVM,
  getClient: () => publicClient,
  getWalletClient: async ({ chainId, from }) => resolveWalletClient({ chainId, from }),
});
```

### 1. Create a SubAccount

A SubAccount is the isolated on-chain account that will hold your collateral. The SDK wraps creation like everything else: `createSubAccounts` takes your affiliate and an array of account definitions, so you can batch several in one transaction.

```typescript
import {
  createSubAccounts,
  getUserSubAccounts,
  SubAccountIsolationType,
} from "@symmio/trading-core";

const chain = config.getChainConfig(999);

await createSubAccounts(config, {
  affiliate: "0xYourRegisteredAffiliate",
  accountsData: [{
    name: "bot-1",
    metadata: "0x",
    symmioCore: chain.addresses.symmioAddress,
    isolationType: SubAccountIsolationType.MARKET,
    singleVAMode: true, // reuse one active VA per market instead of one per open
  }],
});

const [subAccount] = await getUserSubAccounts(config, { user: ownerAddress });
```

> The isolation type (`POSITION`, `MARKET`, `MARKET_DIRECTION`, `CUSTOM`) decides when the AccountLayer spins up a new Virtual Account for a trade. Pick the mode your strategy needs; it also determines what "one position" means when you close or attach TP/SL later.

### 2. Fund the SubAccount

Approve the SYMMIO core to spend your USDC, deposit it into the SubAccount's available balance, then allocate it into tradable balance.

```typescript
import { approveCollateral, depositForAccount, allocate } from "@symmio/trading-core";

// USDC has 6 decimals. Approval and deposit both use collateral decimals.
await approveCollateral(config, { amount: 250_000000n }); // 250 USDC
await depositForAccount(config, { account: subAccount, amount: 250_000000n });

// allocate takes an 18-decimal amount (NOT collateral decimals)
await allocate(config, { account: subAccount, amount: 250_000000000000000000n });
```

> Two traps here. First, decimals: `approveCollateral` and `depositForAccount` use the collateral token's decimals (6 for USDC, read via `getChainConfig().addresses.collateralDecimals`), but `allocate` takes an 18-decimal amount. Mixing them up is an easy and expensive bug. Second, the approval target: `approveCollateral` approves the SYMMIO core contract. Approving the AccountLayer address by hand instead makes the deposit revert.

### 3. Create a session key

The session key is a local throwaway keypair. It signs every trade at runtime so your Owner EOA key stays cold.

```typescript
import { createSessionKeyManager } from "@symmio/session-key";

const manager = createSessionKeyManager({ storage }); // storage: your load/save/remove adapter
const state = await manager.initialize(ownerAddress);  // generates or loads the key
const sessionKey = state.address;
```

> Security note: the manager hands your storage adapter the raw private key as plaintext; it does not encrypt anything for you. Encrypt at rest in your storage adapter.

### 4. Delegate trading authority to the session key

This is the on-chain grant, made against the InstantLayer, that lets the session key trade on the SubAccount's behalf. The step is not optional. In the SDK's words, "missing delegation is the #1 silent-open-failure": the hedger accepts your signed order and your bot thinks it worked, but the on-chain anchor reverts afterward.

Grant the full `INSTANT_TRADE_REQUIRED_SELECTORS` set. It expands to the three selectors that cover the whole lifecycle (open, add margin, close); granting a single raw selector leaves part of the lifecycle unauthorized.

```typescript
import {
  grantDelegation,
  getIsDelegationActive,
  INSTANT_TRADE_REQUIRED_SELECTORS,
} from "@symmio/trading-core";

const expiryTimestamp = 1_766_000_000n; // unix seconds; set to your rotation horizon

await grantDelegation(config, {
  account: { addr: subAccount, isPartyB: false },
  delegatedSigner: sessionKey,
  selectors: INSTANT_TRADE_REQUIRED_SELECTORS,
  expiryTimestamp,
});

// getIsDelegationActive checks one selector at a time, so verify each,
// and gate trading until every one comes back true.
const checks = await Promise.all(
  INSTANT_TRADE_REQUIRED_SELECTORS.map((selector) =>
    getIsDelegationActive(config, {
      account: { addr: subAccount, isPartyB: false },
      delegate: sessionKey,
      selector,
    })
  )
);
const ready = checks.every(Boolean);
```

### A note on server-side TP/SL

You don't need any extra delegation for managed take-profit/stop-loss. Conditional orders run through the solver's TP/SL handler service, and the on-chain close leg is already covered by `REQUEST_TO_CLOSE_POSITION_SELECTOR`, one of the three selectors you just granted. Part 2 shows how to attach the orders.

Once steps 1 through 4 succeed, setup is done. Everything in Part 2 is signed by the session key.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.symm.io/trader-documentation/building-a-trading-bot/part-1-one-time-on-chain-setup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
