Skip to Content
Squid ModeSquid for Apps (SDK)

Squid for Apps

initWaaPSquid returns one container of chain facades backed by Squid dWallets. The facades you select share a single wallet iframe and a single authenticated session, so a user logs in once and can sign on every chain you asked for.

Quick start

import { initWaaPSquid, WAAP_EVENTS } from '@human.tech/waap-sdk' // `chains` is required and must name at least one facade. const waap = initWaaPSquid({ chains: ['evm', 'sui'] }) // 1. Authenticate. Safe to call on startup: it checks the existing session // first and only opens the login screen when there isn't one. await waap.session.login() // 2. Create or restore the Squid dWallets. This step is explicit. await waap.squid.onboard() // 3. Sign. const [address] = (await waap.evm.request({ method: 'eth_requestAccounts' })) as string[] // Release the facade when the owning UI unmounts. waap.destroy()

Onboarding is explicit and must happen after login. Connecting or signing through a Squid facade before onboard() will fail. Squid never provisions dWallets implicitly. This is deliberate: creating a dWallet is an on-chain operation, not a side effect of rendering a Connect button.

Selecting chains

chains is required and must name at least one facade. Only the chains you name are present on the returned object, and the type reflects that. Reading an unnamed facade is a compile error, not a runtime undefined.

const waap = initWaaPSquid({ chains: ['evm', 'solana'] }) waap.evm // available waap.solana // available waap.sui // compile error — not selected

Naming the facades is deliberate rather than defaulting to all three: the old default loaded the Sui and Solana surfaces for callers that only ever used EVM. chains scopes which SDK surfaces load, not the dual-curve provisioning transaction, which always covers both curves.

The facade

MemberPurpose
evm / sui / solanaChain facades, present according to chains. ethereum is an alias for evm.
squid.onboard()Create or restore the Squid dWallets for both curves.
squid.getStatus()Read the current lifecycle without triggering onboarding.
squid.onboardWithStatus()Onboard and return the immediately observable status.
sessionAuthentication, status, and lifecycle events.
getAccountStatus()Combined local status for the initializer.
preload()Mount the iframe and finish its handshake without opening wallet UI.
destroy()Release every facade and the shared iframe.

waap.onboard() is a shorthand for waap.squid.onboard().

waap.ethereum is an alias for waap.evm and is not going away. It is what the published integrations use. Prefer evm: it matches the chains value that produced the facade, and the facade serves every EVM chain rather than Ethereum specifically.

waap.auth is different. A deprecated alias for the session surface that exists only when all three chains are selected. Use waap.session.

Every facade shares one authentication lifecycle, so waap.evm.login(), waap.sui.login(), waap.solana.login(), and waap.session.login() are the same call. session.login() is the chain-neutral spelling and the one to reach for, but a facade call is not broken.

squid.getStatus() reports absent, provisioning, awaiting-network, active, or failed.

Tracking the lifecycle

Onboarding is asynchronous and involves an on-chain operation, so surface its progress rather than blocking your UI on it.

import { WAAP_EVENTS } from '@human.tech/waap-sdk' waap.session.on(WAAP_EVENTS.squidPending, () => showSpinner()) waap.session.on(WAAP_EVENTS.squidReady, () => enableSigning()) waap.session.on(WAAP_EVENTS.squidFailed, ({ message }) => showError(message))
ConstantEvent name
WAAP_EVENTS.squidPendingwaap_squid_pending
WAAP_EVENTS.squidReadywaap_squid_ready
WAAP_EVENTS.squidFailedwaap_squid_failed

getSquidStatus() returns the same state synchronously:

const { state, operationId, transactionDigest, message } = waap.getSquidStatus()

operationId and transactionDigest identify the provisioning operation and are safe to log or display.

In React

import { initWaaPSquid, useWaapAuth } from '@human.tech/waap-sdk' const waap = initWaaPSquid({ chains: ['evm', 'sui', 'solana'] }) function SignButton() { const auth = useWaapAuth(waap.session) return ( <button disabled={!auth.squidReady} onClick={send}> {auth.squidReady ? 'Send' : 'Preparing wallet…'} </button> ) }

useWaapAuth(waap.session) exposes squidStatus plus the derived isConnected, isPending, squidReady, error, address, suiAddress, and solanaAddress fields. squidReady is true once the lifecycle reaches active.

Startup performance

Initialize the facade once for the lifetime of the embedding UI. Do not create and destroy it per Connect click. Squid coalesces the selected facades’ setup into one iframe request, so preload() warms all of them together:

import { initWaaPSquid, preloadWaaPOnIdle } from '@human.tech/waap-sdk' const waap = initWaaPSquid({ chains: ['evm', 'sui', 'solana'], deferIframe: true }) const cancelPreload = preloadWaaPOnIdle(waap) // UI teardown cancelPreload() waap.destroy()

preload() never opens wallet UI and never creates a Squid account. It only completes the non-interactive handshake. Call it after your page’s LCP.

What stays the same

Squid changes where key material lives, not how requests are reviewed. Every Squid transaction goes through the same authorization gate as standard mode: exact chain bytes are verified before any decision, the Policy Engine authorizes against the user’s limits, and a single-use approval names one transaction. Privileges work in Squid mode via withPT: true, exactly as they do in standard mode. On eth_sendTransaction / eth_signTransaction for EVM, signTransaction / signAndExecuteTransaction for Sui, and signTransaction / signAndSendTransaction for Solana. It is ignored on message signing.

Last updated on