Repository navigation
feat(spike): prove Flutter Web Freighter signing and Testnet SAC payments - #70
Conversation
…ents Add the issue #68 spike: a Flutter Web adapter that connects to Freighter 6.x, binds every signature to the connected Testnet account, verifies signatures cryptographically, and decodes official RPC/XDR payment evidence. Live Testnet evidence (2026-09-30): - 1 XLM classic payment to a muxed address (id 68): SUCCESS, ledger 4953089, tx 820c8a985f219346bd7c5672d33b13b7621d384057098619ef82524501d756b4; the SAC transfer event carried amount and to_muxed_id. - Account switch without reconnect rejected with WalletAccountChanged. - ADDRESS_V2 (CAP-71) auth entry signed by Freighter and executed in a SAC transfer: SUCCESS, ledger 4953815, tx 731fdb98f97db64e48200999ba852ec3136dc3848dfa07c95a9958bfde62650e. Fixes found during live testing: - Reject transaction or operation sources that differ from the session before prompting (PayloadAccountMismatch). - Sign auth entries through the HashIdPreimage contract Freighter expects, including ENVELOPE_TYPE_SOROBAN_AUTHORIZATION_WITH_ADDRESS for ADDRESS_V2. - Make the RPC harness runnable with plain dart run via Flutter-free SDK imports, and page getEvents from the transaction ledger. - Read operation-level SAC events with four topics in PaymentEvidence, covered by recorded Testnet fixtures. Refs #68
… changes - Re-encode the incoming transaction envelope and reject it as malformed before prompting when it is not canonical; the SDK silently accepts trailing bytes, so Freighter was prompted before rejection. - Cover empty, whitespace, non-base64, truncated and trailing-byte envelopes with a test that asserts no wallet prompt. - Add "Recommended changes for #8 and ADR-0003" grounded in the live Testnet evidence, and record the live ADDRESS_V2 auth-entry success. Refs #68
Deploying puls3 with
|
| Latest commit: |
459c53f
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://13fcdd2f.puls3-4lw.pages.dev |
| Branch Preview URL: | https://spike-68-flutter-stellar-wal.puls3-4lw.pages.dev |
The unbounded `S[A-Z2-7]{55}` rule matched a 56-character run inside
zero-padded base64 XDR in a public Testnet fixture and failed `scan`.
Word boundaries keep detecting seeds that stand alone or follow `=`,
quotes or whitespace. Verified with gitleaks v8: the PR range and the full
43-commit history report no leaks, and three freshly generated seeds in
.env, JSON and bare-line placements are still detected.
Refs #68
|
Heads-up for reviewers: the payment part of this spike follows ADR-0003's direct SAC transfer to the agent, which ADR-0005 (#72) replaces with an ERC-8183 escrow ( The spike is still valid for what it proves: Freighter signing from Flutter Web and relaying a signed Soroban transaction on Testnet. That carries over unchanged to the escrow calls. Please review it as a signing/integration proof, not as the final payment flow; the real hire flow is specified in #77 and the contract in #55. |
Pericena
left a comment
There was a problem hiding this comment.
Approving as a signing/integration proof (not the final payment flow, per ADR-0005).
Verified locally on 8a07cd7: flutter analyze (0 issues), flutter test (42/42), flutter build web (OK).
Account binding, Testnet binding, signed-envelope integrity and ADDRESS/ADDRESS_V2 preimage signing
are enforced and cryptographically verified; no secrets found.
The fee-bump pre-prompt gap is already tracked in #69 (R3-001). Two items not covered there, for a follow-up:
- .gitleaks.toml:
\bS[A-Z2-7]{55}\bweakens seed detection repo-wide (e.g.KEY_S...no longer matches).
Prefer the original regex plus a path allowlist for spikes/**/test/fixtures/*.json. - ci.yml has no
spikes/*path filter, so the spike's analyze/tests never run in CI.
For #27/#37: cap signatureExpirationLedger (not only reject 0) and allowlist rootInvocation contract/function.
Closes #68
Summary
A Flutter Web spike,
spikes/flutter-stellar-wallet/, proves the wallet boundary for puls3. Freighter 6.x connects on Testnet and signs server-prepared transactions and CAP-71ADDRESS_V2authorization entries. Every request is bound to the connected account and to the Testnet passphrase, and keys never leave the wallet. Payment evidence is decoded from official RPC/XDR responses.docs/spikes/flutter-stellar-wallet.mdrecords the evidence and the concrete changes this implies for #8 and ADR-0003.Live testing found and fixed several defects:
HashIdPreimageFreighter expects, not the whole entry.ADDRESS_V2: support was added. Testnet is on protocol 29 and simulation returns only V2 credentials.dart runbecausestellar_flutter_sdkpulls indart:ui. Event lookup was also unpaginated.Acceptance criteria
Verification evidence
The live run used Freighter 6.x on Testnet, payer
GCCB4MKFLRRD4HBXNGMXQMIIU5TSYX2TBAQIQRIGE5LSILPW77E44GOZ, on 2026-09-30.Explorer links:
Notes for reviewers
EMIT_CLASSIC_EVENTS) is confirmed for the SDF Testnet RPC only. Hosted providers must confirm it.pubspec.yamlandpubspec.lockchange only to register the spike package in the workspace.