BRC-214 Wallet

Wallet Asset Profiles

A BRC-100 wallet holds more than one kind of value: BSV, coins of other chains, items, Bitcoin Native Tokens (BNT) and Issuer-Permissioned Tokens (IPT). Each kind has its own storage, its own proof of authenticity, and its own way for applications to see and move it. This document calls those kinds asset profiles . A profile is the unit of everything an appl

Brandon Cryderman / HandCash (brandongcryderman@gmail.com) Status: Draft (proposed number, not a BSVA assignment)

How it connects

Relationships

Authoritative content mirror

Full upstream text

View source ↗
Rendered from wallet/0214.md at the indexed upstream commit

Abstract

A BRC-100 wallet holds more than one kind of value: BSV, coins of other chains, items, Bitcoin Native Tokens (BNT) and Issuer-Permissioned Tokens (IPT). Each kind has its own storage, its own proof of authenticity, and its own way for applications to see and move it.

This document calls those kinds asset profiles. A profile is the unit of everything an application can be granted. It fixes six things:

  • where the value lives;
  • what proves it;
  • how an application views it;
  • how an application moves it;
  • which actions exist;
  • which spending scope covers it.

Three rules make profiles safe to combine:

  1. Every held asset belongs to exactly one profile, for life.
  2. A grant in one profile never grants anything in another.
  3. Only coin profiles share the payment budget.

The document registers seven profiles (bsv, coin:<chain>, 1sat, bntft, bntnft, iptft, iptnft), marks which token profiles are BNT, and defines one read method, listAssetProfiles, so applications can learn what a wallet holds and accepts before asking.

Motivation

Each asset format so far has specified its own basket, permission scheme and actions in isolation. Each wallet then decides for itself how they interact:

  • Does Auto-pay cover a token transfer?
  • Does permission to view items show tokens?
  • Is a Litecoin balance a collectable?

Different answers in different wallets are a security problem, not a style choice. An application granted a payment budget must not be able to spend an item out of it.

Applications face the opposite gap. They cannot tell whether a wallet holds Litecoin or Issuer-Permissioned Tokens without calling methods and handling failures.

Relationship to other documents

Profile Specified by
bsv BRC-100, with budgets from BRC-73
coin:<chain> Draft BRC-213 (native UTXO-chain coins, #337)
1sat BRC-147 storage, BRC-150 authenticity, BRC-165 permissions
bntft Draft BRC-255 (#335), with the BNT tests of draft BRC-251 (#320)
bntnft Draft BRC-255 (#335)
iptft, iptnft Draft BRC-253 (#333)

A peer paying an identity, not an application, learns which coin profiles that identity receives from its signed receiving record (BRC-213 §7.2), whose coin:<chain> entries are the profile ids here.

Market listings and direct offers for the asset profiles are draft BRC-254 (#334). Draft BRC-255 (#335) is the compact BNT format: its tokens file in bntft and its items in bntnft. A compact countersigned asset is BRC-253 §15, under its own marker ipt, and files in iptft or iptnft. Readers tell formats apart by their tags, never by profile.

A Bitcoin Native Token (BNT) passes the six tests of draft BRC-251: in the script, valid from transactions alone, moved by its holder alone, rules fixed at deploy, settled by Bitcoin, and peer to peer. bntft and bntnft hold only BNT. iptft and iptnft hold Issuer-Permissioned Tokens (IPT, BRC-253), never BNT.

Terms

  • Profile: a named kind of held value with the fields of §1.
  • Coin profile: a profile whose value is a plain payment unit (bsv, coin:<chain>).
  • Asset profile: any other profile. Its value has identity, is issued by someone, and is proven back to an origin or deploy.
  • Grant: anything a user gives an application that outlives one call: a view permission, a spend label scope, an automatic-payment budget, a BRC-73 spendingAuthorization.

Specification

1. Profile fields

Field Meaning
id Lowercase identifier. Coin profiles of other chains are coin:<chain id>
Holds What one unit is
Custody Where the value lives and whose key moves it
Authenticity What proves a held unit is what it claims
View How an application lists it, and which grant that needs
Move How an application spends it, and which consent that needs
Actions The application methods that act on it, each its own consent
Spending scope payment (shares the per-application payment budget) or per-action (always its own prompt, never in a budget)
BNT Token profiles only: whether every unit is a Bitcoin Native Token (BRC-251)

2. Registered profiles

id Holds Custody Authenticity View Move Spending scope
bsv Satoshis Wallet keys on BSV BRC-67 SPV getBalance, listOutputs on the application's own baskets createAction payment
coin:ltc Litoshi The wallet's coin key on Litecoin (BRC-213 §2) Burial 6 deep on the wallet's own Litecoin header chain (BRC-213 §4) listCoins({ chain: "ltc" }) sendCoins({ chain: "ltc", … }) payment
coin:bch Satoshi The wallet's coin key on Bitcoin Cash Burial 6 deep on its own Bitcoin Cash header chain listCoins({ chain: "bch" }) sendCoins({ chain: "bch", … }) payment
coin:btc Satoshi The wallet's coin key on Bitcoin Burial 3 deep on its own Bitcoin header chain listCoins({ chain: "btc" }) sendCoins({ chain: "btc", … }) payment
coin:doge Koinu The wallet's coin key on Dogecoin Burial 20 deep on its own Dogecoin header chain listCoins({ chain: "doge" }) sendCoins({ chain: "doge", … }) payment
1sat One-sat ordinal items Owner key on BSV BRC-150 proof to the origin Basket p 1sat <scope> (BRC-165) createAction labeled p 1sat input id <key> per-action
bntft BNT fungible tokens Owner key on BSV BRC-255 §7 to the deploy Basket p bntft <scope> Wallet methods only (BRC-255) per-action
bntnft BNT items (supply 1) Owner key on BSV BRC-255 §7 to the deploy Basket p bntnft <scope>, with BRC-165 scopes Wallet methods only (BRC-255) per-action
iptft Countersigned fungible tokens (IPT, not BNT) Owner key, plus the issuer's key set for each transfer The issuer's countersignature in each transfer Basket p iptft <scope> Wallet methods only (BRC-253) per-action
iptnft Countersigned items (supply 1, IPT, not BNT) As iptft As iptft Basket p iptnft <scope> Wallet methods only (BRC-253) per-action

coin:<chain> registers one profile per BRC-213 binding. A wallet lists only the chains it supports.

3. Rules

  1. One profile, for life. A held asset belongs to exactly one profile from the moment the wallet records it. Nothing moves an asset between profiles. Even a countersigned asset whose issuer released it stays iptft or iptnft.
  2. Grants never cross. A grant in one profile gives nothing in another. Permission to view 1sat items shows no tokens, a bntft view never shows an item, and a payment budget never covers an asset profile.
  3. One payment budget. All coin profiles share one budget per application: any automatic-payment budget the wallet keeps, and any BRC-73 spendingAuthorization grant. A payment in coin:<chain> counts at its BSV-equivalent fiat value (BRC-213 §10). An application cannot route around its budget by paying on another chain.
  4. Asset actions stay per-action. A transfer, mint, issue, listing, purchase or offer that moves an asset profile is never approved automatically, even when it also pays satoshis. The satoshis it pays do not open a payment-budget path for the asset.
  5. Separate views. A wallet shows each profile in its own place, and never counts an IPT in a BNT balance. Coins are balances, never collectables or tokens. Items are never mixed into token lists. A retired or migrated record of an earlier format is not shown as value in any profile.
  6. Refuse by profile. A request that names one profile but would move value of another is refused, not partly executed.
  7. No profile, no value. A wallet MUST NOT count, price or offer value it cannot place in a profile it supports.

4. listAssetProfiles()

This method requires a connected application and shows no further prompt. It tells the application which profiles the wallet supports and how to reach each. It reveals no balances.

{
  "profiles": [
    { "id": "bsv", "scope": "payment", "spec": ["BRC-100"] },
    { "id": "coin:ltc", "scope": "payment", "spec": ["BRC-213"],
      "chain": "ltc", "decimals": 8, "minConfirmations": 6,
      "methods": ["getCoinAddress", "listCoins", "sendCoins"] },
    { "id": "1sat", "scope": "per-action", "spec": ["BRC-147", "BRC-150", "BRC-165"],
      "basket": "p 1sat", "spendLabel": "p 1sat input id" },
    { "id": "bntft", "scope": "per-action", "spec": ["BRC-251", "BRC-255"], "basket": "p bntft", "bnt": true },
    { "id": "bntnft", "scope": "per-action", "spec": ["BRC-255"], "basket": "p bntnft", "bnt": true },
    { "id": "iptft", "scope": "per-action", "spec": ["BRC-253"], "basket": "p iptft", "bnt": false },
    { "id": "iptnft", "scope": "per-action", "spec": ["BRC-253"], "basket": "p iptnft", "bnt": false }
  ]
}
  • spec lists the documents the wallet implements for that profile, so an application can tell a draft-level implementation apart.
  • basket is the prefix of the view basket, and spendLabel the prefix of the spend label, where they exist.
  • Coin profiles carry the BRC-213 binding facts an application needs to show amounts and waiting times.
  • bnt is present on token profiles only. An application MUST NOT call an asset a Bitcoin Native Token unless its profile has bnt: true.

A wallet MUST list only profiles whose full rule set it enforces. An application MUST treat a missing profile as unsupported, and MUST NOT probe for it with spending calls.

5. Registering a profile

A new profile is registered by a document that fixes every field of §1 and states how it satisfies §3. A profile whose units can pay for anything SHOULD be a coin profile and join the payment budget. A profile whose units have identity MUST be per-action.

Security considerations

  • Budget escape. Without rule 3, an application limited to $10 a day in BSV could pay unlimited Litecoin. Without rule 4, a budget sized for small payments could move a valuable item that happens to cost one satoshi to send.
  • Confused deputy. Rule 6 stops a request built for one profile from reaching inputs of another, such as a createAction spend label that selects an output filed elsewhere.
  • Fingerprinting. listAssetProfiles reveals which profiles a wallet supports, not what it holds. A wallet MAY answer it only after connection, as specified, to avoid exposing even that to unconnected sites.

Rationale

  • The profile is the unit of consent. Users reason about "my Litecoin" or "my items", not baskets or script templates. Grants that follow that line are the ones users can predict.
  • Format is not profile. A profile names a class, not an encoding. What a holder can do with an asset depends on whether it is native or countersigned, not on how its lock is encoded.
  • Native is objective. BNT is decided by six tests a reader checks from the token's rules, not by who issued it, so the bnt flag is a fact about the profile and never a rating.
  • Coins share one budget, assets never do. Coins are interchangeable at a price, so one fiat budget is meaningful. Assets are not interchangeable, so no budget can describe them.

Open questions

  1. Per-profile budgets. Some users may want a smaller budget for one chain. That would narrow rule 3 without breaking it, because the shared budget stays an upper bound.

Implementations

HandCash Desktop and Mobile (@handcash/wallet-ui) implement every profile in §2, with coin bindings coin:ltc, coin:bch, coin:btc and coin:doge. The code is in src/wallet/assetProfiles.ts (listAssetProfiles), and the profile table is in docs/asset-actions-and-permissions.md §0.

References