Product model
A wallet contains balances, not a portfolio model. Braid identifies supported assets, normalizes token units, attaches market observations and derives position value and allocation. A user-defined target becomes portfolio intent. Braid converts the difference between observed and intended allocation into an execution plan without confusing intent, quote and confirmed state.
Architecture and data flow
The interface separates wallet state, market state, derived portfolio state and transaction state. Each domain can fail or refresh independently without overwriting the others.
Integration boundaries
- Wallet adapter: EIP-1193 account and chain access.
- Portfolio adapter: supported token metadata and balances.
- Market adapter: price, source, timestamp and freshness.
- Route adapter: quote, calldata, limits, fees and expiry.
- Receipt adapter: transaction status and confirmed block.
Wallet connection
The client uses the injected EIP-1193 provider directly. eth_accounts restores an existing authorized session, eth_requestAccounts requests connection and eth_chainId reads the active network. The interface subscribes to accountsChanged and chainChanged so identity and network never become stale after a wallet-side change.
What connection authorizes
Connection returns a public address and chain identifier. It does not create token allowance, sign calldata or move funds. When execution requires approval, Braid requests the required allowance as a dedicated wallet step before requesting the portfolio transaction.
Disconnect semantics
Disconnect clears the local Braid session. Browser wallets remain responsible for revoking the website permission because injected providers do not expose one portable permission-revocation method.
Portfolio engine
Every included position carries token identity, normalized balance, decimals, price, price state, derived value and allocation weight. Missing data stays explicit. An unavailable price is never silently represented as zero because that would corrupt both total value and allocation.
Transaction-building code should use integer token units or an audited decimal library. Formatted JavaScript numbers belong to presentation, not calldata.
Allocation and portfolio intent
Current allocation is derived from confirmed holdings and usable prices. Target allocation is user intent. A target is valid only when each value is finite, each weight is between 0 and 100 and the sum equals 100 within the configured tolerance.
Positive deltas require acquisition; negative deltas require reduction. Editing target weights never mutates observed balances and never creates a transaction.
Quote and routing model
A route must expose the input amount, expected output, minimum received, fee estimate, slippage limit, approval requirement, expiry and the network state from which it was derived. Route comparison keeps execution tradeoffs visible before wallet authorization.
- Expired quotes are discarded while portfolio intent remains saved.
- Minimum received protects against execution below the accepted output boundary.
- Allowance should be limited to the amount required by the selected route.
- Changing balance, network or target invalidates dependent quotes.
Execution lifecycle
Approval and portfolio execution are tracked separately. Submitted transactions are not marked complete until a receipt satisfies the configured confirmation policy.
- 01
idle - 02
approval-wallet - 03
approval-submitted - 04
approval-confirmed - 05
transaction-wallet - 06
transaction-submitted - 07
confirming - 08
confirmed - 09
reconciling - 10
reconciled
Reconciliation
After confirmation, Braid refreshes balances and market state, reconstructs the portfolio and compares actual allocation with the original target. Expected output never overwrites this result.
Failure and recovery model
Security and privacy boundaries
- Never request, transmit or store seed phrases or private keys.
- Validate chain ID, token addresses, decimals and contract allowlists.
- Schema-validate every RPC, pricing and routing response.
- Display values from the same integer inputs used to build calldata.
- Apply request timeouts, bounded retries and rate limiting to external providers.
- Keep public address data separate from analytics identities.
- Expose approval, signing, submission and confirmation as distinct states.
See the Privacy Policy for the user-facing treatment of wallet and provider data.
Development and operations
Production uses the standalone Next.js output behind Nginx. The application listens on loopback port 3005 and runs under braid-web.service. Nginx terminates TLS and forwards application traffic. systemd starts the process after reboot and restarts it after an unexpected exit.
Release policy
Build once, deploy a timestamped release, validate the origin, atomically update the current symlink, restart the service, validate public HTTPS and retain a recoverable previous release or archive.