How to use this portal

Guide to connecting your wallet, onboarding a bank on testnet, and using the bank and admin dashboards.

Getting started

This portal is a dashboard for issuing and managing $USDA+ on Ethereum Sepolia (testnet). Connect a wallet that holds the appropriate on-chain role, then use the Bank or Admin tabs.

  1. Choose a connection method in the top right:
    • Connect extension - MetaMask, Fireblocks browser extension, or other injected wallet.
    • Connect WalletConnect - Fireblocks mobile or MetaMask mobile (scan QR). Requires Sepolia support - Rainbow mobile will not work on this testnet portal.
  2. Approve the connection and switch to Sepolia (chainId 11155111) if prompted.
  3. The portal reads chain data and submits transactions through your connected wallet.

Your on-chain roles (minter, burner, manager) are detected automatically after you connect.

For WalletConnect Project ID, Fireblocks policy, and environment setup, see WALLET_SETUP.md in the repository root.

Contracts on Sepolia

$USDA+ uses 6 decimals - 1 $USDA+ = 1_000_000 base units. Transfers to the token contract itself are blocked; use Burn to redeem.

Bank dashboard

The Bank tab is for issuer wallets that mint, burn, or transfer $USDA+.

Account summary

Shows your $USDA+ balance, remaining mint allowance (bounded and decrementing - each mint draws it down), role badges, pause state, and Etherscan links.

Mint

Visible if your wallet has the minter role. Enter recipient address and $USDA+ amount (whole numbers; scaled to 6 decimal places on-chain), then Sign in wallet. The allowance decrements on each mint and does not refill on its own.

Approve

Available to any connected wallet holding $USDA+. Enter the spender address and amount, then Sign in wallet. This grants standard ERC-20 allowance so the spender can move tokens from your balance (e.g. via transferFrom or burn). To burn your own balance, set the spender to your wallet address.

Burn

Visible if your wallet has the burner role. The source address must approve your wallet for the burn amount on the token contract first, then you call burn.

Transfer

Move $USDA+ from your connected wallet to another address.

TransferFrom

Move $USDA+ from an address you have allowance over. The source must have approved your wallet first.

Issuers on-chain

Lists all wallets with active minter or burner roles, indexed from authority contract events.

Webhooks card

Placeholder for a future subscription UI. See Webhooks (planned) below for the intended delivery model.

Signing transactions

Every action uses Sign in wallet - the portal submits the transaction through your connected wallet (extension or WalletConnect).

  • Extension - MetaMask, Fireblocks browser extension, etc. Connect via Connect extension.
  • WalletConnect - Fireblocks mobile and other WC wallets. Connect via Connect WalletConnect and scan the QR code.

Amounts are entered as whole $USDA+ (e.g. 1000 = 1,000 $USDA+). Values are scaled to 6 decimal places on-chain (10001_000_000_000 base units).

See WALLET_SETUP.md for WalletConnect and Fireblocks configuration.

WalletConnect / Fireblocks debugging

Append ?debug=wallet to any portal URL to open the wallet debug panel (only while that query param is present). It shows the settled WalletConnect session topic, approved chains/methods (including whether eth_sendTransaction and Sepolia are present), and the last support diagnostics bundle. Failed connects/writes also offer Copy diagnostics on the error toast for Fireblocks Support.

Admin dashboard

The Admin tab appears only when the connected wallet is the on-chain manager.

Protocol

View manager, owner, pause state. Use Pause / Unpause to halt or resume mint and burn authorization network-wide (transfers are unaffected).

Manage roles & allowances

  1. Choose a function from the dropdown.
  2. Fill in only the fields shown (address only for role changes; address + amount for allowance changes).
  3. Click Sign in wallet.
FunctionWhen to use
addMinter / addBurnerWhitelist a bank custody wallet for issuance.
setMintAllowanceInitial bounded allowance for a new minter.
increaseMintAllowanceExtend capacity after review.
decreaseMintAllowanceReduce a minter's remaining capacity.
removeMinter / removeBurnerRevoke roles from a wallet.

Active wallets

On-chain list of issuers. Click Manage this wallet to pre-fill the form above.

The reserve columns show mock Chainlink PoR data for now - they do not auto-submit transactions.

Onboarding a new bank

Partner onboarding runs commercial and technical tracks in parallel. This portal covers the technical testnet steps - everything else (NDA, LOI, due diligence, mainnet go-live) is handled outside the portal.

What is live today. On-chain mint, burn, and transfer on Sepolia. In-portal onboarding automation, per-bank SSO, and webhook delivery are not built yet.

Before you use the portal

  1. The bank shares the custody wallet address(es) to whitelist.
  2. Commercial / compliance stages complete (vendor DDQ, cyber, regulatory questionnaires) - handled outside the portal.

In the Admin tab (manager wallet)

  1. Add minter and Add burner for the bank's custody address.
  2. Set mint allowance - a bounded, non-refilling cap. Each mint decrements it; use Increase mint allowance to extend after review.

In the Bank tab (bank's custody wallet)

  1. Connect the whitelisted wallet and confirm minter / burner badges and allowance in the account summary.
  2. Run a test Mint to a destination address and confirm the allowance decrements.
  3. Run a test Burn - the holder must approve the burner first.
  4. Optionally test Transfer to another participant.

Exit criteria (technical track)

Whitelist + roles + allowance live on Sepolia; successful mint and burn from the bank's wallet. When webhooks ship, registering an endpoint and verifying the HMAC signature will be part of this gate.

Mainnet go-live is gated separately on GENIUS items (lawful-order freeze/seize, proof-of-reserves) - not available in this portal build.

Webhooks (planned)

Proposed - not yet built. The Webhooks card on the Bank tab is a placeholder. Only on-chain mint / burn / transfer on Sepolia is live today. The design below may change.

When shipped, the integration platform would turn on-chain activity into readable events and POST signed webhooks to each bank's registered HTTPS endpoint - so your systems do not need to poll the chain.

Event types (planned)

TypeTriggers when
mintA whitelisted issuer calls token.mint(dst, amt). Payload includes minter, recipient, amount, and remaining allowance.
redeemAn issuer calls token.burn(src, amt) after approval. Payload includes burner, source holder, and amount.
por_updateProposed proof-of-reserve snapshot - no data source exists today.
feed_readingProposed generic oracle reading between snapshots.

Each event would carry an id (idempotency key), type, org_id, chain_tx, block_number, status (pending until finalized), payload, and created_at.

Verifying delivery (planned)

Each POST would include X-USDAPlus-Signature - a lowercase-hex HMAC-SHA256 over the raw request body, keyed with your per-bank secret. Verify in constant time before trusting the payload.

import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody MUST be the exact bytes received, not a re-serialized object.
export function verify(rawBody, header, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected, "utf8");
  const b = Buffer.from(header, "utf8");
  return a.length === b.length && timingSafeEqual(a, b);
}

Re-serializing JSON before hashing would change the signature and fail verification.

What you will do in the portal (planned)

  • Register your HTTPS subscription URL from the Bank tab Webhooks card.
  • Receive a per-bank signing secret and verify the first test delivery.
  • Act only on events with status: finalized - treat repeated id values as duplicates.