WalletPay integration - #803
Closed
gemdev111 wants to merge 27 commits into
Closed
Conversation
gemdev111
force-pushed
the
feature/payment-links
branch
from
July 30, 2026 20:23
e68cac3 to
f0d713d
Compare
ApprovalData is an ERC-20 allowance, not a swap concept, and it was already used by yielder, Tron's signer and preload, contract_call_data and transaction_input_type. Move it to primitives::approval_data and give gemstone a models/approval module for its FFI record.
The RPC decoders and the session half are two independent halves of the crate, and a payment provider needs only the first. Gate them as `request` and `session`, with base64 and url following their half, so a consumer that only decodes requests does not build the session code.
gemdev111
force-pushed
the
feature/payment-links
branch
4 times, most recently
from
August 4, 2026 11:35
7d7cabf to
f5e6e76
Compare
SignMessage and the per-chain transaction payloads are what a wallet signs, and with payments a second producer speaks them. Move them to primitives::signing and drop the WalletConnect prefix, so the neutral payment action does not name a transport: WalletConnectTransaction becomes SignableTransaction, the name iOS already uses for it.
A scanned or opened payment link decodes to Payment::Link(PaymentLink), carrying the provider and the id only that provider can read. The quote, outcome and merchant models are typeshared so both apps read one definition, and a paid transaction records which provider settled it.
A PaymentProvider trait and a registry that routes a link to the one provider that can settle it, so every layer above stays provider agnostic. WalletConnect Pay is the first provider, living inside the crate the way swapper and yielder hold theirs: it turns the gateway's JSON-RPC into the four actions a wallet can be asked to perform, and reads results back by position.
One GemPaymentService object over the neutral registry, and PaymentError crossing the FFI as itself through a remote enum, the way SwapperError already does, so the apps localize one closed set of failures.
The sheets a signing request can ask for, and nothing more: sign a message, sign a transaction, send one. WalletConnect and payments both drive the same three, so the payload types, the transfer-data factory and the simulator live in one service rather than in either feature.
The app-side view of a payment provider: the gateway client over the gemstone object, the four actions a payment can ask for, and the two screens only a payment has. Everything above it speaks PaymentAction, never the gateway.
TransferExecutor, TransferTransactionProvider and the types they need are UI-free services, but they lived in a feature package, so Payments would have to depend on Features/Transfer, the app's only feature-to-feature dependency. Move them to FeatureServices with their TestKit and tests, alongside SwapService and EarnService.
Resolve a link to its quotes, let the buyer pick one, then run the actions the provider returned: signatures first, so a rejection never costs gas, and approvals broadcast silently and wait to be mined the way swap does. Results go back to the provider by position, and a confirm that fails leaves the payment pending for its status to settle.
Scanned and opened payment links reach the payment manager instead of a no-op, the pending payment is tracked by the transaction state job, and PaymentError is localized as the buyer's failure, not the gateway's.
The generated payment models plus the extensions that map a decoded link and an approval across the FFI boundary.
Merchant, payment expiry and the payment failure copy, in every language file, with the generated iOS and Android outputs.
The URL decoder resolves a payment link into the shared model, the scanner and the deep-link route hand it to the payment manager, and the app metadata a signing request carries no longer comes from a live WalletConnect session.
PaymentsTests was reachable only from the scheme, so the plan CI runs would have skipped it silently.
The transfer and sign-message sheets are the wallet's own approval screens, not WalletConnect's: payments drive them too. SigningRequestService now owns SigningRequestSheetType and the SheetPresenter that serializes presentation, so WalletConnectorSheetType is only the connection proposal and every host shares one dismissal gate.
gemdev111
force-pushed
the
feature/payment-links
branch
from
August 4, 2026 11:55
f5e6e76 to
a8978ba
Compare
SheetPresenter, its callback and the cancellation error move to Primitives: none of them touch UI or localization, so every feature can host a sheet without depending on SigningRequestService. The per-feature presenter wrappers collapse into conditional conformances, the payment protocols move next to the types that implement them, and SignableTransaction maps the Gemstone Ethereum payload at the boundary instead of exposing it. Removes 21 imports left dead by the move.
WalletConnect built ConfirmParams from a SignableTransaction inline. The payment flow needs the same mapping, so move it to gemcore as a shared extension and have WCRequest delegate to it.
The message preview, payload details sheet and full message sheet were internal to the bridge feature. Move them to ui alongside the simulation payload content so the payment flow can present the same review.
The gallery path reduced every scanned code to a recipient address, so a payment link decoded to nothing and reported an unreadable image. Pass the raw text through as the camera path already does, and keep the address as display text only. Recipient codes also keep their amount and memo now.
Add the payment feature: quote selection, the compliance capture web view, permit signing and token approval, driven from a single view model and reusing the confirm screen for anything that broadcasts. The web view speaks the iOS message handler shape, so a shim exposes it and forwards window messages to the Android bridge. Payment links reach the app through the wallet scanner and a deep link on the payment host.
A relayed payment is recorded under its payment id before a chain hash exists. Poll the gateway for that hash, then either rename the record or, when the indexer already delivered the same transaction, drop the placeholder and adopt the existing row. Stay pending until a hash arrives so the poller keeps checking, and hand the adopted record back so the polling job finishes on it instead of writing the deleted row again at timeout.
A payment has no recipient address, so the activity row read "To" with nothing after it and the details screen offered an address link that led nowhere. Take the merchant from the payment metadata for both, and give the details screen a destination that renders as plain text.
Any unrecognised failure became a fee calculation error with the cause discarded, so the screen reported an estimation problem for faults that had nothing to do with fees. Log the throwable where it is swallowed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.