Forest Docs
DevelopersForest Playkit

Swap Sessions

User-approved auto-swap sessions and trusted backend execution.

Swap sessions are user-approved auto-swap permissions. The iframe asks the user to enable a session; your trusted backend executes against it. They are available only when the project owner has enabled auto-swaps for the HTML project (autoSwapsEnabled in project context).

Gate session UI on availability

If autoSwapsEnabled is false, do not render session controls — execution will be rejected with SWAP_SESSION_DISABLED.

How sessions work

Enable (create)

The iframe requests a session with display-decimal budgets. Forest converts them into contract base units, prepares the required token approvals for the session executor contract, and prepares the session transaction. The user confirms the wallet prompts; Forest then confirms the createSession transaction and stores the active session.

Execute (backend)

Session execution is a backend-to-Forest API flow. Forest uses the user's managed executor wallet to send the on-chain execution transaction. HTML templates do not configure executor wallet addresses — Forest owns the executor-wallet setup and confirmation flow.

Revoke

Users can revoke active sessions from the Forest UI or via forest.swap.session.revoke.

Never cache the session id

Before every backend execution, request forest.swap.session.current and use that returned session.id. Do not execute against a session id restored from localStorage or another stale client cache.

Approval hashes are progress, not completion

The create flow may emit hash responses with stage: "approval_submitted" before the final stage: "create_submitted" hash. Treat approval hashes as progress updates; the session is active only after the final success response.

Executor wallet needs gas

The managed executor wallet must hold native gas on the configured chain for executions to land.

Session Methods

forest.swap.session.create

JavaScript
callForest("forest.swap.session.create", {
	forestBudget: "50",
	projectBudget: "1000.5",
	expiresAt: Math.floor(Date.now() / 1000) + 86400,
});

Unlimited budget:

JavaScript
callForest("forest.swap.session.create", {
	forestBudget: null,
	projectBudget: null,
	expiresAt: Math.floor(Date.now() / 1000) + 86400,
});

Prop

Type

Budgets are display decimal strings. Use null for a side that should be unlimited until expiresAt is reached or the user revokes the session. Successful responses return the confirmed session plus the transaction hash:

JavaScript
{
  session: {
    id: "9db7f2d8-5e03-4c73-96f9-31b99747d0c6",
    onChainSessionId: "42",
    chainId: 97,
    status: "active",
    snapshot: {
      routerAddress: "0x...",
      forestBudget: "50000000000000000000",
      projectBudget: "1000500000000000000000",
      expiresAt: "2026-05-15T12:00:00.000Z",
      createTxHash: "0x...",
      createdAt: "2026-05-14T12:00:00.000Z"
    },
    createdAt: "2026-05-14T12:00:00.000Z",
    updatedAt: "2026-05-14T12:00:00.000Z"
  },
  limits: {
    forestBudget: "50000000000000000000",
    projectBudget: "1000500000000000000000",
    expiresAt: "2026-05-15T12:00:00.000Z"
  },
  txHash: "0x..."
}

forest.swap.session.current

JavaScript
callForest("forest.swap.session.current");

Returns the latest active session for the current project and authenticated wallet user, using the same response shape as forest.swap.session.get. Use this method immediately before passing a session id to your backend for execution.

forest.swap.session.get

JavaScript
callForest("forest.swap.session.get", {
	sessionId: "9db7f2d8-5e03-4c73-96f9-31b99747d0c6",
});

Returns the stored session so your app can inspect status, limits, and expiry. Forest resolves router and pair addresses internally; HTML apps never provide or persist those addresses.

Sessions do not re-route

Sessions do not fall back to a new route after router or pair changes. If the on-chain session route is no longer usable, the user must recreate the session.

JavaScript
{
  limits: {
    forestBudget: "50000000000000000000",
    projectBudget: null,
    expiresAt: "2026-05-15T12:00:00.000Z"
  },
  session: {
    id: "9db7f2d8-5e03-4c73-96f9-31b99747d0c6",
    onChainSessionId: "42",
    chainId: 97,
    status: "active",
    snapshot: {
      routerAddress: "0x...",
      forestBudget: "50000000000000000000",
      projectBudget: null,
      expiresAt: "2026-05-15T12:00:00.000Z",
      createTxHash: "0x...",
      createdAt: "2026-05-14T12:00:00.000Z"
    },
    createdAt: "2026-05-14T12:00:00.000Z",
    updatedAt: "2026-05-14T12:00:00.000Z"
  }
}

HTML SDK session responses use base-unit integer strings for budgets. limits mirrors session.snapshot budget fields and exists only as a convenient place to read the configured session caps and expiry.

forest.swap.session.revoke

JavaScript
callForest("forest.swap.session.revoke", {
	sessionId: "9db7f2d8-5e03-4c73-96f9-31b99747d0c6",
});

Revokes an active session through the connected wallet, then confirms the revoke transaction with Forest. This opens a wallet prompt and returns the same response shape as forest.swap.session.get, plus txHash when the revoke transaction is confirmed.

Trusted Swap Session Execution

Uploaded HTML can request that a user enables a session, but execution must come from your trusted backend. Use the same server-only Settlement Signing Secret and HMAC header as settlement:

HTTP
POST /campaigns/{projectId}/html/swap-sessions/{sessionId}/executions
Content-Type: application/json
X-Forest-Settlement-Signature: v1=<hex-hmac>
JavaScript
{
	sessionId: "9db7f2d8-5e03-4c73-96f9-31b99747d0c6",
	requestId: "6ae1ea37-19a2-46db-a59f-742e58fb8c4d",
	direction: "buy",
	projectAmount: "1000000000000000000",
	forestAmountLimit: "1000000000000000000",
	timestamp: Math.floor(Date.now() / 1000)
}

Prop

Type

Sign the exact JSON string you send. Store the signed body by sessionId + requestId and replay that same body if the response is lost. Reusing a request id with a different direction, amount, or deadline is rejected.

A successful response contains the confirmed execution transaction:

JavaScript
{
  id: "execution-id",
  sessionId: "9db7f2d8-5e03-4c73-96f9-31b99747d0c6",
  requestId: "same-request-id",
  direction: "buy",
  txHash: "0x...",
  projectAmount: "1000000000000000000",
  forestAmount: "100000000000000000",
  forestBudgetRemaining: "49000000000000000000",
  projectBudgetRemaining: "100000000000000000000",
  replayed: false
}

Forest records confirmed executions only after the contract emits the matching SwapSessionExecuted event. If your backend loses the response, retry the same requestId and exact signed body. Signature and timestamp failures use the shared settlement error taxonomy; session state, route mismatches, and chain-validation failures can return normal HTTP errors without an app-specific code.

Embedded HTML apps can revoke sessions with forest.swap.session.revoke; users can also revoke active sessions from Forest UI.