Skip to content

feat: add wallet-providers package + upgrade workspace to @arkade-os/sdk 0.4.39#2

Open
Kukks wants to merge 4 commits into
masterfrom
feat/wallet-providers
Open

feat: add wallet-providers package + upgrade workspace to @arkade-os/sdk 0.4.39#2
Kukks wants to merge 4 commits into
masterfrom
feat/wallet-providers

Conversation

@Kukks

@Kukks Kukks commented Apr 1, 2026

Copy link
Copy Markdown

Summary

  • New @arkade-os/wallet-providers package with browser wallet Identity implementations for UniSat, OKX, Leather, and Phantom
  • UniSat and OKX implement BatchSignableIdentity (batch PSBT signing in one popup)
  • Leather and Phantom implement standard Identity (sequential signing)
  • Shared BrowserWalletIdentity base class handles pubkey normalization, signerSession stubs, and PSBT merge+validation
  • Each provider is independently importable via subpath exports (e.g. @arkade-os/wallet-providers/unisat)
  • Adds signMultiple() to existing SatsConnectIdentity using sats-connect's signMultipleTransactions API for batch signing
  • Upgrades the entire workspace to @arkade-os/sdk 0.4.39 + @arkade-os/boltz-swap 0.3.44 (see "Workspace SDK upgrade")
  • Includes a Vite test app at apps/wallet-providers-test/ for manual browser testing

SDK types

  • BatchSignableIdentity and SignRequest are imported from @arkade-os/sdk (arkade-os/ts-sdk#395, shipped in @arkade-os/sdk >=0.4.15). The local stub definitions in wallet-providers — and the separate local SignRequest in sats-connect — have been removed in favour of SDK imports.
  • @arkade-os/wallet-providers declares @arkade-os/sdk >=0.4.15 as a peer dependency.

Workspace SDK upgrade

Bumps every package and app to the latest SDK + boltz-swap and migrates the breaking changes:

  • @arkade-os/sdk0.4.39 (peers >=0.4.15) across root, checkout, sats-connect, sats-connect-react, snap, xverse.
  • @arkade-os/boltz-swap0.3.44 (peers >=0.3.0) across root, checkout, sats-connect-react, xverse. Required because boltz-swap bundles its own SDK copy — staying on 0.2.x would mix SDK 0.3.x and 0.4.x in the same type graph.
  • Breaking change migrated: boltz-swap renamed ArkadeLightningArkadeSwaps (same constructor + methods). Updated in checkout, sats-connect-react, and apps/metamask-snap.
  • Removed pre-existing dead code in checkout/cli/create.ts (unused identity/SingleKey).

⚠️ Known issue — @arkade-os/snap

@arkade-os/snap cannot bundle SDK 0.4.39: the fee Estimator.eval() method name trips MetaMask Snaps' SES "direct eval" check (SES_EVAL_REJECTED), rejecting the whole bundle. SDK 0.3.0 had no such method. Tracked upstream at arkade-os/ts-sdk#580. The snap stays on 0.4.39 and its build will fail until the SDK renames the method — this is the expected red check on this PR.

Provider matrix

Provider Package PSBT format Batch signing
Xverse (sats-connect) @arkade-os/sats-connect (updated) base64 Yes (signMultipleTransactions)
UniSat @arkade-os/wallet-providers hex Yes (signPsbts)
OKX @arkade-os/wallet-providers hex Yes (signPsbts)
Leather @arkade-os/wallet-providers hex No
Phantom @arkade-os/wallet-providers Uint8Array No

Test plan

  • All packages type-check clean (wallet-providers, sats-connect, sats-connect-react, checkout)
  • All packages + apps build (tsup / vite / next) — except @arkade-os/snap (see Known issue)
  • Manual test with each browser extension using apps/wallet-providers-test/
  • Integration test with real Arkade send (requires signet VTXOs)
  • Re-enable @arkade-os/snap build once arkade-os/ts-sdk#580 lands

Browser wallet provider Identity implementations for the Arkade SDK:
- UnisatIdentity (batch signing via signPsbts)
- OkxIdentity (batch signing via signPsbts)
- LeatherIdentity (single sign only)
- PhantomIdentity (single sign only)

UniSat and OKX implement BatchSignableIdentity, enabling the SDK
to batch-sign all checkpoint + main tx PSBTs in a single wallet popup
(depends on arkade-os/ts-sdk#395).

Includes a Vite test app at apps/wallet-providers-test/ for manual
testing with installed browser extensions.
@vercel

vercel Bot commented Apr 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
arkade-checkout Error Error Jun 24, 2026 7:08am

@arkanaai

arkanaai Bot commented Apr 1, 2026

Copy link
Copy Markdown

🔍 Arkana Review — arkade-os/packages#2

New @arkade-os/wallet-providers package — browser wallet Identity implementations

Clean, well-structured package. The BrowserWalletIdentity base class is a solid abstraction. Key observations:

Architecture ✅

  • Good separation: base class handles pubkey normalization/PSBT merge, each provider only implements its signing API
  • BatchSignableIdentity correctly applied only to UniSat + OKX (wallets that support signPsbts)
  • Subpath exports (/unisat, /okx, etc.) — nice for tree-shaking, consumers only import what they need
  • Dual ESM+CJS output via tsup is correct for a library package

Security

  • PSBT tampering check in mergeSignedPsbt() — comparing unsignedTx before/after merge is the right approach. This prevents a malicious wallet extension from silently altering outputs.
  • Pubkey validation in constructor (32 or 33 bytes) is good

Cross-Repo Dependencies

  • Depends on arkade-os/ts-sdk#395 for BatchSignableIdentity and SignRequest types — currently duplicated locally in types.ts with TODO comments. This is fine for now but should be tracked: once ts-sdk 0.4.15+ publishes, remove the local copies
  • @arkade-os/sdk is correctly a peerDependency (not bundled)

Items to Address

  1. compressedPublicKey() throws on 32-byte x-only keys — If a wallet returns an x-only pubkey (Phantom does this via Uint8Array), calling compressedPublicKey() will throw. If the SDK ever calls this internally, Phantom users will hit an error. Consider prefixing with 0x02 as a fallback, or document that Phantom identity cannot be used in contexts requiring compressed keys.

  2. signMessage() throws unconditionally — Every provider stub throws Error. Some wallets (UniSat, OKX) actually support signMessage(). Since you already have the provider references, these could be wired up. Not blocking, but worth a follow-up.

  3. OKX signPsbts options signature — The OKX API passes a single options array where each element corresponds to a PSBT. Verify OKX actually accepts OkxSignOptions[] as the second arg to signPsbts — some versions expect a different shape. The UniSat implementation looks correct.

  4. Test app: empty PSBT magic bytes — The test app sends 70736274ff01000a0000000000000000000000 which is a valid PSBT header but with an empty global map. Some wallets may crash rather than gracefully reject. Consider adding a note in the UI that errors are expected.

  5. No signMultiple error handling for partial failures — If signPsbts returns fewer results than inputs (some wallets do this on partial reject), the map() in signMultiple() will access undefined elements. Consider validating signedHexs.length === requests.length.

Nits

  • psbtToBase64() is defined but never used — keep or remove?
  • The default re-exports at the bottom of each provider file (export { LeatherIdentity as default }) are unusual alongside the named export. Intentional for dynamic import() usage?

Overall: well-designed, ready for manual testing. The batch signing UX improvement (single popup instead of N popups) is a significant win for Arkade web wallet users.

Adds signMultiple() to SatsConnectIdentity using sats-connect's
signMultipleTransactions callback API. This enables batch signing of
all checkpoint + main tx PSBTs in a single Xverse wallet popup.

Also refactors the merge+validate logic into a shared private method
and threads the network config through to the identity constructor.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 2, 2026

Copy link
Copy Markdown

Deploying snap with  Cloudflare Pages  Cloudflare Pages

Latest commit: 79453f1
Status: ✅  Deploy successful!
Preview URL: https://28dde563.snap-bu9.pages.dev
Branch Preview URL: https://feat-wallet-providers.snap-bu9.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 2, 2026

Copy link
Copy Markdown

Deploying arkade-xverse with  Cloudflare Pages  Cloudflare Pages

Latest commit: 79453f1
Status: ✅  Deploy successful!
Preview URL: https://90cc628e.arkade-xverse.pages.dev
Branch Preview URL: https://feat-wallet-providers.arkade-xverse.pages.dev

View logs

@arkanaai

arkanaai Bot commented Apr 2, 2026

Copy link
Copy Markdown

🔍 Review — Second commit: feat(sats-connect): add signMultiple for batch PSBT signing

Reviewing the delta from 68d0399ef7828b.

What changed

  1. SatsConnectIdentity.signMultiple() — new batch signing method using sats-connect's signMultipleTransactions callback API
  2. mergeAndValidate() extracted — the inline PSBT merge+validate logic from sign() is now a private method, reused by both sign() and signMultiple()
  3. Network threading — constructor now accepts optional SatsConnectNetwork, mapped to BitcoinNetworkType enum via toBitcoinNetworkType()
  4. buildInputIndexArray() extracted — small helper for input index resolution
  5. ArkadeWallet — passes this.config.satsConnectNetwork to the identity constructor
  6. SignRequest + re-exportsSignRequest type defined locally and exported from the package index

Security analysis

mergeAndValidate refactor is safe. The extracted method is byte-for-byte identical to the original inline logic. The unsigned-tx tamper check is preserved — this is critical for preventing wallet extensions from silently altering transaction structure.

signMultiple validates each PSBT individually. Each response goes through mergeAndValidate(), so a malicious wallet extension can't tamper with any individual PSBT in the batch without detection.

⚠️ Constructor signature is now (pubkey, address, request, network?). The 4th param is optional so this is backwards-compatible. ArkadeWallet already passes the network. Good.

toBitcoinNetworkType defaults to Mainnet. Correct — safe default for production, and the test app explicitly targets signet.

Observations

  1. SignRequest type duplication — This is the third place SignRequest is defined (also in wallet-providers/types.ts and will be in @arkade-os/sdk per ts-sdk#395). The TODO comment acknowledges this. Not a problem now but track the cleanup.

  2. signMultipleTransactions callback API — The sats-connect API uses onFinish/onCancel callbacks wrapped in a Promise. This is fine but note that if the wallet extension never calls either callback (buggy extension), this Promise will hang indefinitely. Consider adding a timeout in a future iteration for robustness.

  3. SignMultipleTransactionsResponse type — Assumes the response is an array indexed 1:1 with the input psbts array. This matches the sats-connect docs but there's no explicit length check. A defensive if (responses.length !== requests.length) guard would be cheap insurance.

  4. No BatchSignableIdentity interface — Unlike UnisatIdentity and OkxIdentity in the wallet-providers package, SatsConnectIdentity has signMultiple() but doesn't implement a BatchSignableIdentity interface. This is fine if the SDK does duck-typing ("signMultiple" in identity), but worth aligning once ts-sdk#395 lands.

Verdict

Clean refactor. The merge+validate extraction reduces code duplication without changing behavior. The batch signing implementation correctly validates each PSBT individually. The network threading is a good addition for multi-network support.

Ship it once ts-sdk#395 is merged and the SignRequest/BatchSignableIdentity imports are switched from local definitions to SDK imports.

… 0.4.39

BatchSignableIdentity and SignRequest were stubbed locally pending
arkade-os/ts-sdk#395, which is now merged and published in
@arkade-os/sdk >=0.4.15. Re-export them from the SDK and drop the stubs.

- types.ts: re-export SignRequest/BatchSignableIdentity from @arkade-os/sdk
- package.json: peerDependency >=0.4.15, devDependency ^0.4.39
Bumps every package and app to the latest SDK (0.4.39) and boltz-swap
(0.3.44), and migrates the breaking changes:

- sats-connect: source SignRequest from the SDK (drop local stub)
- checkout, sats-connect-react, metamask-snap: rename boltz-swap
  ArkadeLightning -> ArkadeSwaps (renamed in boltz-swap 0.3.x)
- checkout/cli: remove dead unused identity/SingleKey (pre-existing
  typecheck error, unrelated to the bump)

Verified: every package and app typechecks + builds EXCEPT @arkade-os/snap.
The snap cannot bundle SDK 0.4.39 because the fee Estimator.eval() method
trips MetaMask's SES direct-eval check (arkade-os/ts-sdk#580). Left on
0.4.39 pending the upstream rename.
@Kukks Kukks changed the title feat: add @arkade-os/wallet-providers package feat: add wallet-providers package + upgrade workspace to @arkade-os/sdk 0.4.39 Jun 24, 2026
@pietro909 pietro909 self-requested a review June 29, 2026 08:05
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