Repository navigation
Conversation
# Conflicts: # CHANGELOG.md
|
Ready for review: CI passes on d452bf6, which merges master. The prerelease |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. Adds paykit_route_payment, a pure router that pays a Paykit contact directly (Lightning, then on chain for the wallet's network), else through the cheapest live quoted service leg, else returns None with a reason. Reviewed d452bf6, full tier, static: the PR's code was not built or run here.
What I checked, and 5 candidates I ruled out
Read in full: src/modules/paykit_route/{router,types,errors,mod}.rs, README.md, the src/lib.rs export, the version files (Cargo.toml, Package.swift, gradle.properties), the bitkitcoreFFI.h additions
Traced: the consumer in synonymdev/bitkit-android#1754 (PaykitRouteRepo.route, quotePaykitRoute, withdrawalRouteLeg), which builds ServiceRouteLeg with debitSat = amount + userFeeSat and validUntilUnix = quote.expiresAt, matching the router's contract
CI: green (Android and iOS bindgen, manifests, SwiftPM, usdt-tests, wake-tests)
Ruled out
- Fee underflow in
min_by_key(debit - delivered): the filter before it keeps onlydebit_sat >= delivered_sat. - Expiry off by one:
valid_until_unix > now_unixdrops a quote at its expiry second; the test'sNOWleg covers that. - Paying a contact's endpoint on another network: direct on-chain and service legs both build
btc-{rail}-{kind}from the wallet's network; Lightning ids carry no network segment, so they are taken as published. - Version files out of sync:
Cargo.toml,Package.swiftandgradle.propertiesall read0.8.0-spark.2, and thev0.8.0-spark.2tag exists ate72a49f; the merge from master after it only brings in the trezor-connect-rs 10.0.1 bump. - English
reasoninPaykitRoute::None: the crate already returns English reasons this way (UrError::InvalidUr,UsdtError::TransactionRejected), so this follows the house pattern.
Merge confidence: 4/5, no CI job runs cargo test modules::paykit_route (only the usdt and wake modules are tested in CI), and I could not run the new router tests here.
coreyphillips
left a comment
There was a problem hiding this comment.
Two independent reviews.
worth doing, does not block
- Direct Lightning routing never looks at the endpoint value (src/modules/paykit_route/router.rs:33-35)
- Tests miss the published-address check and every real network label (src/modules/paykit_route/router.rs:118-123)
- No CI job runs the paykit_route tests (.github/workflows/wake-tests.yml:31). The router's tests are never run by CI, so the Automated Checks listed in the description only run when someone runs them locally. The only Rust test workflows are
usdt-tests.yml(modules::usdt) andwake-tests.yml(modules::wake). The PR's checks confirm this: the two bindgen jobs, the manifest jobs, usdt-tests and wake-tests. There is no generalcargo testjob. Master's wake work added its own workflow, so a matchingcargo test --locked --lib modules::paykit_routejob would follow that precedent for a module that selects payment routes. - Testnet4 is routed to Testnet3 endpoints (src/modules/paykit_route/router.rs:15-20)
the reviewers disagree, your call
PaykitRoute::Nonereason is one fixed English sentence (src/modules/paykit_route/router.rs:105-107)- App PRs bypass the Direct path, so the planned bolt11 run won't exercise it (src/lib.rs:3745-3757)
Decode BOLT11 endpoint values and skip invoices for another network, expired at now or for another amount. Route nothing on chain for Testnet4, which has no rail in the spec. Test the published-address check and each network rail.
Refs:
Description
paykit_route_payment, which picks how to pay a Paykit contact, so a Spark-only wallet can pay contacts without Pubky Swaps. The function is synchronous, needs no seed and makes no network calls.btc-lightning-bolt11, thenbtc-lightning-lnurl, whenlightning_spendable_satcovers the amount. The Spark balance counts as Lightning-spendable.btc-{network}-p2tr,p2wpkh,p2shorp2pkh, in that order, whenonchain_spendable_satcovers it.service_legs, such as a Spark withdrawal to the contact's on-chain address.PaykitRoute::None'sreasonis English detail for logs; the apps show their own localized text.Paykit Route TestsCI job that runs the module's tests.Out of Scope
src/modules/pubky_swaps: swap routes stay in draft feat: pubky swaps as paykit route #182, which stacks on this PR and addsswap/1as a second leg kind once pubky/paykit-rs#229 settles.btc-lightning-bolt12: not routed. Breez SDK 0.28.0 parses BOLT12 offers, but itsprepare_send_paymentrefuses them as an unsupported payment method, so a Spark wallet can't pay one yet.Design
N/A — no UI changes.
Preview
N/A — no user-visible changes.
QA Notes
Journeys
N/A
Manual Tests
N/A
Automated Checks
src/modules/paykit_route/router.rstests: Lightning first, then the preferred on-chain type; direct before any leg; cheapest live leg to a published endpoint; BOLT11 invoices for another network, expired or for another amount skipped; legs to an unpublished address ignored; each network rail, and nothing on chain for Testnet4; the reason when nothing routes.github/workflows/paykit-route-tests.ymlWhat it needs to ship
0.8.0-spark.3, feat: pay contacts via spark bitkit-android#1754 and feat: pay contacts via spark bitkit-ios#1191, replacepubkySwapsRoutePaykitPaymentwithpaykitRoutePayment, and pass the contact's full endpoint list soDirectruns too.