Reimplement Pirate Chain plugin over react-native-pirate-wallet - #1055
Reimplement Pirate Chain plugin over react-native-pirate-wallet#1055j0ntz wants to merge 10 commits into
Conversation
9df27fb to
c26cdcb
Compare
c26cdcb to
c2a610d
Compare
c2a610d to
7049511
Compare
|
Simulator-tested update (force-pushed as part of the single commit):
Upstream blocker found while testing: block sync still cannot progress through this binding. |
7049511 to
0481ded
Compare
|
End-to-end sync + send verified on the iOS simulator (with a locally rebuilt pirate core carrying the one-line persistent-runtime fix):
Two more findings, both addressed in the latest force-push:
|
peachbits
left a comment
There was a problem hiding this comment.
Two non-blocking suggestions on the new react-native-pirate-wallet integration, both at the native-bridge boundary. The plugin reimplementation reads cleanly otherwise.
a0927f1 to
beaae5d
Compare
The piratechain team's orchard upgrade replaces the zcash-cloned react-native-piratechain SDK with a wallet-registry based SDK (react-native-pirate-wallet) whose lightwalletd endpoint, checkpoints, and spending keys live inside the native core. Rebuild the engine, tools, and yaob io bridge on that API: wallets are restored into the SDK registry under the Edge walletId alias, sync progress comes from the SDK's polling synchronizer, transactions map from signed fee-inclusive amounts, and sends go through the registry wallet instead of passing the mnemonic per spend.
The Pirate Unified Light Wallet v1.1.5 release ships the merged upstream fixes and finalizes the wire format the plugin targets. Serialize amounts as decimal strings end to end so balances and sends above 2^53-1 arrrtoshi keep full precision, and drive sends through the SDK's send() now that it keeps the opaque build/sign/broadcast payloads verbatim. Replace the removed global app-passphrase flow with per-wallet configureAccountStorage so each local wallet lives in its own registry namespace unlocked by a passphrase derived from that wallet's seed instead of a shared hardcoded one. Type native bridge errors as unknown to match what the RN bridge actually delivers.
2cbed88 to
6d4e32d
Compare
The SDK's configureAccountStorage selects the wallet registry globally: one namespace is active at a time, and switching cancels any running sync and clears the registry and block caches. Per-wallet namespaces therefore left only the last-selected ARRR wallet syncing, with the others' pollers reading the wrong namespace, and gave up the shared block cache. Configure a single device-scoped registry once, key every wallet by alias inside it, and let each wallet's synchronizer run concurrently. Its passphrase is a random per-device secret minted from io.random and kept in the plugin's local storage, replacing the seed-derived HMAC, which cannot key a registry that holds many wallets. Wallet-free reads use the device registry, so the throwaway probe namespace is gone. Also expose the synchronizer status from the bridge and read it once after the engine subscribes, so a SYNCED that fires before subscription cannot strand the engine at STOPPED.
Rewrite the storage section and decisions 1 and 3 to the shipped model, and record the phase-4 divergence from the per-wallet namespaces phase 2 built.
6d4e32d to
76bb601
Compare
The SDK bakes in a default lightwalletd and never consults the plugin's networkInfo, so every wallet scanned against that default. When that node stops serving blocks the failure is silent and total: test_node still succeeds and the chain tip still resolves, so the app shows 'Sync in Progress, 0% Complete' forever with no error, while the scan sits in the Headers stage at zero blocks per second. Pass the configured node down to makeSynchronizer and apply it with set_lightd_endpoint before the synchronizer starts. The configured port moves from 443 to the node's plain gRPC port, which is what the SDK speaks; test_node fails against https on 443 and succeeds on 9067.
59e95bb to
a58a7ed
Compare
25992e1 to
983e6b0
Compare
983e6b0 to
70ea0d9
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 70ea0d9. Configure here.
The Pirate team published unified wallet v1.1.6 as react-native-pirate-wallet 0.3.0, with all four native sidecars. It sets the Ironwood activation height, ships their Supernova sync engine, and fixes several sync issues. The wrapper's JS surface is byte-identical to 0.2.1, so the plugin needs no reconciliation: the whole delta is native, and the peer range is the only thing that has to move.
494248a to
b9d763e
Compare
Records the 0.3.0 round: the broadcast timeout is gone (2.08s end to end, against roughly five minutes ending in a gRPC timeout on 0.2.1), sync runs about 27x faster on the Supernova engine, and the release's whole delta is native. Adds sections for Ironwood activation, which is what makes shipping this pair time-sensitive, and for the arm64 link ceiling that still blocks the merge. Retires the stale non-goal that deferred the v1.1.6 bump.
b9d763e to
54b8a1f
Compare













Technical Design Document
piratechain-sdk-v115-reconcile.md, committed on this branch. It holds the design, every decision with its rejected alternatives, the phase history, and the test evidence. Read it instead of a long description here.
CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Description
Asana: https://app.asana.com/0/1215088146871429/1214721783909451
Reimplements the Pirate Chain plugin over
react-native-pirate-wallet(unified wallet v1.1.6, npm0.3.0), the Pirate team's replacement for thereact-native-piratechainmodule Edge wrote. In the old module the Swift and Rust layers each opened the wallet's SQLite database and the app crashed when they overlapped, which is why unrelated work has to setpiratechain: falsein the GUI'scorePlugins.ts. The new SDK keeps all database access in Rust, and this branch retires that workaround.The plugin's public shape and the engine's transaction mapping are unchanged. What is new:
list_transactions. Amounts cross the wire as decimal strings, and sends go through the SDK'ssend().set_lightd_endpoint. Without it a wallet scans against the SDK's baked-in default, which now refuses connections outright, and the app sits at 0% sync with no error anywhere.getLatestNetworkHeighttakes the chain tip from a registered wallet or fromtest_node, falling back to the create-and-delete probe only when the registry is empty. Running that probe while a synchronizer is live panics the native service and aborts the app.Paired with EdgeApp/edge-react-gui#6021, which swaps the GUI dependency and has to land after this one publishes.
Verified on the iOS simulator: a funded ARRR send reached the transaction-success scene (txid
8d2e25d0e624cf714057b65311347a8a5d21cafbbae8f579e714fb979e94a579, 2.083 seconds from build to broadcast), both wallets sync, a resync ran at about 47,700 blocks/sec, and the mocha suite is 490 passing. Section 7 of the doc has the full numbers and what stayed uncovered.Note
High Risk
This is a full native SDK and wallet-storage swap for ARRR—sync, spend, registry passphrase handling, and lightwalletd routing all change—and incorrect endpoint or registry behavior can strand wallets at 0% sync or block spends; Ironwood readiness depends on pinning v1.1.6.
Overview
Replaces
react-native-piratechainwithreact-native-pirate-wallet(unified wallet v1.1.6, peer^0.3.0) and rewrites the native IO bridge and engine around the SDK’s encrypted wallet registry and polling synchronizer.Device-scoped registry: One
configureAccountStoragenamespace (edge-pirate-device) holds every ARRR wallet keyed by wallet-id alias; a random 32-byte passphrase is minted on the core side (piratechainDeviceStorage.ts) and passed to the bridge viasetDevicePassphrase. Multiple wallets can sync concurrently on a shared block cache without namespace switching.Sync and history: Transaction history no longer uses block-range paging in
otherData; the engine processes the SDK’s fulllist_transactionslist with a per-txid height cache. Balances and txs use string amounts end-to-end; sends go throughwalletSdk.send()instead of raw build/sign/broadcast invoke. A one-timegetStatus()backstop avoids staying stuck atSTOPPEDifSYNCEDfires before subscriptions attach.lightwalletd: Each wallet gets
set_lightd_endpointwith the plugin’slightwalletdUrl(http://lightd1.pirate.black:9067plain gRPC), because the SDK ignores pluginnetworkInfoand its baked-in default node is unreachable or non-serving.Adds local
rnPirateWallet.d.tstypings and a long design doc;package-lockdrops the old piratechain dev dependency.Reviewed by Cursor Bugbot for commit 25992e1. Bugbot is set up for automated code reviews on this repo. Configure here.