You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The persisted coins table with idx_coins_unspent … WHERE spent_height IS NULL, and WalletDb::unspent_coins(asset_id) (crates/dig-wallet/src/sage/db.rs)
The gap is only pagination. An address with thousands of coins currently returns everything in one
response.
The shape — reuse the repo's own Sage-parity idiom, do not invent one
crates/dig-wallet/src/sage/rpc.rs:358-366 already implements this correctly for coinsByParent.
Match it:
ASCENDING by coin_id — a stable total order, so a page boundary is well-defined.
Cursor, not offset. Return the last coin_id of the page; the caller resumes from it. An offset
re-reads a shifting table and silently skips or repeats rows when a coin is spent between pages —
and on a money surface a skipped coin reads as missing funds.
has_more derived from rows remaining BEYOND the page, never from whether the page filled. The
repo's own comment says why: the two differ exactly when the count is a multiple of the page size.
An empty page is an answer, not an error (rpc.rs:1853).
A short page is never marked complete to salvage a partial read (rpc.rs:1859).
Note the existing query's scope, and decide deliberately
unspent_coins(asset_id) filters by asset_id only — it does not filter by puzzle_hash. Check
what the RPC layer does with that before adding a page on top: if the address filter is applied above
the query, paginating the unfiltered query and then filtering would produce short pages and a wrong has_more. Filter and paginate at the same level, in SQL, or the two disagree.
Also
Keep --json machine output (§6.2) and make the cursor/has_more fields part of it — a scripted
caller must be able to page without parsing prose.
control.wallet.coins is a published contract in dig-node-control-interface; adding optional
paging params is additive, but the catalog must be updated in the same family (§4.1 release-first).
State the SemVer judgement.
§2.4b: bring dig-*/chia-* deps to latest in the PR; index checks need a User-Agent header.
Acceptance
dign wallet coins <address> --asset dig pages through a real funded address, --json carries the
cursor, and the last page reports has_more: false without a spurious extra request. Evidence is a
real run (§2.6).
Task
Paginate the unspent-coin read:
control.wallet.coinsand thedign wallet coinsCLI that fronts it.Parent epic: https://github.com/DIG-Network/dig_ecosystem/issues/3170
User directive, verbatim: "the dig-node cli also needs a command in its wallet to list available
coins, paginated"
What already exists — do NOT rebuild it
control.wallet.coins— shipped, per-address, unspent-only (crates/dig-node-service/src/control.rs:148)dign wallet coins <ADDRESS> --asset xch|dig [--json]— shipped, unpaginatedcoinstable withidx_coins_unspent … WHERE spent_height IS NULL, andWalletDb::unspent_coins(asset_id)(crates/dig-wallet/src/sage/db.rs)The gap is only pagination. An address with thousands of coins currently returns everything in one
response.
The shape — reuse the repo's own Sage-parity idiom, do not invent one
crates/dig-wallet/src/sage/rpc.rs:358-366already implements this correctly forcoinsByParent.Match it:
coin_id— a stable total order, so a page boundary is well-defined.coin_idof the page; the caller resumes from it. An offsetre-reads a shifting table and silently skips or repeats rows when a coin is spent between pages —
and on a money surface a skipped coin reads as missing funds.
has_morederived from rows remaining BEYOND the page, never from whether the page filled. Therepo's own comment says why: the two differ exactly when the count is a multiple of the page size.
rpc.rs:1853).rpc.rs:1859).Note the existing query's scope, and decide deliberately
unspent_coins(asset_id)filters byasset_idonly — it does not filter bypuzzle_hash. Checkwhat the RPC layer does with that before adding a page on top: if the address filter is applied above
the query, paginating the unfiltered query and then filtering would produce short pages and a wrong
has_more. Filter and paginate at the same level, in SQL, or the two disagree.Also
--jsonmachine output (§6.2) and make the cursor/has_morefields part of it — a scriptedcaller must be able to page without parsing prose.
control.wallet.coinsis a published contract indig-node-control-interface; adding optionalpaging params is additive, but the catalog must be updated in the same family (§4.1 release-first).
State the SemVer judgement.
SPEC.md(§4.2) and the CLI parity test (Mirror creates need an advertised URL this node can be fetched at #426 guards drift between the RPC and the CLI).dig-*/chia-*deps to latest in the PR; index checks need aUser-Agentheader.Acceptance
dign wallet coins <address> --asset digpages through a real funded address,--jsoncarries thecursor, and the last page reports
has_more: falsewithout a spurious extra request. Evidence is areal run (§2.6).