> For the complete documentation index, see [llms.txt](https://docs.northstar.sonicsvm.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.northstar.sonicsvm.org/getting-started/recipes.md).

# Recipes

Working snippets for common NorthStar patterns. Each recipe extends the [Hello World](https://github.com/mirrorworld-universe/northstar-docs/blob/main/getting-started/hello-world/README.md) shape; copy-paste ready.

## 1. Always-on agent loop

A Bun service that opens a persistent session, runs a deterministic policy each tick, and re-emits each decision over Server-Sent Events. This is the shape the [Mach Sandbox](https://github.com/mirrorworld-universe/mach-amm) runs in production.

```typescript
import { AgentLoop, currentRatioBps, DEFAULT_POLICY } from "@mach/agent";

const loop = new AgentLoop({
  manifest, agent, owner, mintA, mintB,
  rpc: ER_RPC,
  intervalMs: 1_000,
  onCycle: (event) => {
    eventBus.publishTx({
      tSendUnixMs: event.timestampMs,
      signature: event.signature,
      direction: event.decision.kind === "swap" ? event.decision.direction : null,
      // …
    });
  },
});
loop.start();
```

The `onCycle` callback fires per tick with the policy decision, vault snapshot, and any submitted signature. Wire it to whatever consumer you need — SSE, NDJSON file, OpenTelemetry.

## 2. Confirm-status reconciliation

ER confirmation can be faster than the L1-tuned `confirmTransaction` timeout. Use a separate `getSignatureStatuses` poller to upgrade `pending` rows once the chain catches up:

```typescript
const reconciler = setInterval(async () => {
  for (const seq of pending) {
    const [status] = (await ER_RPC.getSignatureStatuses([seq.signature], {
      searchTransactionHistory: true,
    })).value;
    if (!status) continue;
    if (status.err) markFailed(seq, status.err);
    else if (status.confirmationStatus === "confirmed") markConfirmed(seq, status.slot);
  }
}, 1_500);
```

## 3. Settle on TTL approach

Sessions auto-expire when their TTL elapses. To rotate gracefully, open the next session in parallel a few minutes before expiry, warm it (delegate accounts), then swap your traffic over and close the old one:

```typescript
async function rotateBeforeTTL(currentSession: Session, currentSlot: bigint) {
  const slotsLeft = currentSession.expirySlot - currentSlot;
  const slotsBeforeRotate = 200n;          // ~ 80s buffer at 400ms slots

  if (slotsLeft > slotsBeforeRotate) return;

  const next = await sdk.openSession({ owner, gridId: currentSession.gridId + 1n, ttlSlots, feeCap });
  for (const account of currentSession.delegatedAccounts) {
    await sdk.delegate({ owner, gridId: next.gridId, account, ownerProgram });
  }
  await sdk.closeSession({ owner, gridId: currentSession.gridId });

  return next;
}
```

## 4. Custom-fee grid (USDC)

```typescript
import { FeeStructure } from "@sonicsvm/northstar-sdk";

const usdcMint = new PublicKey("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU");

await sdk.openSession({
  owner,
  gridId: 1n,
  ttlSlots: 86_400n,
  feeCap: 0n,                                  // gasless from the user's perspective
  feeStructure: FeeStructure.custom({
    token: usdcMint,
    perTxLamports: 10_000n,                    // ~ 0.001 USDC per tx
    revenueSplitBps: 5_000,                    // 50% to grid operator
  }),
});
```

See [Programmable Economics](https://github.com/mirrorworld-universe/northstar-docs/blob/main/build/fees/README.md) for the full schema.

## 5. Subscribe to live activity

The Portal's session account is just a Solana account; subscribe to it like any other:

```typescript
const subId = erRpcConnection.onAccountChange(sessionAddress, (acct) => {
  console.log(`Session bytes changed at slot ${acct.lamports} …`);
});
```

For per-tx feeds, use the program's instruction accounts:

```typescript
const programSubId = ER_RPC.onLogs(programId, (logs) => {
  console.log("ix logs:", logs);
});
```

## See also

* [Hello World](https://github.com/mirrorworld-universe/northstar-docs/blob/main/getting-started/hello-world/README.md)
* [Confirmation lifecycle](https://github.com/mirrorworld-universe/northstar-docs/blob/main/architecture/confirmation-lifecycle/README.md)
* [API reference](https://github.com/mirrorworld-universe/northstar-docs/blob/main/reference/sdk-typescript/README.md)


---

# 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.northstar.sonicsvm.org/getting-started/recipes.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.
