Braid
Technical documentation · v1.0

From wallet state to confirmed portfolio state.

Braid is a non-custodial portfolio and execution interface. It converts supported wallet balances into valued positions, makes allocation explicit, validates a target, prepares a reviewable route and reconciles only after confirmed execution.

WalletAddress · network · balances
Portfolio adapterSupported positions
Market adapterPrice · source · freshness
Allocation engineCurrent · target · delta
Route engineQuote · constraints · expiry
Wallet authorizationApproval · signature
Onchain executionSubmission · receipt
ReconciliationConfirmed portfolio

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.

Non-custodial boundaryBraid never receives a seed phrase or private key. Connection, allowance and transaction signature remain separate wallet actions.

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.

wallet + chain → supported balances → normalized positions + price observations → portfolio value + current allocation → validated target + value deltas → quote + route constraints → wallet approval + transaction signature → submission + confirmation → balance refresh + reconciliation

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.

normalizedBalance = rawBalance / 10^decimals positionValue = normalizedBalance × usablePrice portfolioValue = Σ includedPositionValues allocation = positionValue / portfolioValue × 100

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.

targetValue(asset) = portfolioValue × targetWeight(asset) / 100 tradeDelta(asset) = targetValue(asset) − currentValue(asset)

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.

  1. 01idle
  2. 02approval-wallet
  3. 03approval-submitted
  4. 04approval-confirmed
  5. 05transaction-wallet
  6. 06transaction-submitted
  7. 07confirming
  8. 08confirmed
  9. 09reconciling
  10. 10reconciled

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

RPC unavailablePreserve last verified state and retry without clearing intent.
Missing priceHide dependent totals instead of substituting zero.
Quote expiredKeep target; rebuild route from current state.
Wallet rejectedReturn to review; no onchain failure is recorded.
Transaction revertedKeep hash and receipt details available.
Partial executionPreserve confirmed changes and reconcile before retry.

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

npm install npm run dev -- --port 3001 npm run build npm run start

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.

systemctl status braid-web.service journalctl -u braid-web.service -n 100 --no-pager nginx -t curl -I https://braidonchain.xyz/

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.