Read a balance and a transaction history from a chain node (Android) #74

Merged
paulhitt merged 1 commits from feat/wallet-chain-client into main 2026-09-04 20:49:43 +00:00
paulhitt commented 2026-09-04 18:43:33 +00:00 (Migrated from gitlab.com)

ChainRpc asks a node what a public address holds and what has happened to it.
The node is trusted with nothing: it never sees a key and cannot move money.
What it CAN do is lie about a balance or withhold a history, so nothing here
treats an answer as authoritative beyond "this is what that node said".

A JSON-RPC error arrives with HTTP 200. The transport succeeded; the node
said no. A client that checks only the status code carries on with a body that
has no result, fails somewhere less obvious, and throws away the node's own
explanation on the way — the difference between "insufficient funds for rent
exemption" on screen and a parse error nobody can act on. Both cases are
tested, including an error carrying no message.

A FAILED transaction still appears in an address's history, and is shown as
failed. Not doing that is the worst kind of wrong: somebody would believe a
payment went through. err is an OBJECT for one class of failure and an ARRAY
for another, so the check is "not null" rather than a shape — testing for an
object alone would pass one whole class of failure off as a success. Both
shapes tested.

A body with neither result nor error is malformed, never a balance of zero.
Reading a missing result as zero would show somebody an empty wallet that is
not empty.

Lamports as a Long throughout, and to the edge of the UI. Five SOL already
exceeds Int.MAX_VALUE, and converting to a fractional unit early means carrying
rounding through code that compares and subtracts — a rounding error in a
balance is money.

A transaction the node has not dated yet reports no time rather than 1970.
It has the transaction and has not assigned a block time; "just now" is the
truth and the epoch is not.

Which node somebody points at is a privacy decision the app has to state:
asking a public RPC endpoint for an address's balance ties that address to this
device's IP in somebody else's logs. Running your own node is the only answer
that removes it; the default exists so the wallet works at all, not because it
is private.

15 tests, against a MockWebServer. App builds, every JVM suite green.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

`ChainRpc` asks a node what a public address holds and what has happened to it. The node is trusted with nothing: it never sees a key and cannot move money. What it CAN do is lie about a balance or withhold a history, so nothing here treats an answer as authoritative beyond "this is what that node said". A JSON-RPC error arrives with HTTP 200. The transport succeeded; the node said no. A client that checks only the status code carries on with a body that has no `result`, fails somewhere less obvious, and throws away the node's own explanation on the way — the difference between "insufficient funds for rent exemption" on screen and a parse error nobody can act on. Both cases are tested, including an error carrying no message. A FAILED transaction still appears in an address's history, and is shown as failed. Not doing that is the worst kind of wrong: somebody would believe a payment went through. `err` is an OBJECT for one class of failure and an ARRAY for another, so the check is "not null" rather than a shape — testing for an object alone would pass one whole class of failure off as a success. Both shapes tested. A body with neither result nor error is malformed, never a balance of zero. Reading a missing result as zero would show somebody an empty wallet that is not empty. Lamports as a Long throughout, and to the edge of the UI. Five SOL already exceeds Int.MAX_VALUE, and converting to a fractional unit early means carrying rounding through code that compares and subtracts — a rounding error in a balance is money. A transaction the node has not dated yet reports no time rather than 1970. It has the transaction and has not assigned a block time; "just now" is the truth and the epoch is not. Which node somebody points at is a privacy decision the app has to state: asking a public RPC endpoint for an address's balance ties that address to this device's IP in somebody else's logs. Running your own node is the only answer that removes it; the default exists so the wallet works at all, not because it is private. 15 tests, against a MockWebServer. App builds, every JVM suite green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
paulhitt commented 2026-09-04 18:43:33 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt
paulhitt commented 2026-09-04 20:49:41 +00:00 (Migrated from gitlab.com)

deleted the feat/wallet-store branch. This merge request now targets the main branch

deleted the `feat/wallet-store` branch. This merge request now targets the `main` branch
paulhitt commented 2026-09-04 20:49:43 +00:00 (Migrated from gitlab.com)

mentioned in commit 7bd8784d98

mentioned in commit 7bd8784d98d1ba0618192f34fb3ae449e9c65a56
paulhitt (Migrated from gitlab.com) merged commit 7bd8784d98 into main 2026-09-04 20:49:43 +00:00
paulhitt commented 2026-09-09 19:01:30 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
Sign in to join this conversation.