Skip to content

WalletPay integration - #803

Draft
gemdev111 wants to merge 13 commits into
mainfrom
feature/payment-links
Draft

WalletPay integration#803
gemdev111 wants to merge 13 commits into
mainfrom
feature/payment-links

Conversation

@gemdev111

@gemdev111 gemdev111 commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

A merchant QR carries the payment as a pay.walletconnect.com URL, as a
WalletConnect pairing URI with a pay parameter, or as the gem://wc deep link
wrapping that pairing URI.

Unlike the other standards this one owns no scheme of its own, so it is matched
by host, exactly or as a dotted suffix, and the payment id must carry the pay_
prefix so other pages on that host do not resolve.
The decoder's Payment lived only in Rust while gemstone re-declared its fields
as PaymentWrapper, and a decoded link was flattened to a bare string, so neither
app could tell which provider issued it.

Payment is now typeshared as either a Request we can pay ourselves or a Link a
provider settles, gemstone aliases it instead of redeclaring it, and each app
maps it once at the boundary. Splitting the two cases also removes an empty
address: scanning a provider link into the send recipient field used to blank
the field with no error on iOS and paste the raw link on Android.
A payment link opened as a URL was consumed as a WalletConnect pairing attempt,
because UrlAction checked WalletConnect first and knew nothing about payments,
while the payment decoder checked payments first. The same URL meant different
things depending on which door it arrived through.

UrlAction now asks the payment decoder and takes only the delegated case, so
both doors share one definition of a provider link and adding a provider updates
them together. Neither app acts on it yet.
Sits behind developer mode while the flow is being proven, so it ships without a
customer-facing entry point.

The scan goes through UrlAction rather than the payment decoder: the decoder is
built for an address field and treats any string as an address, so a pairing URI
or a wifi code would have resolved to a nonsense payment. UrlAction reports what
a code actually is, and anything that is not a payment link is refused.
@gemdev111 gemdev111 changed the title Decode payment links into a model both apps share WalletPay integration Jul 29, 2026
Every sign and transaction request needs the name, url and icon of whoever asked, and only WalletConnect answers that with a session. TransactionAppMetadata replaces RequestingApp across core, gemstone and both apps, and the session types drop the WalletConnection prefix they never needed, so a request can be reviewed without a live connection behind it.
A bare app label next to the session metadata read as two different things. The transfer data, sign payload and bindings now call the field appMetadata, and the bindings field follows as app_metadata.
Parsing and decoding a request is protocol work with no session behind it, so it moves from gem_wallet_connect into gem_wallet_connect_request and the session crate re-exports it. Paying reuses the request layer without depending on sessions.
A payment from any provider resolves to the same typeshared models. Quoting yields PaymentQuotes: the merchant plus one PaymentQuote per route, each carrying its amount, an optional personal data url and the provider option it came from as an opaque payload the caller hands back. A settled payment reports a PaymentResult, and TransactionPaymentMetadata ties a recorded transaction to its payment and merchant so both apps can track and render it.
The gateway quotes a payment into routes and the wallet executes one: quote, collect data if the route demands it, fetch the wallet rpc actions, confirm with the signed results, follow the status. The service is stateless, the chosen quote rides with the caller, and gateway failures map to typed errors read from the response code so the apps never see a raw body.
Remote aliases keep one definition per payment model instead of a duplicate for the bindings, and the uniffi object hands an app the payment step, the actions for a chosen quote, confirm, cancel and status.
The sign message payload carried a WalletConnect session, so a review sheet could only render for a live connection. It now carries the requesting app metadata and its own request id, the scene view model reads only the payload, and the transfer data factory moves out of the signer so any caller can build the same transfer data.
@gemdev111
gemdev111 force-pushed the feature/payment-links branch from e68cac3 to f0d713d Compare July 30, 2026 20:23
The generic transaction input now carries app metadata, and the short name helper takes the name itself, so the Kotlin call sites follow and the session mapping that nothing else used goes away. Cargo records the two new crates at the workspace version.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant