Improvement Idea: Interactive Transaction Request Protocol
Problem:
Sui’s existing payment URI scheme works well when payment details can be determined in advance. However, it does not provide a neutral way for a merchant or application to dynamically construct a Programmable Transaction Block after receiving the user’s address.
Dynamic construction is necessary for many payment and application flows, including:
- swapping the user’s asset into the merchant’s preferred asset
- selecting routes based on current liquidity
- sponsoring gas
- applying fees, discounts, or rewards
- selecting objects owned by the user
- interacting with Move packages
- combining multiple actions into one atomic transaction
For example, a customer may hold EURC while a merchant accepts USDC. A payment server could construct one PTB that swaps EURC to USDC, pays the merchant, sponsors gas, and performs additional settlement actions atomically.
Sui supports these transactions, but wallets and applications currently require wallet specific links, proprietary integrations, or custom signing flows. This creates fragmentation and makes it harder for wallets, merchants, payment processors, point of sale systems, and applications to interoperate.
Description:
Add an optional r parameter to the sui:pay URI scheme. The parameter would contain a URL for an interactive transaction-request endpoint.
sui:pay?r=https%3A%2F%2Fmerchant.example%2Frequests%2Fabc123
Existing payment parameters could also be included as a fallback for wallets that do not support interactive requests:
sui:pay?receiver=0x123...&amount=1000000&coinType=0x...&r=https%3A%2F%2Fmerchant.example%2Frequests%2Fabc123
The URI could be delivered through a QR code, NFC tag, NFC enabled point of sale terminal, universal link, application link, or copied text.
A supporting wallet would check for the r parameter and initiate the following flow.
1. Retrieve request metadata
The wallet sends a GET request to the URL contained in r.
GET /requests/abc123
Accept: application/json
The server returns basic information identifying the requester:
{
"name": "Example Merchant",
"icon": "https://merchant.example/icon.png"
}
For the first version, the metadata response would contain only:
name: the merchant, application, organization, or person requesting the transactionicon: an optional HTTPS image URL representing the requester
The wallet displays the name, icon, and request domain to the user before continuing.
2. Request the transaction
Next, the wallet sends a POST request to the same URL:
POST /requests/abc123
Content-Type: application/json
{
"address": "0x123...",
"wallet": "Slush"
}
The request contains:
address: the Sui address that will act as the transaction senderwallet: an optional informational wallet name
The wallet name could reuse the name exposed through the Sui Wallet Standard, provided wallet developers agree that this value is sufficiently standardized.
The wallet name must not be used for authentication or security decisions. It may be useful for compatibility handling, debugging, and implementation analytics.
3. Return the transaction
The server constructs a transaction using the supplied address and returns the serialized transaction block:
{
"transaction": "<base64-encoded serialized Sui transaction>"
}
We should discuss a canonical transaction serialization format. We may also need to support existing signatures when the transaction uses gas sponsorship:
{
"transaction": "<base64-encoded serialized Sui transaction>",
"signatures": [
"<optional sponsor signature>"
]
}
The returned transaction may contain any valid Sui PTB. It does not have to be a payment.
The transaction could transfer assets, swap tokens, interact with a Move package, claim or mint an object, redeem a voucher, create or modify objects, or execute several application actions atomically.
Although the request is initiated through sui:pay, the interactive transaction request mechanism would be a general purpose transaction primitive.
4. Review, sign, and submit
The wallet must treat the server provided transaction as untrusted.
Before asking the user to sign, the wallet should deserialize, inspect, and simulate the transaction where possible. It should clearly present the transaction’s actual effects, including:
- assets leaving the user’s account
- transfers to the merchant or other addresses
- Move calls
- swaps and protocol interactions
- object changes
- gas costs and sponsorship
- additional required signers
The wallet should verify that the transaction sender matches the address supplied in the POST request.
The user may then approve or reject the transaction. If approved, the wallet signs and submits it to the Sui network.
5. Notify the request server
After submission, the wallet may send another POST request to the same URL containing the resulting transaction digest:
{
"digest": "TransactionDigest..."
}
This lets the server associate the submitted transaction with the original request and begin verification immediately.
The digest notification must not be treated as proof of payment or successful execution. The server must independently query the Sui network and verify that:
- the transaction exists
- the transaction finalized successfully
- the sender is the expected address
- the transaction corresponds to the transaction created by the server
- the transaction’s effects satisfy the original request
The confirmation POST should be idempotent so the wallet can safely retry it.
Payment-specific implementations may additionally verify application events or receipt objects, but these should not be required by the protocol because the returned transaction may perform any valid Sui operation.
Backward compatibility
The r parameter would be optional.
Wallets that support interactive transaction requests would detect r and initiate the extended flow. Wallets that do not support it could ignore the parameter and process any standard payment fields included in the URI.
When the request represents a non-payment transaction and no static fallback is available, an unsupported wallet should report that it cannot process the request.
This proposal takes influence from simple interactive transaction request protocols used by other major blockchain ecosystems while adapting the model to Sui’s Programmable Transaction Blocks, object model, sponsored transactions, and finality model.