diff --git a/src/components/cards.tsx b/src/components/cards.tsx index 8397f9d6..0e25a18b 100644 --- a/src/components/cards.tsx +++ b/src/components/cards.tsx @@ -231,6 +231,39 @@ export function LightningSessionCard() { ); } +export function SolanaMethodCard() { + return ( + + ); +} + +export function SolanaChargeCard() { + return ( + + ); +} + +export function SolanaSessionCard() { + return ( + + ); +} + export function StripeMethodCard() { return ( = { "/payment-methods/stripe": "Stripe", "/payment-methods/card": "Card", "/payment-methods/lightning": "Lightning", + "/payment-methods/solana": "Solana", "/payment-methods/custom": "Custom", "/intents": "Intents", "/protocol/transports": "Transports", diff --git a/src/pages/intents/charge.mdx b/src/pages/intents/charge.mdx index 5a84b593..d6d882d0 100644 --- a/src/pages/intents/charge.mdx +++ b/src/pages/intents/charge.mdx @@ -5,7 +5,7 @@ imageDescription: "Immediate one-time payments where the full amount is collecte import { Cards } from 'vocs' import { MermaidDiagram } from '../../components/MermaidDiagram' -import { TempoChargeCard, StripeMethodCard, LightningMethodCard, CardMethodCard } from '../../components/cards' +import { TempoChargeCard, StripeMethodCard, LightningMethodCard, SolanaChargeCard, CardMethodCard } from '../../components/cards' import { SpecCard } from '../../components/SpecCard' # Charge [Immediate one-time payments] @@ -69,6 +69,7 @@ Each payment method defines how charge is fulfilled, verified, and settled on it + diff --git a/src/pages/payment-methods/index.mdx b/src/pages/payment-methods/index.mdx index e0c86d9d..1e59a349 100644 --- a/src/pages/payment-methods/index.mdx +++ b/src/pages/payment-methods/index.mdx @@ -3,7 +3,7 @@ imageDescription: "Available payment methods in MPP and how to choose the right --- import { Cards, Tab, Tabs } from 'vocs' -import { TempoMethodCard, CardMethodCard, LightningMethodCard, StripeMethodCard, CustomMethodCard } from '../../components/cards' +import { TempoMethodCard, CardMethodCard, LightningMethodCard, SolanaMethodCard, StripeMethodCard, CustomMethodCard } from '../../components/cards' # Payment methods [Available methods and how to choose one] @@ -36,6 +36,12 @@ WWW-Authenticate: Payment method="card", intent="charge", ... ```http HTTP/1.1 402 Payment Required WWW-Authenticate: Payment method="lightning", intent="charge", ... +``` + + +```http +HTTP/1.1 402 Payment Required +WWW-Authenticate: Payment method="solana", intent="charge", ... ``` @@ -47,5 +53,6 @@ WWW-Authenticate: Payment method="lightning", intent="charge", ... + diff --git a/src/pages/payment-methods/solana/charge.mdx b/src/pages/payment-methods/solana/charge.mdx new file mode 100644 index 00000000..edc995d8 --- /dev/null +++ b/src/pages/payment-methods/solana/charge.mdx @@ -0,0 +1,63 @@ +--- +imageDescription: "One-time Solana payments using signed transactions or confirmed transaction signatures" +--- + +import { Cards } from 'vocs' +import { SpecCard } from '../../../components/SpecCard' + +# Solana charge [One-time payments on Solana] + +The Solana implementation of the [charge](/intents/charge) intent. + +The server issues a charge challenge describing the expected amount, currency, recipient, and Solana-specific `methodDetails`. The client either presents a signed transaction for server broadcast or presents a confirmed transaction signature. The server verifies the transfer on-chain and returns the resource with a receipt. + +This method is best for fixed-price API calls, digital goods, and payments that should settle directly on Solana. + +## Server + +Use `solana.charge` to gate endpoints behind native SOL or SPL token payments. + +```ts +import { Mppx } from 'mppx/server' +import { solana } from '@solana/mpp/server' + +const mppx = Mppx.create({ + methods: [solana.charge({ + recipient: '9xAXssX9j7vuK99c7cFwqbixzL3bFrzPy9PUhCtDPAYJ', + network: 'devnet', + })], + secretKey: process.env.MPP_SECRET_KEY!, +}) +``` + +## Client + +Use `solana.charge` with `Mppx.create` to automatically handle Solana charge challenges. + +```ts +import { Mppx } from 'mppx/client' +import { solana } from '@solana/mpp/client' + +const mppx = Mppx.create({ + methods: [solana.charge()], +}) +``` + +## Solana-specific request fields + +The Solana charge request extends the base charge schema with `methodDetails` fields such as: + +- `network` +- `decimals` +- `tokenProgram` +- `feePayer` +- `feePayerKey` +- `splits` + +These fields let the server describe whether payment is in SOL or an SPL asset, whether fee sponsorship is available, and whether the payment should be split across multiple recipients. + +## Specification + + + + diff --git a/src/pages/payment-methods/solana/index.mdx b/src/pages/payment-methods/solana/index.mdx new file mode 100644 index 00000000..e1c8e421 --- /dev/null +++ b/src/pages/payment-methods/solana/index.mdx @@ -0,0 +1,60 @@ +--- +imageDescription: "Native SOL and SPL token payments on Solana for one-time and session-based billing" +--- + +# Solana [Native SOL and SPL token payments] + +The Solana payment method enables MPP payments on Solana using native SOL, SPL tokens, and Token-2022 assets. Solana supports two intents: **charge** for one-time payments and **session** for escrowed, pay-as-you-go billing. + +The reference implementation is provided by [`@solana/mpp`](https://github.com/solana-foundation/mpp-sdk), which extends [`mppx`](https://github.com/tempoxyz/mpp) with Solana-native client and server handlers. + +## Installation + +:::code-group +```bash [npm] +npm install @solana/mpp mppx @solana/kit +``` +```bash [pnpm] +pnpm add @solana/mpp mppx @solana/kit +``` +::: + +## Why Solana + +Solana enables several useful capabilities for MPP: + +- **Split payouts and richer settlement flows** through multiple instructions per transaction +- **Fast finality** for low-latency charge flows +- **Cheap transactions** for micropayments and fee-sponsored UX +- **Native fee payer support** so servers can sponsor network fees +- **Token flexibility** across SOL, SPL, and Token-2022 assets +- **Delegated signer options** including Ed25519 and passkey-friendly secp256r1 flows + +## Choosing an intent + +| | **Charge** | **Session** | +|---|---|---| +| **Pattern** | One-time payment per request | Escrow once, pay incrementally with vouchers | +| **Latency overhead** | One transaction or confirmed signature per request | Low after open; vouchers are off-chain | +| **Throughput** | Best for discrete purchases | Best for high-frequency metered usage | +| **Best for** | Paid API calls, downloads, fixed-price purchases | LLM APIs, streaming, repeated calls | +| **Settlement** | Immediate on-chain transfer | Escrow on-chain, settle accepted usage later | + +## Intents + + + + + + + Solana charge + One-time payments with signed transactions or confirmed signatures + + + + + + Solana session + Coming soon: Solana sessions with off-chain vouchers and on-chain settlement + + diff --git a/vocs.config.ts b/vocs.config.ts index 3dad35f0..af906749 100644 --- a/vocs.config.ts +++ b/vocs.config.ts @@ -355,6 +355,14 @@ export default defineConfig({ { text: "Session", link: "/payment-methods/lightning/session" }, ], }, + { + text: "Solana", + collapsed: true, + items: [ + { text: "Overview", link: "/payment-methods/solana" }, + { text: "Charge", link: "/payment-methods/solana/charge" }, + ], + }, { text: "Custom", link: "/payment-methods/custom" }, ], },