Skip to content

EIP-712 & Passkey wallets#96

Draft
frol wants to merge 345 commits into
azbang:mainfrom
NEAR-DevHub:eip712
Draft

EIP-712 & Passkey wallets#96
frol wants to merge 345 commits into
azbang:mainfrom
NEAR-DevHub:eip712

Conversation

@frol

@frol frol commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

This is a draft version of WalletConnect support through Wallet Contracts on NEAR taking EIP-712 signed message payload as "NEAR transaction".

It is based on DefuseLabs' WalletContract which also implements NEP-641 (signMessage for contracts)

There are still a few unresolved design items, which is why I will keep it as draft, but we have actually launched it in https://trezu.org (and will have to migrate users after we address the pending issues)

azbang and others added 24 commits April 9, 2026 15:02
Enable `signDelegateActions` in NEARMobile manifest
Add Privy Wallet connector manifest and provide manifest to sandbox wallet on ready()
Export EventMap, EventType, and Account types
Ship Agent Skills (near-connect-quickstart, near-connect-transactions)
via TanStack Intent so AI coding agents can auto-discover correct
@hot-labs/near-connect usage patterns. Updates package.json files array,
adds tanstack-intent keyword, and adds README section for consumers.
srcdoc iframes inherit the parent's Content Security Policy, so inline
scripts inside the sandbox are blocked when the parent uses nonce-based
CSP (script-src 'nonce-X'). Add a cspNonce option that propagates the
parent's nonce to both <script> tags in the srcdoc iframe, allowing
them to execute while preserving CSP enforcement.
feat: add TanStack Intent skills for AI agent discoverability
feat: add cspNonce option for nonce-based CSP compliance
Three related bugs caused the NEP-641 sign flow to abort right after
Connect on mobile and Ledger Live, before the user could sign:

1) Open-handler echo loop in SandboxedWallet/executor.ts

   The sandbox "open" RPC registered a window message forwarder that
   relays cross-window messages back into the iframe when the panel's
   origin matches `ev.origin`. For wallet deeplinks (`ledgerlive://`,
   `metamask://`, etc.) `window.open` returns `null` and
   `new URL(deeplink).origin === "null"` — the same string the
   sandboxed iframe uses for its own outgoing messages. Every
   selector.call message the iframe sent was therefore echoed back to
   itself, resolving the call promise with `event.data.result === undefined`
   long before WalletConnect could deliver the real response.

   Fix: only attach the forwarder when `window.open` actually returned a
   popup, ignore self-messages (`ev.source === iframe.contentWindow`),
   and skip when the parsed URL origin is `"null"`.

2) wcConnect raced its own cancellation in eip712-wallet.ts

   `modal.subscribeModal({ open: false }) → reject("User cancelled
   pairing")` fired on every modal close — including when the wallet
   app auto-closes the modal after the user approves pairing on mobile
   and Ledger Live. Drop the subscribeModal cancel; rely on the
   "Use a different wallet" button + indefinite getSession polling.

3) Stale persisted WC session shadowed the new pairing

   WC v2 stores sessions in localStorage. On the next sign-in attempt
   getSession returned the dead topic, the poll resolved early, and
   eth_signTypedData_v4 was routed to a session no wallet was actually
   bound to. Disconnect the persisted session before pairing and
   snapshot/skip the stale topic in the poll for belt-and-suspenders.

Also tightened a few small spots:
- example/src/App.tsx: hoist SignClient.init to a module-level singleton
  so React StrictMode's double-mount doesn't create two SignClient
  instances (the "Pending session not found for topic" log).
- resolveAuth now throws a clear "Wallet returned no signature" error
  instead of crashing on `sigHex.replace` when the wallet returns
  undefined.
- IframeExecutor: expose a `contentWindow` getter so the new
  self-message check doesn't have to reach into a private field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.