For the complete documentation index, see llms.txt. This page is also available as Markdown.

Abstraxion signer mode

Abstraxion authentication.type signer — getSignerConfig, AA API, env vars, Turnkey registration pattern

Signer mode (authentication.type: "signer") runs Meta Account flows without redirecting the user to the full-page Verona dashboard.

Outcomes to read alongside this page

For architecture-level combinations (recommended auto / dashboard flows vs signer + session vs signer + requireAuth, plus passkey-first narratives), read Abstraxion modes and opportunities. The rest of this document is wiring and appendix reference.

The essentials: getSignerConfig

What you implement

Write getSignerConfig: an async function that returns a SignerConfig when your wallet or custody layer is ready. The SDK calls it when the user connects.

In demo-app, that logic lives in useTurnkeyViem.ts (or useTurnkeyRawAPI.ts), selected by useTurnkeyForAbstraxion and passed from signer-mode/layout.tsx into AbstraxionProvider. Replace that hook with your stack (MetaMask, Privy, …).

What you wire

Put getSignerConfig on authentication next to type: "signer", and set chainId (and anything else) the same way as the demo layout. Do not re-derive the boilerplate from scratch—start from layout.tsx + apps/demo-app/.env.example.

Everything else on authentication and env mapping is in the appendix.

When to use signer mode

Use signer mode when…

Prefer dashboard auth (auto / popup / redirect) when…

You control the key material (Turnkey, Privy, custom HSM) or bridge a browser wallet as owner.

Standard Meta Account login via hosted dashboard is enough.

You must avoid a full navigation away from your SPA.

Popup or embedded dashboard UX is acceptable.

You are prototyping wallet-led abstract accounts (e.g. MetaMask in direct-signing-demo).

You want the fastest path with minimal AA API / contract metadata.

Concrete demo routes for signer auth + signing paths are in Signing: session key vs direct below.

Signing: session key vs direct

Signer mode only changes how the user authenticates (getSignerConfig). How transactions are signed is only two choices below: session (default hook) vs direct (requireAuth). Turnkey in /signer-mode is example wiring for the session demo (custody UI → getSignerConfig), not a third signing mode.

Session signing (default useAbstraxionSigningClient())

Call useAbstraxionSigningClient() with no options (or only options that do not set requireAuth: true).

  • After connect, the SDK uses a session-style signing client (GranteeSignerClient) aligned with Treasury / fee grants: gas is covered for allowed messages when grants are configured.

  • Typical gasless dApp flow: user approves grants once (when applicable), then submits through the session client.

  • Fees on execute: you often use "auto" for gas estimation like the main Account abstraction tutorial.

Vendor example — Turnkey on /signer-mode: that route pairs Turnkey with Abstraxion using registerAbstraxionLogin, registerAbstraxionLogout, registerCreateWallet, and registerWalletsGetter in providers.tsx (“how does custody UI hand off before getSignerConfig runs?”). The same context + refs idea applies to other vendors. Turnkey env: appendix. For MetaMask-style wiring used to diff session vs direct signing, use /direct-signing-demo instead of Turnkey there.

Direct signing (requireAuth: true)

Call useAbstraxionSigningClient({ requireAuth: true }).

  • Each (or many) operations go through the user’s authenticator on the meta-account (AAClient path in signer mode), not the delegated session shortcut.

  • Gas is usually paid by the user (or you model fees explicitly); "auto" on execute is less appropriate than simulate + calculateFee (or your own fee model)—see the demo for the split.

  • Use when you need per-transaction user approval, no session grants, or to compare behavior next to the session path.

Which demo to read

Example
Route
What it highlights

Session / gasless with signer auth

signer + Turnkey → getSignerConfig; default useAbstraxionSigningClient(); gasless / Treasury.

Direct vs session side by side

Same signer auth; default vs requireAuth: true; MetaMask-style wallet; simulate / fees vs "auto".

Run demo-app locally and open those routes after reading the page components and hooks—they are the authoritative examples next to this page.


Appendix: Signer configuration reference

Match signer-mode/layout.tsx or extend it. Full commented env: apps/demo-app/.env.example.

authentication when type: "signer"

Required?
Field
Notes

Yes

type

Must be "signer".

Yes

getSignerConfig

Your async factory → SignerConfig.

Preset/override

aaApiUrl

Must still be provided by your app at runtime, typically from the preset URL for your chainId from .env.example (or via override). Demo layout.tsx reads NEXT_PUBLIC_AA_API_URL.

Preset/override

smartAccountContract

Must still be provided by your app at runtime, typically from the preset wasm for that network + AA API from .env.example (or via override). codeId / checksum must match the AA API you use.

No

indexer

Set when using NEXT_PUBLIC_INDEXER_URL (+ type/token per .env.example); else RPC discovery.

No

treasuryIndexer

{ url } when NEXT_PUBLIC_TREASURY_INDEXER_URL is set.

If your SignerAuthentication type still lists aaApiUrl / smartAccountContract, populate them from the same chainId preset (not new values you invent)—equivalent to copying the block for that network from .env.example into config.

Top-level config & environment variables

chainId is required. normalizeAbstraxionConfig fills rpcUrl, restUrl, gasPrice, and feeGranter from @burnt-labs/constants when omitted for a known Verona chainId.

aaApiUrl and smartAccountContract are not filled by that same helper in the public SDK today—treat them as documented presets per network (same values as the chainId block in apps/demo-app/.env.example): copy or merge them in app config. You override only for custom AA / wasm.

Required?
Variable
Maps to

Yes

NEXT_PUBLIC_CHAIN_ID

config.chainId — required network id; enables RPC/REST/gas/fee-granter defaults via normalizeAbstraxionConfig when those env vars are unset.

No

NEXT_PUBLIC_AA_API_URL

authentication.aaApiUrloverride; demo reads from env.

No

NEXT_PUBLIC_CODE_ID

authentication.smartAccountContract.codeIdoverride; demo reads from env.

No

NEXT_PUBLIC_CHECKSUM

authentication.smartAccountContract.checksumoverride; demo reads from env.

No

NEXT_PUBLIC_ADDRESS_PREFIX

authentication.smartAccountContract.addressPrefix (demo → xion if unset)

No

NEXT_PUBLIC_RPC_URL

config.rpcUrl

No

NEXT_PUBLIC_REST_URL

config.restUrl

No

NEXT_PUBLIC_GAS_PRICE

config.gasPrice

No

NEXT_PUBLIC_TREASURY_ADDRESS

config.treasury (gasless UX)

No

NEXT_PUBLIC_FEE_GRANTER_ADDRESS

config.feeGranter

No

NEXT_PUBLIC_INDEXER_URL

builds authentication.indexer (with INDEXER_TYPE / INDEXER_TOKEN as in .env.example)

No

NEXT_PUBLIC_TREASURY_INDEXER_URL

authentication.treasuryIndexer.url

No

NEXT_PUBLIC_TURNKEY_ORG_ID

Turnkey providers.tsx only

No

NEXT_PUBLIC_TURNKEY_API_BASE_URL

Turnkey providers.tsx only

Next.js: demo layout uses export const dynamic = "force-dynamic" for runtime process.env. The demo layout.tsx reads AA / wasm from env; if CODE_ID / CHECKSUM are missing in the browser, it logs an error. Your app can instead hardcode or merge the .env.example preset for your chainId and omit those env vars.

Last updated

Was this helpful?