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

Best Practices

Patterns, pitfalls, and production-ready examples for building on MOSS.

Patterns, pitfalls, and production-ready examples for shipping MOSS in production.

UX Patterns

1. Initialise Early, Not on Click

The SDK creates an iframe and establishes a Penpal connection — this takes a moment. If you initialise on button click, users feel the delay. initialise() is idempotent (the SDK tracks an internal flag), so calling it at app boot and again later is safe.

// DO this — initialise when your app loads
// app.ts or main.ts
import { mega } from '@megaeth-labs/wallet-sdk';

await mega.initialise({ network: 'mainnet' });

// DON'T do this — initialise on button click
connectButton.onclick = async () => {
  await mega.initialise({ network: 'mainnet' }); // Delay here
  await mega.connect();
};

2. Always Subscribe to Status Changes

Connection state can change outside your app, including direct actions from wallet UI. Subscribe once and keep your UI state in sync.

3. Handle Every Transaction Result

Transaction methods return a status field with three outcomes: approved, cancelled, error. Handle all three explicitly — cancelled is not an error, so don't show error toasts when users deliberately cancel.

4. Design Permissions Narrowly

Session key permissions are powerful. Keep scope as tight as possible from day one: specific contract scope, low spend limits, short expiry. Avoid wildcard calls, high monthly spends, and long-lived grants. Expose revoke controls in your app — users can also revoke per-app from wallet settings.

Key rules: keep expiry short (24h for active sessions, 7 days max for background agents), scope every calls[] entry with both to and signature, and use the smallest spend limit your flow can tolerate.

5. Silent Mode Requires Granted Permissions

silent: true skips approval UI for callContract(). It only works after valid permission grants cover the action. Without valid permissions, the wallet falls back to approval UI.

6. Next.js and SSR

initialise() creates a DOM iframe, so it must run in the browser. Either gate it behind useEffect in a 'use client' provider, or use the React SDK which handles the client lifecycle for you.

Or use the React SDK:

Security Hardening

7. Sponsor Gas with a Paymaster

Sponsorship is configurable. Choose a mode and fee token that matches your product risk model. Start with app-only + native; move to explicit if you only want limited sponsorship windows.

Mode
Who pays
Who controls logic
When to use

app-only (default)

Developer sponsor balance

Sponsor endpoint + app-initiated requests

Most production partner integrations.

explicit

Developer sponsor balance

Sponsor endpoint + per-request sponsorship intent

Sponsor only setup/first-run actions.

everything

Developer sponsor balance

Sponsor endpoint for all activity

Testing only; not recommended for production.

Configure sponsorship during initialise:

Full implementation details: Paymaster Guide →.

8. Server-Side Verification

Use @megaeth-labs/wallet-server-verify for backend signature verification and SIWE challenge validation.

Error
What it means
Action

DIFFERENT_MESSAGE

Signed payload does not match what your backend generated.

Reject request and issue a fresh challenge.

INVALID_SIGNATURE

Signature does not match payload.

Reject request and require re-sign.

For agent-driven flows with delegated permissions, see AI Agent Guide. For full method-by-method reference, see Methods Reference.

Last updated