Skip to content

feat(sdk-ffi): ask one evonode for its DAPI status; expose the platform HTTP port - #4461

Merged
QuantumExplorer merged 1 commit into
v4.2-devfrom
feat/evonode-status-ffi
Aug 23, 2026
Merged

feat(sdk-ffi): ask one evonode for its DAPI status; expose the platform HTTP port#4461
QuantumExplorer merged 1 commit into
v4.2-devfrom
feat/evonode-status-ffi

Conversation

@QuantumExplorer

Copy link
Copy Markdown
Member

Summary

Lets a wallet ask one specific evonode for its DAPI getStatus self-report, and gives the wallet what it needs to address its own evonodes.

  • dash_sdk_evonode_get_status(handle, "https://<ip>:<port>") (rs-sdk-ffi) — sends getStatus to that single node via rs-sdk's EvoNodeStatus::fetch_unproved(EvoNode) (one-connection pool, no address-list failover) and returns every field of the report as JSON: software/protocol versions, node id + proTxHash, chain heights/hashes, network, state sync, time. Hashes hex, omitted optionals null.
    • Request settings bounded for a single-node probe: 10 s connect, 15 s request, one retry, no ban — an offline node fails in ~20 s instead of the OS TCP timeout (~75 s × retries; measured 2.5 min before this).
    • Timestamps pass through raw. Real mainnet data: Drive's block/genesis are ms (0 = unknown genesis), local is seconds from rs-dapi and ms from the legacy JS DAPI — the Swift model encodes that once (Time.localDate/blockDate/genesisDate, magnitude-disambiguated, 0 → nil).
  • Masternode aggregation (rs-platform-wallet-ffi): MasternodeEntryFFI.platform_http_port + has_platform_http_port, from the latest ProRegTx / ProUpServTx together with the service address (same latest-wins rule).
  • Swift SDK: PlatformMasternode.platformHTTPPort + platformDAPIAddress (https://<service host>:<port>, IPv6 bracketed), typed EvonodeStatus (Codable, every field), SDK.getEvonodeStatus(address:) — deliberately in its own nonisolated extension (the PlatformQueryExtensions extension is @MainActor; this is a blocking FFI call callers run off-main, like Identities.getBalance).

Consumer: dashpay/dashwallet-ios "Request status" button on the evonode detail screen (PR to follow).

Test plan

  • cargo test -p rs-sdk-ffi --lib evonode::queries::status — JSON carries every field / omitted ⇒ null, null handle / null address / invalid address error codes.
  • cargo test -p rs-sdk-ffi --lib evonode::queries::status -- --ignoredlive mainnet probe (https://31.220.91.60:443): full report in 1.1 s, heights/chain id asserted.
  • cargo test -p platform-wallet-ffi --lib core_wallet_types — port follows ProRegTx then ProUpServTx; FFI entry gated by has_platform_http_port.
  • cargo fmt --all --check; cargo clippy -p rs-sdk-ffi -p platform-wallet-ffi --all-targets --all-features --locked -- --no-deps -D warnings.
  • xcodebuild test -scheme SwiftDashSDK -only-testing:SwiftDashSDKTests/EvonodeStatusTests — 6/6 (decoding, omitted fields, time units, DAPI address incl. IPv6).
  • ./build_ios.sh --target sim + SwiftExampleApp compiles with -warnings-as-errors.
  • In-app (dashwallet-ios, simulator): real mainnet evonode → full report; unreachable address → "Couldn't reach the evonode" in ~20 s.

🤖 Generated with Claude Code

…rm HTTP port

`dash_sdk_evonode_get_status(handle, "https://<ip>:<port>")` sends DAPI
`getStatus` to that single node (rs-sdk `EvoNodeStatus::fetch_unproved` over
`EvoNode`, one-connection pool, no address-list failover) and returns every
field of the self-report as JSON: software/protocol versions, node id +
proTxHash, chain heights/hashes, network, state sync, time. Request settings
are bounded for a single-node probe — 10 s connect, 15 s request, one retry,
no ban — so an offline node fails in ~20 s instead of the OS TCP timeout.
Timestamps pass through raw; the Swift model documents the units (Drive
`block`/`genesis` in ms with `0` = unknown, `local` in seconds from rs-dapi
and ms from the JS DAPI).

To address a wallet's own evonode, the masternode aggregation now carries
the platform HTTP port from the latest ProRegTx / ProUpServTx alongside the
service address (`MasternodeEntryFFI.platform_http_port` /
`has_platform_http_port`).

Swift SDK: `PlatformMasternode.platformHTTPPort` + `platformDAPIAddress`
(`https://<service host>:<port>`), a typed `EvonodeStatus` (Codable), and
`SDK.getEvonodeStatus(address:)` — nonisolated/blocking like
`Identities.getBalance`, for callers to run off the main actor.

Tests: FFI JSON shape (every field, omitted ⇒ null), null/invalid-address
errors, an ignored live mainnet probe; aggregation latest-wins for the port;
Swift decoding, time-unit accessors, and DAPI address building.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@QuantumExplorer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 28 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d9327a6-2178-4058-80bc-5654a70fefef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f6dce2 and 552dcd9.

📒 Files selected for processing (7)
  • packages/rs-platform-wallet-ffi/src/core_wallet_types.rs
  • packages/rs-sdk-ffi/src/evonode/queries/mod.rs
  • packages/rs-sdk-ffi/src/evonode/queries/status.rs
  • packages/swift-sdk/Sources/SwiftDashSDK/FFI/EvonodeStatusQuery.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/Models/EvonodeStatus.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerMasternodes.swift
  • packages/swift-sdk/SwiftTests/SwiftDashSDKTests/EvonodeStatusTests.swift

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@thepastaclaw

thepastaclaw commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

🕓 Ready for review — next in queue (commit 552dcd9)
Queue position: 1/1 · 2 reviews active
ETA: start ~10:15 UTC · complete ~10:37 UTC (median 22m across 30 recent reviews; 2 slots)
Queued 3m ago · Last checked: 2026-08-23 10:10 UTC

@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.40%. Comparing base (8f6dce2) to head (552dcd9).

Additional details and impacted files
@@             Coverage Diff              @@
##           v4.2-dev    #4461      +/-   ##
============================================
- Coverage     87.56%   87.40%   -0.17%     
============================================
  Files          2698     2698              
  Lines        344559   344559              
============================================
- Hits         301719   301150     -569     
- Misses        42840    43409     +569     
Components Coverage Δ
dpp 88.92% <ø> (-0.02%) ⬇️
drive 86.29% <ø> (-0.03%) ⬇️
drive-abci 89.21% <ø> (-0.56%) ⬇️
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.92% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 47.40% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved

@QuantumExplorer
QuantumExplorer merged commit fd8d8d1 into v4.2-dev Aug 23, 2026
17 of 19 checks passed
@QuantumExplorer
QuantumExplorer deleted the feat/evonode-status-ffi branch August 23, 2026 10:15
bfoss765 added a commit that referenced this pull request Aug 23, 2026
Brings the branch up to date with upstream after #4451 (masternode
credit withdrawals), #4452, #4453, #4456, and #4461 landed on v4.2-dev.

One conflict, in packages/rs-platform-wallet/src/wallet/core/mod.rs:
a module-registration collision where this branch adds
'pub mod spend_observer;' and upstream adds
'pub(crate) use sign_message::is_signable_funding_account;' at the same
spot. Resolved as the union — both lines kept, no semantic overlap.

Auto-merged overlaps verified by hand: both error.rs files and
DashSdkError.kt gained disjoint additions (upstream's
MasternodeWithdrawalUnconfirmed / FFI code 42 alongside this branch's
StaleReservation reusing code 34 — codes distinct, both mapping arms
present). generation.rs (the broadcast-fence redesign) was touched by
this branch only.

Verified: cargo check -p platform-wallet -p platform-wallet-ffi clean;
cargo test -p platform-wallet wallet::core::generation — 15/15 passed,
including the settle-boundary and handoff tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bfoss765 added a commit that referenced this pull request Aug 23, 2026
Brings the shielded-invite branch up to date with upstream v4.2-dev
(#4451 masternode credit withdrawals, #4452, #4453, #4456, #4461).

One conflict, in rs-platform-wallet/src/wallet/shielded/operations.rs:
upstream #4451 moved carries_consensus_rejection() and
broadcast_definitely_failed() out of operations.rs into the new shared
crate::broadcast_outcome module (so masternode withdrawals can reuse
them), while this branch had inserted its one-time-key claim machinery
(NullifierSpentStatus, claim-evidence resolution) directly after those
functions. Resolved by dropping the now-local duplicate of
broadcast_definitely_failed() — its body is byte-identical to the moved
copy, and the file already imports both helpers from
crate::broadcast_outcome via upstream's auto-merged use line — and
keeping this branch's one-time-key claim block in place. No semantic
changes to either side.

Verified: cargo check -p platform-wallet -p platform-wallet-ffi
-p rs-unified-sdk-jni clean; cargo test -p platform-wallet
--features shielded wallet::shielded = 205 passed, 0 failed
(includes the one_time_claim_evidence and note_selection suites).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QuantumExplorer added a commit to dashpay/dashwallet-ios that referenced this pull request Aug 24, 2026
…s on demand (#1043)

Adds a "Request status" row to the evonode detail screen. Tapping it pushes
`EvonodeStatusScreen`, which sends DAPI `getStatus` to that node alone
(`https://<service host>:<platform HTTP port>` — the SDK's new
`PlatformMasternode.platformDAPIAddress`) and lists everything the node
answered, grouped as the node groups it: Request (address asked, time
received), Software (DAPI/Drive/Tenderdash), Protocol versions, Node (node
id, proTxHash, an identity check against the masternode being viewed),
Chain (catching up, heights, hashes), Network (chain id, peers, listening),
State sync, Time (node clock, latest block, genesis, epoch). Optional fields
the node omitted read "Not reported". Hashes/addresses are tap-to-copy.

Nothing is requested automatically: the request is sent only when the user
taps the row (and again on the screen's Refresh / Try again). The row is
disabled with the reason when the aggregation doesn't know the node's DAPI
address. An unreachable node shows the transport error and a Try again
button (~20 s with the SDK's single-node timeouts).

`EvonodeStatusViewModel` owns the SDK call (`SDK.getEvonodeStatus`, run off
the main actor) and the row layout/formatting; the view only renders.
`MasternodeDetailRow` / `MasternodeCopyRow` become internal and are reused.

Requires dashpay/platform#4461 (FFI `dash_sdk_evonode_get_status`,
`platform_http_port` in the masternode aggregation, Swift `EvonodeStatus`).

Co-authored-by: Claude Fable 5 <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.

2 participants