Skip to content

feat(wallet-sdk): initial release of @abstract-foundation/wallet-sdk - #30

Merged
coffee-the-dev merged 2 commits into
mainfrom
coffee/wallet-sdk
May 8, 2026
Merged

coffee-the-dev merged 2 commits into
mainfrom
coffee/wallet-sdk

Conversation

@coffee-the-dev

@coffee-the-dev coffee-the-dev commented May 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Initial release of @abstract-foundation/wallet-sdk — a new dApp-side SDK that lets any web app embed the Abstract Global Wallet on third-party origins via an iframe (with automatic popup fallback). Mirrors the security model of Porto, adapted for the AGW + Privy stack.

The wallet host (the page that actually runs inside the iframe) is a separate app currently in flight. This SDK ships the dApp-side primitives so it can be consumed as soon as the host is up.

What's in the box

import { createWallet } from '@abstract-foundation/wallet-sdk';

const wallet = createWallet({
  host: 'https://wallet.abs.xyz',
  chainId: 2741,
  dialog: 'auto',  // 'auto' | 'iframe' | 'popup'
});

// EIP-1193 — drop straight into wagmi/viem/ethers
const accounts = await wallet.provider.request({ method: 'eth_requestAccounts' });

Lower-level primitives are exposed at @abstract-foundation/wallet-sdk/core:

import { Dialog, Messenger, UserAgent, IntersectionObserver }
  from '@abstract-foundation/wallet-sdk/core';

Security highlights (defense-in-depth from Porto)

  • Hardened iframe attrs pinned: sandbox="allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" and allow="payment; publickey-credentials-{get,create} <walletOrigin>; clipboard-write" (clipboard-write skipped on Firefox).
  • Top-layer <dialog>.showModal() mounting — z-index stacking attacks fail; ESC always closes; backdrop is rendered for free.
  • Origin-validated postMessage on every inbound message; outbound targetOrigin is required (refuses to ever post to *). Branded envelopes (abs: 1) so foreign messages on the same origin can't spoof.
  • Ready handshake + request IDs prevent response substitution and replay against pending requests.
  • WebAuthn-aware fallback — Safari blocks navigator.credentials.create in iframes, so wallet_connect and eth_requestAccounts automatically route through a popup on Safari.
  • IO-v2 eligibility check in Dialog#secure — combined with the wallet host's trusted-host allowlist, the dApp side decides whether iframe mode is safe; the actual isVisible-based pointer-event lockdown lives inside the wallet host (delivery-mechanic concern, doesn't belong in the SDK).
  • MutationObserver strips inert attributes injected onto the dialog by browser extensions (well-known issue with 1Password and similar).

Verification

  • pnpm typecheck — clean
  • pnpm build — ESM + CJS dual emit clean
  • pnpm test — 8/8 (origin filtering, brand-envelope rejection, send-without-origin refusal, UA detection)
  • pnpm test:build — publint clean (same suggestions agw-react/agw-client already ship with), attw --pack --ignore-rules false-cjs all green for node10, node16 (CJS+ESM), and bundler resolutions
  • Biome lint clean against the abstract-packages config

Out of scope (follow-ups)

  • /elements — Lit-based Custom Elements (<abs-wallet-button>, <abs-balance>, etc.) so any framework can embed widgets, not just React. Addresses the long-standing AGW criticism of being React-only.
  • /react — auto-generated @lit/react wrappers + hooks over the same elements.
  • Wallet host application — the app at wallet.abs.xyz that this SDK talks to. Internal repository; in flight.

Notes

  • Initial version is 0.1.0 (changeset = minor) — pre-1.0 because the wallet host isn't deployed yet, but the surface area is intentionally tight and ready to be tagged.
  • Test layout matches agw-client (test/src/**/*.test.ts with vitest -c ./test/vitest.config.ts).
  • package.json exports / build scripts mirror agw-client and agw-react. provenance: true set so npm provenance tags publish correctly under the existing OIDC workflow.

@vercel

vercel Bot commented May 7, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
agw-nextjs Ignored Ignored Preview May 8, 2026 1:05am
mpp-demo Ignored Ignored Preview May 8, 2026 1:05am

Request Review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Framework-agnostic SDK for embedding the Abstract Global Wallet on
third-party origins via iframe (with popup fallback). Ports the
security-relevant pieces of Porto to the Abstract stack.

What ships:
- createWallet({ host, chainId, dialog }) returning an EIP-1193 provider
- iframe() / popup() dialog factories with hardened sandbox + allow attrs:
    sandbox="allow-forms allow-scripts allow-same-origin
             allow-popups allow-popups-to-escape-sandbox"
    allow="payment;
           publickey-credentials-get   <walletOrigin>;
           publickey-credentials-create <walletOrigin>;
           clipboard-write"
- Top-layer <dialog>.showModal() mounting so z-index attacks fail and ESC
  always closes
- Origin-validated postMessage messenger with branded envelopes (abs: 1),
  ready handshake, request-id correlation. Refuses to ever post to '*'.
- WebAuthn-aware iframe → popup fallback (Safari blocks WebAuthn credential
  creation in iframes for wallet_connect / eth_requestAccounts)
- IntersectionObserver-v2 feature detection used by the parent-side
  secure() eligibility check; the actual visibility wrapper lives in the
  wallet host application (delivery-mechanic concern)
- MutationObserver defending against extensions injecting `inert` onto the
  dialog (1Password and similar)
- Pending-request map redelivered against the new transport on mode switch

Public API:
  import { createWallet } from '@abstract-foundation/wallet-sdk';
  import { Dialog, Messenger, UserAgent, IntersectionObserver }
    from '@abstract-foundation/wallet-sdk/core';

Verified: pnpm typecheck, pnpm build, pnpm test (8/8), pnpm test:build
(publint clean, attw all green).

Web Components (/elements) and React wrappers (/react) ship in follow-up
releases.
AGW does not use WebAuthn for wallet signing or account creation, and Privy
passkey enrollment only happens in the main Abstract portal app under
account management — never inside the iframed wallet. So forcing every
Safari user into popup mode for `wallet_connect` / `eth_requestAccounts`
on the chance that they might be enrolling a passkey is over-eager: it
hurts UX for the Safari users who sign in with email + OTP / social /
external wallet (the majority).

Returning users with passkeys log in via `navigator.credentials.get()`,
which works in cross-origin iframes when the `publickey-credentials-get`
permission is granted (set automatically by `Dialog.iframe()`'s `allow`
attribute, which is unchanged by this commit).

Removed:
- SAFARI_WEBAUTHN_METHODS constant in Wallet.ts
- The Safari/WebAuthn check in pickInitialMode (now just iframe vs popup
  based on the configured mode)
- The orphaned `UserAgent` import in Wallet.ts

Kept:
- iframe `allow="payment; publickey-credentials-{get,create} <origin>;
  clipboard-write"` policy — `get` is needed for passkey login, `create`
  is harmless and future-proofs us
- The messenger-driven `__internal { type: 'switch', mode: 'popup' }`
  channel — the wallet host can still request a runtime switch for any
  reason (including future flows that genuinely need WebAuthn create)

Docs / changeset updated to match. All gates re-verified: typecheck,
build, 8/8 tests, publint, attw all green.
@coffee-the-dev
coffee-the-dev merged commit 63cd1e9 into main May 8, 2026
18 checks passed
@coffee-the-dev
coffee-the-dev deleted the coffee/wallet-sdk branch May 8, 2026 01:11
@abstract-release-bot abstract-release-bot Bot mentioned this pull request May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant