Upgrade Arkade SDKs and harden Ark wallet integration#8585
Conversation
Hook the lightning-ark wallet up to the new Arkade SDK repositories layer, introduce the Realm-backed Arkade adapter instance, register the delegate contract via RestDelegatorProvider on Wallet.create, and set the Boltz swap referral.
Tighten Realm-backed Arkade adapter setup so the database lifecycle is deterministic across wallet import, app boot, and tests. Fix integration tests to handle Realm persistence in mocks and proper initialization in wallet-import.
…nd wallet history
Surface per-swap claim and refund controls, restore swaps on wallet import, drop the racing Claim CTA in the LN invoice view (show a Receiving spinner and let SwapManager events drive UI state), and keep the transactions header mounted so the list does not jump on scroll.
Wire iOS/Android background task plumbing for Ark swap monitoring, surface actionable swap notifications via the notification suppression repository, and drop the racing Electrum probe from SelfTest.
Add unit and integration coverage for the lightning-ark wallet's contract with the Arkade SDK (derivation, sync, swaps); refresh SDK fixture set.
Stabilize the e2e suite on real devices: unstall Detox iOS sync on NotificationSettings, skip the Arkade indexer stream in iOS sync, and tighten the wallet-discovery / import / watch-only e2e flows.
# Conflicts: # package-lock.json # package.json # screen/transactions/TransactionStatus.tsx
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
✅ Build 8.0.0 (1779435704) has been uploaded to TestFlight and will be available for testing soon. |
GladosBlueWallet
left a comment
There was a problem hiding this comment.
The pending pill has been taught to confuse dead history with live state. Ark failed/refunded rows still set ispaid false, so this carousel will keep shouting pending long after the swap is dead. State machines are not decorative murals.
| // never depend on a Lightning shape. | ||
| const isLightningShaped = item.type === LightningCustodianWallet.type || item.type === LightningArkWallet.type; | ||
| const hasPendingTx = isLightningShaped | ||
| ? item.getTransactions().some((tx: any) => tx.ispaid === false) |
There was a problem hiding this comment.
This treats terminal Ark history as pending because getTransactions() now leaves ispaid false for Failed: and Refunded: rows. After a failed/refunded swap, the wallet card will stay on pending until the row disappears. The state machine is lying to the UI.
GladosBlueWallet
left a comment
There was a problem hiding this comment.
The lint fix is acceptable. Compressing the array into one line is aesthetically dubious, but the repo’s 140-column ceiling survives, so this chamber remains functional.
| if (this._wallet) { | ||
| this._transactionsHistory = await this._wallet.getTransactionHistory(); | ||
| const balance = await this._wallet.getBalance(); | ||
| this.balance = balance.available; |
There was a problem hiding this comment.
Should it be balance.available or balance.total ?
There was a problem hiding this comment.
I recall a discussion about this with @GladosBlueWallet and the rule is that BlueWallet shows the available balance (ie: anything you can spend).
There was a problem hiding this comment.
glados is a bot and cant discuss btw
|
✅ Build 8.0.0 (1779716609) has been uploaded to TestFlight and will be available for testing soon. |
Flag failed/refunded/expired swap rows in getTransactions and gate the carousel pending pill on it, so a dead swap no longer pins the card to pending forever.
|
✅ Build 8.0.0 (1779719904) has been uploaded to TestFlight and will be available for testing soon. |
|
✅ Build 8.0.0 (1779721906) has been uploaded to TestFlight and will be available for testing soon. |
Restore flat header structure so the context-menu native view gets its Yoga frame instead of drawing at origin.
Both conflicts resolved by keeping this branch's versions, which deliberately diverged for New Architecture / Detox reasons that bw/master's changes would regress: - components/TransactionsNavigationHeader.tsx: kept our ActionSheet-based Manage Funds button. It avoids ToolTipMenu because react-native-context-menu-view mispositions under Fabric (overlapping the wallet label); bw/master's "FIX: Manage funds layout" keeps ToolTipMenu inside a balanceSection wrapper. - screen/settings/SelfTest.tsx: kept our removal of the BlueElectrum network self-test (network calls + live timers hang Detox/FabricTimersIdlingResource on CI); bw/master's "REF: blue electrum" only refactored that block.
|
✅ Build 8.0.0 (1779956793) has been uploaded to TestFlight and will be available for testing soon. |
|
✅ Build 8.0.0 (1779958351) has been uploaded to TestFlight and will be available for testing soon. |
getTransactions() merged three feeds (Boltz swaps, boarding UTXOs, SDK history) and reconciled the swap overlay against the SDK rows with a fragile fingerprint matcher, so any timestamp skew surfaced one settlement twice — e.g. a refill also showing as a phantom "Lightning" row of the same amount. Rebuild it: getTransactionHistory() is the single source of rows (boarding entry -> Refill via TxKey.boardingTxid, everything else -> native Lightning leg). Settled swaps enrich their matching native leg in place and emit no row of their own; only non-settled swaps that need visibility (claimable/in-flight/failed/refunded, plus open invoices for the registry) emit a swap- row. A settlement can no longer appear both as its native leg and as a swap- row, regardless of timestamp skew. isInvoiceGeneratedByWallet() now answers from _swapHistory directly so a settled invoice stays recognizable after its row is enriched onto the leg.
|
✅ Build 8.0.0 (1779967377) has been uploaded to TestFlight and will be available for testing soon. |
|
✅ Build 8.0.0 (1779977368) has been uploaded to TestFlight and will be available for testing soon. |
getTransactionHistory() reports a swept boarding refill TWICE: once as the boarding leg (key.boardingTxid) and once as the round key.commitmentTxid that sweeps it into a VTXO — both RECEIVED, same amount, minutes apart, the commitment leg carrying no arkTxid. Pass 1 of getTransactions() routed them to two rows: a "Refill" and a phantom "Lightning" leg of the same amount. Pre-collect the boarding fingerprints, then drop the commitment-sweep twin: a RECEIVED entry keyed only by commitmentTxid (no arkTxid) that matches a boarding fingerprint within the match window is the sweep, already represented by the Refill row. Fingerprints are consumed once so each refill drops exactly one twin; genuine arkTxid receives/sends are untouched. Downstream workaround for an SDK bug: the SDK's own commitmentsToIgnore de-dup misses when the boarding output's on-chain spender txid differs from the resulting VTXO's commitmentTxId. Remove once fixed upstream.
|
✅ Build 8.0.0 (1780002401) has been uploaded to TestFlight and will be available for testing soon. |
The consumer-side fingerprint pre-pass that collapsed duplicate boarding + commitment-sweep rows into one Refill entry is no longer needed. arkade-os/ts-sdk#531 (released in 0.4.32) fixes commitmentsToIgnore de-dup at the source.
|
✅ Build 8.0.0 (1780032985) has been uploaded to TestFlight and will be available for testing soon. |
Manage Funds -> Refill had two issues: 1. A refill appeared immediately as a completed "Received / Refill" row and the headline balance jumped right away. fetchBalance() used SDK balance.total (offchain + boarding), so an unconfirmed boarding deposit inflated the balance before it was usable, and the pending boarding row (boarding-utxo-...) rendered as a confirmed receive. 2. After the deposit confirmed, the balance briefly showed ~2x the refill. getBalance().total = boarding(confirmed+unconfirmed) + offchain; during settlement the boarding UTXO is still unspent in getCoins() while its freshly-minted preconfirmed VTXO is already counted, so total double-counts the refill until getCoins() drops the spent UTXO. Fix: headline balance is now available + recoverable (= total minus boarding.total) in both fetchBalance() and the swap-event handler, so a refill enters the balance once, at settlement. Refill rows render as "Pending" until settlement promotes them to a settled "Refill" row, and the detail screen (resolveTxDisplayState) is kept in parity. A dedup guard prevents one refill from showing as both settled and pending if the SDK feeds momentarily disagree. Matches the reference wallets (../wallet preconfirmed:!settled, ../trixie-wallet headline = available).
|
✅ Build 8.0.0 (1780172917) has been uploaded to TestFlight and will be available for testing soon. |
…-chain detail Settled swaps are emitted as enriched native Ark legs (type 'bitcoind_tx', synthetic 'ark-' id) that carry the swap's invoice payload. TransactionListItem routed taps by type, so these missed the invoice branch and fell through to the on-chain TransactionStatus screen. Route on 'payment_request' presence instead, in both onPress and the long-press Details path, so enriched legs reach LNDViewInvoice while refills and pure Ark transfers (no payload) keep the on-chain detail. LNDViewInvoice gains an amount fallback to abs(value): an enriched leg has no 'amt', so the settled success view would otherwise render 0 sats. Locks the data contract with four unit assertions: enriched settled swaps carry payment_request; refill rows do not.
On master, Refill / Pending refill rows (type 'bitcoind_tx', no hash, no txid) are not tappable — tapping is a no-op. This branch gave them synthetic boarding txids and a txid -> TransactionStatus tap branch, so they began opening the on-chain detail. Gate that branch on the txid prefix: native Ark transfer legs (ark-) keep opening the hash-less-tolerant TransactionStatus detail, while Refill rows (boarding- / boarding-utxo-) navigate nowhere, restoring master behavior. Applied to both the row tap (onPress) and the long-press Details menu. The guard uses the same boarding- prefix that arkRowKind uses to label a row 'Refill', so tap behavior stays consistent with the label.
|
✅ Build 8.0.0 (1780266374) has been uploaded to TestFlight and will be available for testing soon. |
|
Wake the fuck up samurai, we have PRs to merge [all PRs for @Overtorment] https://github.com/BlueWallet/BlueWallet/pulls/review-requested/Overtorment |
| // Boltz publishes deterministic fees, so Arkade shows a single fixed amount | ||
| // under a definite label ("Network fee"), not a "potential" bracket. Custodial | ||
| // keeps the legacy "Potential fee" label + range. | ||
| const feeLabel = wallet instanceof LightningArkWallet ? loc.lnd.network_fee : loc.lnd.potentialFee; |
There was a problem hiding this comment.
its probavly the feee boltz takes, but actual lightning routing fee is still unknown? (unless boltz probed the route in advance and knows the fees on that route)
| setNotificationsEnabledState(false); | ||
| } | ||
|
|
||
| setNotificationsEnabledState(await isNotificationsEnabled()); |
| // tapscript and hide funds from the indexer. | ||
| const DELEGATOR_URLS = { | ||
| bitcoin: 'https://delegate.arkade.money', | ||
| mutinynet: 'https://delegator.mutinynet.arkade.sh', |
There was a problem hiding this comment.
just a thought - it you really need mutinynet support, say, for dev purposes. in bluewallet.
maybe we can add a dedicated way to import mutinynet arkade wallet.
for exampe, import string like arkmutinynet://abandon abandon or smt like this
| }); | ||
| staticWalletCache[namespace] = wallet; | ||
| } | ||
| mm.end(); |
There was a problem hiding this comment.
is it still a slow operation so we need to keep an eye on its timing..?

Replaces #8538
Summary
Upgrades the Arkade SDKs and overhauls the Ark/Lightning wallet integration to take advantage of the new SDK surface. The wallet now delegates swap orchestration, claim/refund, and persistence to the SDK's repositories and swap manager rather than re-implementing them in app code.
Structured as 8 logical commits on top of
bw/master.What changed
@arkade-os/ts-sdkand@arkade-os/boltz-swapto their latest releases.WalletsCarousel,TransactionListItem,WalletTransactions,WalletDetails,lndViewInvoiceandTransactionStatusconsume the SDK swap manager directly. Wallet activity is now derived from the union of on-chain history and swap state.wallet-importrestores in-flight swaps so they survive reinstalls.blue_modules/arkade-background.tsandblue_modules/arkade-notifications.tsdriving Android/iOS background ticks to claim/refund swaps and notify the user. iOS background mode and Android scheduler config included.loc/en.jsonfor swap states, claim/refund actions, and notifications.