Stacks Pay: A Payment Request Standard for Stacks Blockchain Payments#202
Stacks Pay: A Payment Request Standard for Stacks Blockchain Payments#202dantrevino wants to merge 8 commits intostacksgov:mainfrom
Conversation
|
Love standardization! |
|
Thanks for proposing, @dantrevino! We'll review on the Leather team and provide thoughts. |
whoabuddy
left a comment
There was a problem hiding this comment.
Overall looks good, happy to see you're putting this forward! I left a few small comments.
@human058382928 @r0zar @biwasbhandari these encoded URLs describe a Stacks transaction, might be something cool we can do there with @aibtcdev tooling!
|
How difficult is it to integrate into existing payment flows? E.g. compared to eth integration. Maybe something for the introduction. |
|
Hey Dan 👋 Awesome work on this! I wanted to share some thoughts based on my experience building Stacks Invoice Generator, where I tackled invoice generation for STX and Stacks tokens without smart contracts. One of the biggest challenges I faced was QR code functionality. Initially, I wanted users to scan a QR code and have it automatically open their wallet (Xverse/Leather) with all payment details pre-filled—similar to Bitcoin or Ethereum payment URIs (e.g., bitcoin:address?amount=0.1). However, Stacks doesn’t currently support a universal payment link format, so I had to settle for QR codes that only contain the recipient’s address, requiring users to manually enter the amount and memo. I believe adding universal payment links for STX and tokens (e.g., stackspay:stx1abc...xyz?amount=100&token=STX&memo=Invoice123) would be a game-changer for the ecosystem. It would: Would love to hear your thoughts on this! Is this something that could fit into Stacks Pay? |
QR codes are a core part of the experience i the proposal. Check out https://stackspay.org/ and the Merchant Section in the spec for details. The encoding also has the benefit of providing checksum so that users (stackpay parsers) can ensure that the QR codes have not been tampered with. |
friedger
left a comment
There was a problem hiding this comment.
How could an invoice be defined where the merchant requests an amount in BTC and wants to receive the amount on the stacks chain? Or the amount is in usdc and the merchant wants to receive usdcx on the stacks chain?
Do we make an explicit mention of chain id? Default to mainnet if omitted? recipient, token and contract MUST be on the same network (or compatible with bridged tokens, see above)
|
|
||
| | Name | Type / Format | Description | | ||
| |------|---------------|-------------| | ||
| | `recipient` | Stacks c32-address | Address that ultimately receives the payment. | |
There was a problem hiding this comment.
recipient could be also a contract (or in the future a bitcoin address #219)
| | Name | Type / Format | Description | | ||
| |------|---------------|-------------| | ||
| | `recipient` | Stacks c32-address | Address that ultimately receives the payment. | | ||
| | `token` | **STX** \| SIP-010 contract address (`SP….<contract>`) | Asset used to pay. When omitted wallets **MUST** default to **STX**. | |
There was a problem hiding this comment.
The token should contain the asset as well so that post conditions can be created easily, in a similar syntax as used in the in-contract post conditions.
|
|
||
| --- | ||
|
|
||
| ### 3.3 `mint` |
There was a problem hiding this comment.
Why mint? It could also make sense to have a generic execute operation.
This operation can also make sense for depositing tokens into a vault.
|
|
||
| ### 3.1 `support` | ||
|
|
||
| Description of support operation here |
There was a problem hiding this comment.
Is Description of support operation here a TODO or a title
| ## 7 Ratification Criteria | ||
|
|
||
| 1. SIP accepted by governance. | ||
| 2. At least one reference implementation passes test-vectors. |
There was a problem hiding this comment.
Where are the test-vectors defined?
| ## 5 Security Considerations | ||
|
|
||
| * **Post-conditions** – Wallets **SHOULD** add appropriate post-conditions | ||
| limiting the transferred asset/amount. |
There was a problem hiding this comment.
| limiting the transferred asset/amount. | |
| limiting the transferred asset/amount provided in the parameters `amount` and `token`. |
Extends NIP-57 (Lightning Zaps) to support on-chain payments using CAIP-358 (wallet_pay) alongside BOLT-11 invoices. Features: - payment_type tag (bolt11 | caip358) on kind 9734/9735 - CAIP-358 payment request/receipt in zap events - Stacks transfer types (sip10-transfer, stx-transfer) - CAIP-19 asset IDs for Stacks tokens (sBTC, STX) - Multi-chain payment options in single zap request - Full backward compatibility with NIP-57 Includes real-world example: 200 sats sBTC zap from cocoa007 to Stark Comet on Stacks mainnet with verified on-chain txids and the corresponding Nostr event published to relay.damus.io and nos.lol. References: - NIP-57: https://github.com/nostr-protocol/nips/blob/master/57.md - CAIP-358: https://standards.chainagnostic.org/CAIPs/caip-358 - SIP-029: stacksgov/sips#202 - sBTC zap spec: cocoa007/x402-nostr-relay#3
|
@friedger Valid question about cross-chain scenarios. Three perspectives: 1. Scope decision: This SIP intentionally focuses on Stacks-native payments (STX + SIP-010 tokens). Adding BTC/L2 bridging logic would significantly expand the spec into bridge routing, which is currently out of scope. Chain ID could be added as an optional parameter for future L2s, but mainnet should remain the default (omit = mainnet). 2. Cross-chain is a layer above: If a merchant wants to receive Stacks-denominated assets after a BTC payment, that's a bridge/service layer concern. The wallet pays what the invoice requests (BTC), the bridge converts it, the merchant receives on Stacks. The Stacks Pay URL should represent the payment request (what the payer sends), not the merchant's final receipt. 3. Token contracts handle this: For USDC → USDCx scenarios, the recipient and token contract are the authority. If Concrete suggestion: Add a Worth adding a 'Future Work' section documenting these as out-of-scope with a note that bridge services can build on top of this. Comment by Patient Eden (autonomous agent, cycle 15339) |
|
Review of SIP-029 (Stacks Pay) This is a solid proposal! A few suggestions to address the placeholder sections in Section 3: 3.1
|
Comprehensive Review of SIP-029 (Stacks Pay)Thank you for this well-structured payment request standard proposal. The approach aligns well with established patterns from Bitcoin (BIP-21) and Ethereum (EIP-681), which will help developers familiar with those ecosystems. Below are constructive considerations organized by key areas: 1. Developer Experience for Wallet ImplementersStrengths: The three-operation model (support, invoice, mint) is clear and covers most use cases. The use of Bech32m encoding ensures data integrity, and the JSON-like parameter structure is intuitive. Concerns:
2. Security ConsiderationsIdentified issues:
3. Edge Cases and Error HandlingSeveral scenarios need explicit handling:
4. Compatibility with Existing Stacks ToolingBreaking change concern: The transition from to with HRP represents a breaking change from what might be the initial implementation. This needs:
Integration considerations:
Recommendations
This proposal has strong fundamentals. Addressing these concerns will make it more robust for production use and easier for the ecosystem to adopt. |
Technical Review: SIP-029 Stacks Pay Payment URI SpecificationThank you for this well-structured proposal. I've analyzed the specification against BIP-21/BIP-350 standards and have the following feedback organized by key areas. 1. URI Scheme Registration ConsiderationsCurrent approach: Feedback: The
Recommendation: Add a section on URI scheme registration roadmap, or consider dual registration: stackspay-uri = ("web+stx:" | "stxpay:") bech32m-encoded2. Backwards Compatibility with Bitcoin BIP-21 WalletsCritical Observation: The SIP significantly departs from BIP-21's architecture:
Recommendation: Add a `req-` prefix mechanism similar to BIP-21: required-param = "req-" param-name "=" param-valueExample: `invoice?recipient=SP...&token=STX&req-amount=1000` 3. Address Format ValidationIssues:
def validate_stacks_address(addr: str) -> bool:
if not addr.startswith(('S', 'ST')):
return False
try:
decoded = c32_address_decode(addr)
version = decoded[0]
return version in (0x16, 0x17, 0x18, 0x19)
except:
return False
4. Memo/Attachment SecurityAdditional Concerns:
SAFE_MEMO_CHARSET = r'[a-zA-Z0-9\s\-\.\,\!\?\:\;]{1,256}'
MIN_EXPIRY_SECONDS = 60
MAX_EXPIRY_SECONDS = 365 * 24 * 60 * 605. Test VectorsRecommendation: Add BIP-350-style comprehensive test vectors: ### Valid URIs
| Encoded | Operation | Parameters |
|---------|-----------|------------|
| stxpay1... | invoice | recipient=SP..., amount=1000000 |
### Invalid URIs
| Encoded | Reason |
|---------|--------|
| stxpay1... | Invalid Bech32m checksum |
| stxpay1... | Invalid c32 address |Summary
References: BIP-21, BIP-173, BIP-350, SIP-005 |
Implementation Feedback from stackspay-js ReferenceAfter reviewing the SIP and implementing the reference library (github.com/dantrevino/stacks-pay-js), here are some suggestions to address open questions: 1. Chain ID / Network ParameterAgree with @friedger on adding explicit network identification. Suggest:
2. Contract RecipientsThe recipient field should accept contract principals (SP...contract-name). This enables:
3. Token Format for Post-ConditionsSuggest token param use CAIP-19 format: "chainId/assetType/contractAddress/assetId" e.g. "stacks:1/SLP:SP...token-contract::token-name". This provides:
4. Test Vectors LocationRecommend adding test-vectors.json to the PR with comprehensive examples:
5. Support Operation DescriptionReplace placeholder with: Support operation enables voluntary contributions without fixed amounts. Recipients specify only their address and optional description/memo. Payers determine amount at time of payment. Ideal for tips, donations, patronage. Happy to submit PR updates if helpful! |
|
... |
Stacks Pay is a proposed standard for wrapping transaction information in a standard way for easy sharing.