x402 Progressive Demo · Chapter 2 of 7

Choose Your Recipient

What if the buyer picks who to pay?
Published 2026-04-16 · Northwoods Software · x402 Payment Protocol

Where We Left Off

In Chapter 1, we proved the simplest possible thing: one buyer sends USDC to one seller on Solana. The recipient wallet address was hardcoded — a constant baked into the page. That was the right starting point. It isolated the payment mechanics and confirmed that the x402 protocol works end-to-end: request, sign, broadcast, verify.

But a real-world shop doesn't have one seller. A marketplace has many. A publisher network has many authors. A merch store might split revenue between the brand, the designer, and the fulfillment partner. The question for Chapter 2: can the buyer choose who gets paid — without changing the payment code?

The Change: One Line

Here is the entirety of what changed between Chapter 1 and Chapter 2. The payment flow — connect wallet, build transaction, sign, broadcast, verify on-chain — is identical. The only difference is where the recipient address comes from.

Chapter 1Chapter 2
payTo = "fixed_wallet_address" payTo = dropdown.selectedValue

A dropdown menu lists the available recipients — each one is just a name paired with a Solana wallet address. When the buyer selects a recipient and clicks "Pay," the same payment function fires. It reads the payTo field from the dropdown instead of a constant. That's it.

Key insight: One line of code changed. Same protocol. The recipient field went from a constant to a variable. This proves x402 scales to N authors, sellers, or partners without rewriting the payment flow. Each recipient is just a wallet address.

Why This Matters

This is a small code change but a significant conceptual step. It demonstrates that the x402 payment protocol is recipient-agnostic. The protocol doesn't care who receives the funds — it cares that a valid USDC transfer happened on-chain from the buyer to whoever was specified. This has direct implications for real business models:

How the Demo Works

┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Buyer's │ │ Recipient │ │ Solana │ │ Browser │ │ Dropdown │ │ Devnet │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ 1. │ selects recipient │ │ │───────────────────▶│ │ │ │ │ 2. │ wallet address │ │ │◀───────────────────│ │ │ │ │ 3. │ builds tx with │ │ │ selected payTo │ │ │─────────────────────────────────────────▶ │ │ │ 4. │ signs + broadcasts│ │ │─────────────────────────────────────────▶ │ │ │ 5. │ confirmed on-chain│ │ │◀───────────────────────────────────────── │ │ │

The recipient list is a simple data structure — an array of objects, each with a name and a walletAddress. In this demo, the list is defined in the page. In a production system, it would come from a database, an API, or a CMS like Titan.

const recipients = [
  { name: "Alice (Author)",   walletAddress: "A1ice...xyz" },
  { name: "Bob (Designer)",   walletAddress: "B0b...abc" },
  { name: "Carol (Publisher)",walletAddress: "Car0l...def" },
]

// Payment function — unchanged from Chapter 1
async function pay(payTo, amountUSDC) {
  const tx = buildTransferTx(buyer, payTo, amountUSDC)
  const signed = await wallet.signTransaction(tx)
  const sig = await connection.sendRawTransaction(signed.serialize())
  return sig
}

The pay() function is byte-for-byte identical to Chapter 1. It accepts a payTo parameter. Chapter 1 always passed the same address. Chapter 2 passes whichever address the buyer selected. The protocol doesn't know or care about the difference.

What This Tells Us About x402

The x402 protocol treats the recipient wallet address as a parameter, not a configuration. This is by design. The protocol's job is to ensure that a valid USDC transfer happens on-chain — it verifies the amount, the token (USDC), and the network (Solana). Who receives the funds is a business decision, not a protocol decision.

This separation matters because it means x402 can serve fundamentally different business models without protocol changes:

Business ModelWho Sets the RecipientProtocol Change Needed
Single-seller shopHardcoded (Chapter 1)None
MarketplaceProduct catalog (Chapter 2)None
Publisher networkArticle metadataNone
Tip jar / donationCreator profileNone
Revenue splitSmart contractMulti-output (future)
The pattern holds. Every row except the last requires zero protocol changes. The recipient is just data. The protocol is the pipe.
Note: Chapters 2 and beyond require running the x402 gateway locally to try the demos. See the project's README for setup instructions, including Solana devnet configuration and wallet requirements.

What's Next

Choosing a recipient is a user-interface concern. The payment itself is still "buyer clicks pay, money moves." But what if the content is locked — and the buyer has to pay before they can see it? That's a fundamentally different interaction: the server has to enforce access control based on payment status.

In Chapter 3: Minimal Paywall, we add the HTTP 402 response code — the one the protocol is named after — and build the simplest possible pay-to-read flow. The payment mechanics are identical. The new part is the access layer.