Sway

Connect a wallet

Three pages on the site take a browser wallet. Shoppers never connect one; they give their agent an address at claim time.

PageWho uses itWhat the wallet does
Brand console, https://swayoffers.com/consoleBrandsSigns in, registers the brand, posts the bond, creates and funds campaigns, posts sealed offers and rotates the receipt key
Integrator console, https://swayoffers.com/agentsAgent developersActs as the integrator authority: registers the integrator and each agent device's key. It signs messages only, never a transaction
Operator page, https://swayoffers.com/adminThe Sway operator, with the deployment's Config admin walletActivates and suspends merchants, releases bonds, resolves disputes and approves integrators

An agent device's own key never goes into a wallet: it lives in that device's operating-system keychain (see For agent developers).

Supported wallets

All three pages find wallets through Wallet Standard. Every Solana wallet installed in the browser that registers through Wallet Standard appears as a button named after it, for example Connect Phantom. The pages name Phantom, Solflare and Backpack. Hardware wallets that connect over USB, such as Ledger, Trezor and Keystone, are not offered.

If the browser has no Solana wallet, the panel reads: "No Solana wallet found in this browser. Install Phantom, Solflare or Backpack, then reload this page."

The network

The top bar names the Solana cluster the page signs for, Devnet or Mainnet. Set your wallet to the same cluster before you sign anything. Every transaction a page asks you to sign is prepared by the Sway API for that cluster, its sway_exchange program and its USDC mint.

What you need in the wallet

AssetWhat it pays for
SOLThe fee of every transaction your wallet signs, and the rent of the accounts your actions create: the merchant and bond accounts at registration, a campaign and its vault, each offer submission
USDCThe bond and campaign funding. USDC settles as a plain SPL token with 6 decimals

The brand console takes USDC from your wallet's associated USDC token account, and a campaign withdrawal returns to that same account. Forms take amounts in USDC, such as 250 or 12.50; the API receives them as base units.

Recording an order and refunding one need nothing from the wallet. The receipt key in the browser signs them, and Sway's relayer submits them.

The integrator console signs only messages, so the wallet pays no fees there. When the connected wallet is also your payout wallet, it must already exist on chain, holding SOL.

Signing in

The brand console and the operator page sign in with the wallet:

  1. Connect the wallet.
  2. Select Sign in with this wallet. The page asks the API for a one-use challenge, and the wallet shows a message to sign. It is a message signature, not a transaction.
  3. The API checks the signature and issues a session. The page keeps it in this browser tab until it expires.

The message has nine lines:

Sway authorization v1
Audience: <the origin this challenge is bound to>
Purpose: merchant_session
Public-Key: <your wallet address>
Nonce: <random, 43 characters>
Issued-At: <ISO time>
Expires-At: <ISO time>
Request-SHA256: <hash of the sign-in request>
Resources-SHA256: <hash of the resource list>

The challenge works once and only until Expires-At. A session belongs to one wallet: opening the page in a new tab, or connecting a different wallet, asks you to sign in again. On the operator page, the session carries the Config admin wallet's activation, suspension, bond release and bond debit transactions; the admin wallet signs in without registering a merchant.

Signed requests

The integrator console has no sign-in. Instead the wallet signs each request it makes to the API, and the operator page signs its requests the same way. Your wallet shows a nine-line message that begins Sway signed request v1 and names the page's role (SwayIntegrator or SwayAdmin), the request's method and path, and a hash of its body. Each signature is good for that one request. The integrator console signs one when it reads your integrator's status on page load, and one more for the agent-key list once the integrator is active. API and MCP gives the exact format.

What each signature does

Every on-chain action runs the same way. The API prepares the transaction, your wallet signs exactly those bytes, and the page submits them. In the brand console, the status line under the button moves through "Preparing the transaction", your wallet's approval prompt, "Waiting for the chain" and "Confirmed". The page checks the chain once a second for up to 90 seconds.

Brand console

ButtonYour wallet signsEffect
Sign in with this walletThe challenge messageA merchant session for this tab. No funds move
Registerregister_merchantCreates your merchant account with the receipt signer and return window, and its bond account
Post bondpost_bondMoves USDC from your wallet into the merchant's bond account
Rotate receipt keyrotate_receipt_signerRegisters a replacement receipt key created in this browser and opens the next signer epoch
Create campaigncreate_campaignCreates the campaign with its caps and lock, and its USDC vault
Fundfund_campaignMoves USDC from your wallet into the campaign vault
Withdrawwithdraw_campaignMoves USDC still in the vault back to your wallet
Seal and post offersubmit_offerQueues the sealed offer for ingest into the category book
Sign and send receiptNothingThe receipt key in this browser signs the 128-byte receipt
RefundNothingThe receipt key in this browser signs the 128-byte refund notice

Integrator console

ButtonYour wallet signsEffect
RegisterThe integrator_registration challenge messageRegisters the integrator with this wallet as its authority. No funds move
Register agent keyThe agent_registration challenge message and a SwayIntegrator requestRegisters an agent device's public key under your integrator
RevokeA SwayIntegrator requestRevokes that agent key

Operator page

ButtonYour wallet signsEffect
Sign in with this walletThe challenge messageA session for submitting the operator's transactions
Load pending requestsFour SwayAdmin requestsLists the merchants and integrators waiting for approval, the active and suspended merchants, and the open disputes
ActivateA SwayAdmin request, then activate_merchantActivates a bonded merchant. The button works once the page is signed in
ApproveA SwayAdmin requestApproves the integrator, whose status becomes active
SuspendA SwayAdmin request, then suspend_merchantSuspends an active merchant
Release bondA SwayAdmin request, then release_bondPays a suspended merchant's whole bond to its wallet's own USDC account; refused with BOND_LOCKED while a liability remains
ResolveA SwayAdmin request, then slash_bond for a shopper outcomeRecords the outcome with the SHA-256 of the resolution note; a shopper outcome pays the bond debit to the compensation address

A wallet may add compute-budget instructions or a Lighthouse guard instruction to a prepared transaction. The API refuses any other change, such as a different instruction, signer or blockhash, with INVALID_SIGNATURE. It also simulates each signed transaction before sending it. If the simulation fails, the page shows TRANSACTION_SIMULATION_FAILED: refresh your balances and try the action again.

Signing out and disconnecting

ButtonWhat it does
Sign outForgets the session in this tab. The wallet stays connected
DisconnectSigns out and disconnects the wallet from the page

Your merchant account, bond, campaigns and offers belong to your wallet address. Connect the same wallet and sign in again, and the brand console reads them back. The receipt signer is separate from the wallet and stays in the browser profile; For brands explains how to keep it and rotate it. The integrator console remembers your integrator ID for the wallet in this browser.