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.
| Page | Who uses it | What the wallet does |
|---|---|---|
Brand console, https://swayoffers.com/console | Brands | Signs in, registers the brand, posts the bond, creates and funds campaigns, posts sealed offers and rotates the receipt key |
Integrator console, https://swayoffers.com/agents | Agent developers | Acts 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/admin | The Sway operator, with the deployment's Config admin wallet | Activates 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
| Asset | What it pays for |
|---|---|
| SOL | The 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 |
| USDC | The 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:
- Connect the wallet.
- 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.
- 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
| Button | Your wallet signs | Effect |
|---|---|---|
| Sign in with this wallet | The challenge message | A merchant session for this tab. No funds move |
| Register | register_merchant | Creates your merchant account with the receipt signer and return window, and its bond account |
| Post bond | post_bond | Moves USDC from your wallet into the merchant's bond account |
| Rotate receipt key | rotate_receipt_signer | Registers a replacement receipt key created in this browser and opens the next signer epoch |
| Create campaign | create_campaign | Creates the campaign with its caps and lock, and its USDC vault |
| Fund | fund_campaign | Moves USDC from your wallet into the campaign vault |
| Withdraw | withdraw_campaign | Moves USDC still in the vault back to your wallet |
| Seal and post offer | submit_offer | Queues the sealed offer for ingest into the category book |
| Sign and send receipt | Nothing | The receipt key in this browser signs the 128-byte receipt |
| Refund | Nothing | The receipt key in this browser signs the 128-byte refund notice |
Integrator console
| Button | Your wallet signs | Effect |
|---|---|---|
| Register | The integrator_registration challenge message | Registers the integrator with this wallet as its authority. No funds move |
| Register agent key | The agent_registration challenge message and a SwayIntegrator request | Registers an agent device's public key under your integrator |
| Revoke | A SwayIntegrator request | Revokes that agent key |
Operator page
| Button | Your wallet signs | Effect |
|---|---|---|
| Sign in with this wallet | The challenge message | A session for submitting the operator's transactions |
| Load pending requests | Four SwayAdmin requests | Lists the merchants and integrators waiting for approval, the active and suspended merchants, and the open disputes |
| Activate | A SwayAdmin request, then activate_merchant | Activates a bonded merchant. The button works once the page is signed in |
| Approve | A SwayAdmin request | Approves the integrator, whose status becomes active |
| Suspend | A SwayAdmin request, then suspend_merchant | Suspends an active merchant |
| Release bond | A SwayAdmin request, then release_bond | Pays a suspended merchant's whole bond to its wallet's own USDC account; refused with BOND_LOCKED while a liability remains |
| Resolve | A SwayAdmin request, then slash_bond for a shopper outcome | Records 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
| Button | What it does |
|---|---|
| Sign out | Forgets the session in this tab. The wallet stays connected |
| Disconnect | Signs 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.