Files
chip-bcmr/bcmr-v2.schema.ts
2024-01-31 17:32:10 -05:00

1001 lines
41 KiB
TypeScript

/**
* A mapping of identifiers to URIs associated with an entity. URI identifiers
* may be widely-standardized or registry-specific. Values must be valid URIs,
* including a protocol prefix – e.g. `https://` or `ipfs://`., Clients are only
* required to support `https` and `ipfs` URIs, but any scheme may be specified.
*/
export type URIs = {
[identifier: string]: string;
};
/**
* A mapping of extension identifiers to extension definitions. Extensions may
* be widely standardized or application-specific, and extension definitions
* must be either:
*
* - `string`s,
* - key-value mappings of `string`s, or
* - two-dimensional, key-value mappings of `string`s.
*
* This limitation encourages safety and wider compatibility across
* implementations.
*
* To encode an array, it is recommended that each value be assigned to a
* numeric key indicating the item's index (beginning at `0`).
* Numerically-indexed objects are often a more useful and resilient
* data-transfer format than simple arrays because they simplify difference-only
* transmission: only modified indexes need to be transferred, and shifts in
* item order must be explicit, simplifying merges of conflicting updates.
*
* For encoding of more complex data, consider using base64 and/or
* string-encoded JSON.
*/
export type Extensions = {
[extensionIdentifier: string]:
| string
| { [key: string]: string }
| { [keyA: string]: { [keyB: string]: string } };
};
/**
* Tags allow registries to classify and group identities by a variety of
* characteristics. Tags are standardized within a registry and may represent
* either labels applied by that registry or designations by external
* authorities (certification, membership, ownership, etc.) that are tracked by
* that registry.
*
* Examples of possible tags include: `individual`, `organization`, `token`,
* `wallet`, `exchange`, `staking`, `utility-token`, `security-token`,
* `stablecoin`, `wrapped`, `collectable`, `deflationary`, `governance`,
* `decentralized-exchange`, `liquidity-provider`, `sidechain`,
* `sidechain-bridge`, `acme-audited`, `acme-endorsed`, etc.
*
* Tags may be used by clients in search, discovery, and filtering of
* identities, and they can also convey information like accreditation from
* investor protection organizations, public certifications by security or
* financial auditors, and other designations that signal integrity and value
* to users.
*/
export type Tag = {
/**
* The name of this tag for use in interfaces.
*
* In user interfaces with limited space, names should be hidden beyond
* the first newline character or `20` characters until revealed by the user.
*
* E.g.:
* - `Individual`
* - `Token`
* - `Audited by ACME, Inc.`
*/
name: string;
/**
* A string describing this tag for use in user interfaces.
*
* In user interfaces with limited space, descriptions should be hidden beyond
* the first newline character or `140` characters until revealed by the user.
*
* E.g.:
* - `An identity maintained by a single individual.`
* - `An identity representing a type of token.`
* - `An on-chain application that has passed security audits by ACME, Inc.`
*/
description?: string;
/**
* A mapping of identifiers to URIs associated with this tag. URI identifiers
* may be widely-standardized or registry-specific. Values must be valid URIs,
* including a protocol prefix (e.g. `https://` or `ipfs://`). Clients are
* only required to support `https` and `ipfs` URIs, but any scheme may
* be specified.
*
* The following identifiers are recommended for all tags:
* - `icon`
* - `web`
*
* The following optional identifiers are standardized:
* - `blog`
* - `chat`
* - `forum`
* - `icon-intro`
* - `registry`
* - `support`
*
* For details on these standard identifiers, see:
* https://github.com/bitjson/chip-bcmr#uri-identifiers
*
* Custom URI identifiers allow for sharing social networking profiles, p2p
* connection information, and other application-specific URIs. Identifiers
* must be lowercase, alphanumeric strings, with no whitespace or special
* characters other than dashes (as a regular expression: `/^[-a-z0-9]+$/`).
*
* For example, some common identifiers include: `discord`, `docker`,
* `facebook`, `git`, `github`, `gitter`, `instagram`, `linkedin`, `matrix`,
* `npm`, `reddit`, `slack`, `substack`, `telegram`, `twitter`, `wechat`,
* `youtube`.
*/
uris?: URIs;
/**
* A mapping of `Tag` extension identifiers to extension definitions.
* {@link Extensions} may be widely standardized or application-specific.
*/
extensions?: Extensions;
};
/**
* A definition for one type of NFT within a token category.
*/
export type NftType = {
/**
* The name of this NFT type for use in interfaces. Names longer than `20`
* characters may be elided in some interfaces.
*
* E.g. `Market Order Buys`, `Limit Order Sales`, `Pledge Receipts`,
* `ACME Stadium Tickets`, `Sealed Votes`, etc.
*/
name: string;
/**
* A string describing this NFT type for use in user interfaces.
*
* In user interfaces with limited space, names should be hidden beyond the
* first newline character or `140` characters until revealed by the user.
*
* E.g.:
* - "Receipts issued by the exchange to record details about purchases. After
* settlement, these receipts are redeemed for the purchased tokens.";
* - "Receipts issued by the crowdfunding campaign to document the value of
* funds pledged. If the user decides to cancel their pledge before the
* campaign completes, these receipts can be redeemed for a full refund.";
* - "Tickets issued for events at ACME Stadium.";
* - Sealed ballots certified by ACME decentralized organization during the
* voting period. After the voting period ends, these ballots must be revealed
* to reclaim the tokens used for voting."
*/
description?: string;
/**
* A list of identifiers for fields contained in NFTs of this type. On
* successful parsing evaluations, the bottom item on the altstack indicates
* the matched NFT type, and the remaining altstack items represent NFT field
* contents in the order listed (where `fields[0]` is the second-to-bottom
* item, and the final item in `fields` is the top of the altstack).
*
* Fields should be ordered by recommended importance from most important to
* least important; in user interfaces, clients should display fields at lower
* indexes more prominently than those at higher indexes, e.g. if some fields
* cannot be displayed in minimized interfaces, higher-importance fields can
* still be represented. (Note, this ordering is controlled by the bytecode
* specified in `token.nft.parse.bytecode`.)
*
* If this is a sequential NFT, (the category's `parse.bytecode` is
* undefined), `fields` should be omitted or set to `undefined`.
*/
fields?: string[];
/**
* A mapping of identifiers to URIs associated with this NFT type. URI
* identifiers may be widely-standardized or registry-specific. Values must be
* valid URIs, including a protocol prefix (e.g. `https://` or `ipfs://`).
* Clients are only required to support `https` and `ipfs` URIs, but any
* scheme may be specified.
*/
uris?: URIs;
/**
* A mapping of NFT type extension identifiers to extension definitions.
* {@link Extensions} may be widely standardized or application-specific.
*/
extensions?: Extensions;
};
/**
* A definition specifying a field that can be encoded in non-fungible tokens of
* a token category.
*/
export type NftCategoryField = {
[identifier: string]: {
/**
* The name of this field for use in interfaces. Names longer than `20`
* characters may be elided in some interfaces.
*
* E.g.:
* - `BCH Pledged`
* - `Tokens Sold`
* - `Settlement Locktime`
* - `Seat Number`,
* - `IPFS Content Identifier`
* - `HTTPS URL`
*/
name?: string;
/**
* A string describing how this identity uses NFTs (for use in user
* interfaces). Descriptions longer than `160` characters may be elided in
* some interfaces.
*
* E.g.:
* - `The BCH value pledged at the time this receipt was issued.`
* - `The number of tokens sold in this order.`
* - `The seat number associated with this ticket.`
*/
description?: string;
/**
* The expected encoding of this field when read from the parsing altstack
* (see {@link ParsableNftCollection}). All encoding definitions must have a
* `type`, and some encoding definitions allow for additional hinting about
* display strategies in clients.
*
* Encoding types may be set to `binary`, `boolean`, `hex`, `number`,
* or `utf8`:
*
* - `binary` types should be displayed as binary literals (e.g. `0b0101`)
* - `boolean` types should be displayed as `true` if exactly `0x01` or
* `false` if exactly `0x00`. If a boolean value does not match one of these
* values, clients should represent the NFT as unable to be parsed
* (e.g. simply display the full `commitment`).
* - `hex` types should be displayed as hex literals (e.g.`0xabcd`).
* - `https-url` types are percent encoded with the `https://` prefix
* omitted; they may be displayed as URIs or as activatable links.
* - `ipfs-cid` types are binary-encoded IPFS Content Identifiers; they may
* be displayed as URIs or as activatable links.
* - `locktime` types are `OP_TXLOCKTIME` results: integers from `0` to
* `4294967295` (inclusive) where values less than `500000000` are
* understood to be a block height (the current block number in the chain,
* beginning from block `0`), and values greater than or equal to
* `500000000` are understood to be a Median Time Past (BIP113) UNIX
* timestamp. (Note, sequence age is not currently supported.)
* - `number` types should be displayed according the their configured
* `decimals` and `unit` values.
* - `utf8` types should be displayed as utf8 strings.
*/
encoding:
| {
type:
| 'binary'
| 'boolean'
| 'hex'
| 'https-url'
| 'ipfs-cid'
| 'utf8'
| `locktime`;
}
| {
type: 'number';
/**
* The `aggregate` property indicates that aggregating this field from
* multiple NFTs is desirable in user interfaces. For example, for a
* field named `BCH Pledged` where `aggregate` is `add`, the client
* can display a `Total BCH Pledged` in any user interface listing
* more than one NFT.
*
* If specified, clients should aggregate the field from all NFTs, of
* all NFT types within the category, within a particular view (e.g.
* NFTs held by a single wallet, NFTs existing in a single
* transaction's outputs, etc.) using the specified operation.
*
* Note, while aggregation could be performed using any commutative
* operation – multiplication, bitwise AND, bitwise OR, bitwise XOR,
* etc. – only `add` is currently supported.
*/
aggregate?: 'add';
/**
* An integer between `0` and `18` (inclusive) indicating the
* divisibility of the primary unit of this token field.
*
* This is the number of digits that can appear after the decimal
* separator in amounts. For a field with a `decimals` of `2`, a value
* of `123456` should be displayed as `1234.56`.
*
* If omitted, defaults to `0`.
*/
decimals?: number;
/**
* The unit in which this field is denominated, taking the `decimals`
* value into account. If representing fungible token amount, this
* will often be the symbol of the represented token category.
*
* E.g. `BCH`, `sats`, `AcmeUSD`, etc.
*
* If not provided, clients should not represent this field as having
* a unit beyond the field's `name`.
*/
unit?: string;
};
/**
* A mapping of identifiers to URIs associated with this NFT field. URI
* identifiers may be widely-standardized or registry-specific. Values must
* be valid URIs, including a protocol prefix (e.g. `https://` or
* `ipfs://`). Clients are only required to support `https` and `ipfs` URIs,
* but any scheme may be specified.
*/
uris?: URIs;
/**
* A mapping of NFT field extension identifiers to extension definitions.
* {@link Extensions} may be widely standardized or application-specific.
*/
extensions?: Extensions;
};
};
/**
* Interpretation information for a collection of sequential NFTs, a collection
* in which each NFT includes only a sequential identifier within its on-chain
* commitment. Note that {@link SequentialNftCollection}s differ from
* {@link ParsableNftCollection}s in that sequential collections lack a
* parsing `bytecode` with which to inspect each NFT commitment: the type of
* each NFT is indexed by the full contents its commitment (interpreted as a
* positive VM integer in user interfaces).
*/
export type SequentialNftCollection = {
/**
* A mapping of each NFT commitment (typically, a positive integer encoded as
* a VM number) to metadata for that NFT type in this category.
*/
types: {
/**
* Interpretation information for each type of NFT within the token
* category, indexed by commitment hex. For sequential NFTs, the on-chain
* commitment of each NFT is interpreted as a VM number to reference its
* particular NFT type in user interfaces. Issuing a sequential NFT with a
* negative or invalid VM number is discouraged, but clients may render the
* commitment of such NFTs in hex-encoded form, prefixed with `X`.
*/
[commitmentHex: string]: NftType;
};
};
/**
* Interpretation information for a collection of parsable NFTs, a collection
* in which each NFT may include additional metadata fields beyond a sequential
* identifier within its on-chain commitment. Note that
* {@link ParsableNftCollection}s differ from {@link SequentialNftCollection}s
* in that parsable collections require a parsing `bytecode` with which to
* inspect each NFT commitment: the type of each NFT is indexed by the
* hex-encoded contents the bottom item on the altstack following the evaluation
* of the parsing bytecode.
*/
export type ParsableNftCollection = {
/**
* A segment of hex-encoded Bitcoin Cash VM bytecode that parses UTXOs
* holding NFTs of this category, identifies the NFT's type within the
* category, and returns a list of the NFT's field values via the
* altstack. If undefined, this NFT Category includes only sequential NFTs,
* with only an identifier and no NFT fields encoded in each NFT's
* on-chain commitment.
*
* The parse `bytecode` is evaluated by instantiating and partially
* verifying a standardized NFT parsing transaction:
* - version: `2`
* - inputs:
* - 0: Spends the UTXO containing the NFT with an empty
* unlocking bytecode and sequence number of `0`.
* - 1: Spends index `0` of the empty hash outpoint, with locking
* bytecode set to `parse.bytecode`, unlocking bytecode `OP_1`
* (`0x51`) and sequence number `0`.
* - outputs:
* - 0: A locking bytecode of OP_RETURN (`0x6a`) and value of `0`.
* - locktime: `0`
*
* After input 1 of this NFT parsing transaction is evaluated, if the
* resulting stack is not valid (a single "truthy" element remaining on
* the stack) – or if the altstack is empty – parsing has failed and
* clients should represent the NFT as unable to be parsed (e.g. simply
* display the full `commitment` as a hex-encoded value in the user
* interface).
*
* On successful parsing evaluations, the bottom item on the altstack
* indicates the type of the NFT according to the matching definition in
* `types`. If no match is found, clients should represent the NFT as
* unable to be parsed.
*
* For example: `00d2517f7c6b` (OP_0 OP_UTXOTOKENCOMMITMENT OP_1 OP_SPLIT
* OP_SWAP OP_TOALTSTACK OP_TOALTSTACK) splits the commitment after 1 byte,
* pushing the first byte to the altstack as an NFT type identifier and the
* remaining segment of the commitment as the first NFT field value.
*
* If undefined (in a {@link SequentialNftCollection}), this field could be
* considered to have a default value of `00d26b` (OP_0 OP_UTXOTOKENCOMMITMENT
* OP_TOALTSTACK), which takes the full contents of the commitment as a fixed
* type index. As such, each index of the NFT category's `types` maps a
* precise commitment value to the metadata for NFTs with that particular
* commitment. E.g. an NFT with an empty commitment (VM number 0) maps to
* `types['']`, a commitment of `01` (hex) maps to `types['01']`, etc. This
* pattern is used for collections of sequential NFTs.
*/
bytecode: string;
/**
* A mapping of hex-encoded values to definitions of possible NFT types
* in this category.
*/
types: {
/**
* A definitions for each type of NFT within the token category. Parsable
* NFT types are indexed by the hex-encoded value of the bottom altstack
* item following evaluation of `NftCategory.parse.bytecode`. The remaining
* altstack items are mapped to NFT fields according to the `fields`
* property of the matching NFT type.
*/
[bottomAltstackHex: string]: NftType;
};
};
/**
* A definition specifying the non-fungible token information for a
* token category.
*/
export type NftCategory = {
/**
* A string describing how this identity uses NFTs (for use in user
* interfaces). Descriptions longer than `160` characters may be elided in
* some interfaces.
*
* E.g.:
* - "ACME DEX NFT order receipts are issued when you place orders on the
* decentralized exchange. After orders are processed, order receipts can
* be redeemed for purchased tokens or sales proceeds.";
* - "ACME Game collectable NFTs unlock unique playable content, user
* avatars, and item skins in ACME Game Online."; etc.
*/
description?: string;
/**
* A mapping of field identifier to field definitions for the data fields
* that can appear in NFT commitments of this category.
*
* Categories including only sequential NFTs (where `parse.bytecode` is
* undefined) should omit `fields` (or set to `undefined`).
*/
fields?: NftCategoryField;
/**
* Parsing and interpretation information for all NFTs of this category;
* this enables generalized wallets to parse and display detailed
* information about all NFTs held by the wallet, e.g. `BCH Pledged`,
* `Order Price`, `Seat Number`, `Asset Number`,
* `IPFS Content Identifier`, `HTTPS URL`, etc.
*
* Parsing instructions are provided in the `bytecode` property, and the
* results are interpreted using the `types` property.
*/
parse: SequentialNftCollection | ParsableNftCollection;
};
/**
* A definition specifying information about an identity's token category.
*/
export type TokenCategory = {
/**
* The current token category used by this identity. Often, this will be
* equal to the identity's authbase, but some token identities must migrate
* to new categories for technical reasons.
*/
category: string;
/**
* An abbreviation used to uniquely identity this token category.
*
* Symbols must be comprised only of capital letters, numbers, and dashes
* (`-`). This can be validated with the regular expression:
* `/^[-A-Z0-9]+$/`.
*/
symbol: string;
/**
* An integer between `0` and `18` (inclusive) indicating the divisibility
* of the primary unit of this token category.
*
* This is the number of digits that can appear after the decimal separator
* in fungible token amounts. For a token category with a `symbol` of
* `SYMBOL` and a `decimals` of `2`, a fungible token amount of `12345`
* should be displayed as `123.45 SYMBOL`.
*
* If omitted, defaults to `0`.
*/
decimals?: number;
/**
* Display information for non-fungible tokens (NFTs) of this identity.
* Omitted for token categories without NFTs.
*/
nfts?: NftCategory;
};
/**
* A snapshot of the metadata for a particular identity at a specific time.
*/
export type IdentitySnapshot = {
/**
* The name of this identity for use in interfaces.
*
* In user interfaces with limited space, names should be hidden beyond
* the first newline character or `20` characters until revealed by the user.
*
* E.g. `ACME Class A Shares`, `ACME Registry`, `Satoshi Nakamoto`, etc.
*/
name: string;
/**
* A string describing this identity for use in user interfaces.
*
* In user interfaces with limited space, descriptions should be hidden beyond
* the first newline character or `140` characters until revealed by the user.
*
* E.g.:
* - `The common stock issued by ACME, Inc.`
* - `A metadata registry maintained by Company Name, the embedded registry for Wallet Name.`
* - `Software developer and lead maintainer of Wallet Name.`
*/
description?: string;
/**
* An array of `Tag` identifiers marking the `Tag`s associated with this
* identity. All specified tag identifiers must be defined in the registry's
* `tags` mapping.
*/
tags?: string[];
/**
* The timestamp at which this identity snapshot is fully in effect. This
* value should only be provided if the snapshot takes effect over a period
* of time (e.g. an in-circulation token identity is gradually migrating to
* a new category). In these cases, clients should gradually migrate to
* using the new information beginning after the identity snapshot's timestamp
* and the `migrated` time.
*
* This timestamp must be provided in simplified extended ISO 8601 format, a
* 24-character string of format `YYYY-MM-DDTHH:mm:ss.sssZ` where timezone is
* zero UTC (denoted by `Z`). Note, this is the format returned by ECMAScript
* `Date.toISOString()`.
*/
migrated?: string;
/**
* If this identity is a type of token, a data structure indicating how tokens
* should be understood and displayed in user interfaces. Omitted for
* non-token identities.
*/
token?: TokenCategory;
/**
* The status of this identity, must be `active`, `inactive`, or `burned`. If
* omitted, defaults to `active`.
* - Identities with an `active` status should be actively tracked by clients.
* - Identities with an `inactive` status may be considered for archival by
* clients and may be removed in future registry versions.
* - Identities with a `burned` status have been destroyed by setting the
* latest identity output to a data-carrier output (`OP_RETURN`), permanently
* terminating the authchain. Clients should archive burned identities and –
* if the burned identity represented a token type – consider burning any
* remaining tokens of that category to reclaim funds from those outputs.
*/
status?: 'active' | 'burned' | 'inactive';
/**
* The split ID of this identity's chain of record.
*
* If undefined, defaults to {@link Registry.defaultChain}.
*/
splitId?: string;
/**
* A mapping of identifiers to URIs associated with this identity. URI
* identifiers may be widely-standardized or registry-specific. Values must be
* valid URIs, including a protocol prefix (e.g. `https://` or `ipfs://`).
* Clients are only required to support `https` and `ipfs` URIs, but any
* scheme may be specified.
*
* The following identifiers are recommended for all identities:
* - `icon`
* - `web`
*
* The following optional identifiers are standardized:
* - `blog`
* - `chat`
* - `forum`
* - `icon-intro`
* - `image`
* - `migrate`
* - `registry`
* - `support`
*
* For details on these standard identifiers, see:
* https://github.com/bitjson/chip-bcmr#uri-identifiers
*
* Custom URI identifiers allow for sharing social networking profiles, p2p
* connection information, and other application-specific URIs. Identifiers
* must be lowercase, alphanumeric strings, with no whitespace or special
* characters other than dashes (as a regular expression: `/^[-a-z0-9]+$/`).
*
* For example, some common identifiers include: `discord`, `docker`,
* `facebook`, `git`, `github`, `gitter`, `instagram`, `linkedin`, `matrix`,
* `npm`, `reddit`, `slack`, `substack`, `telegram`, `twitter`, `wechat`,
* `youtube`.
*/
uris?: URIs;
/**
* A mapping of `IdentitySnapshot` extension identifiers to extension
* definitions. {@link Extensions} may be widely standardized or
* application-specific.
*
* Standardized extensions for `IdentitySnapshot`s include the `authchain`
* extension. See
* https://github.com/bitjson/chip-bcmr#authchain-extension for details.
*/
extensions?: Extensions;
};
/**
* A snapshot of the metadata for a particular chain/network at a specific
* time. This allows for registries to provide similar metadata for each chain's
* native currency unit (name, description, symbol, icon, etc.) as can be
* provided for other registered tokens.
*/
export type ChainSnapshot = Omit<IdentitySnapshot, 'migrated' | 'token'> & {
/**
* A data structure indicating how the chain's native currency units should be
* displayed in user interfaces.
*/
token: {
/**
* An abbreviation used to uniquely identity this native currency unit.
*
* Symbols must be comprised only of capital letters, numbers, and dashes
* (`-`). This can be validated with the regular expression:
* `/^[-A-Z0-9]+$/`.
*/
symbol: string;
/**
* An integer between `0` and `18` (inclusive) indicating the divisibility
* of the primary unit of this native currency.
*
* This is the number of digits that can appear after the decimal separator
* in currency amounts. For a currency with a `symbol` of `SYMBOL` and a
* `decimals` of `2`, an amount of `12345` should be displayed as
* `123.45 SYMBOL`.
*
* If omitted, defaults to `0`.
*/
decimals?: number;
};
};
/**
* A field keyed by timestamps to document the evolution of the field. Each
* timestamp must be provided in simplified extended ISO 8601 format, a
* 24-character string of format `YYYY-MM-DDTHH:mm:ss.sssZ` where timezone is
* zero UTC (denoted by `Z`). Note, this is the format returned by ECMAScript
* `Date.toISOString()`.
*
* For example, to insert a new value:
* ```ts
* const result = { ...previousValue, [(new Date()).toISOString()]: newValue };
* ```
*/
export type RegistryTimestampKeyedValues<T> = {
[timestamp: string]: T;
};
/**
* A block height-keyed map of {@link ChainSnapshot}s documenting the evolution
* of a particular chain/network's identity. Like {@link IdentityHistory}, this
* structure allows wallets and other user interfaces to offer better
* experiences when a chain identity is rebranded, redenominated, or other
* important metadata is modified in a coordinated update.
*/
export type ChainHistory = RegistryTimestampKeyedValues<ChainSnapshot>;
/**
* A timestamp-keyed map of {@link IdentitySnapshot}s documenting
* the evolution of a particular identity. The current identity information is
* the snapshot associated with the latest timestamp reached. If no timestamp
* has yet been reached, the snapshot of the oldest timestamp is considered
* current. Future-dated timestamps indicate planned migrations.
*
* This strategy allows wallets and other user interfaces to offer better
* experiences when an identity is rebranded, a token redenominated, or other
* important metadata is modified in a coordinated update. For example, a wallet
* may warn token holders of a forthcoming rebranding of fungible tokens they
* hold; after the change, the wallet may continue to offer prominent interface
* hints that the rebranded token identity was recently updated.
*
* Timestamps may be order by time via lexicographical sort. For determinism, it
* is recommended that implementations sort from newest to oldest in exported
* registry JSON files.
*
* If the current snapshot's {@link IdentitySnapshot.migrated} isn't specified,
* the snapshot's index is a precise time at which the snapshot takes effect and
* clients should begin using the new information. If `migrated` is specified,
* the snapshot's index is the timestamp at which the transition is considered
* to begin, see {@link IdentitySnapshot.migrated} for details.
*
* Each timestamp must be provided in simplified extended ISO 8601 format, a
* 24-character string of format `YYYY-MM-DDTHH:mm:ss.sssZ` where timezone is
* zero UTC (denoted by `Z`). Note, this is the format returned by ECMAScript
* `Date.toISOString()`.
*
* In the case that an identity change occurs due to on-chain activity (e.g. an
* on-chain migration that is set to complete at a particular locktime value),
* registry-recorded timestamps reflect the real-world time at which the
* maintainer of the registry believes the on-chain activity to have actually
* occurred. Likewise, future-dated timestamps indicate a precise real-world
* time at which a snapshot is estimated to take effect, rather than the Median
* Time Past (BIP113) UNIX timestamp or another on-chain measurement of time.
*/
export type IdentityHistory = RegistryTimestampKeyedValues<IdentitySnapshot>;
/**
* An identity representing a metadata registry that is not published on-chain
* and therefore has no authbase or trackable authchain.
*/
export type OffChainRegistryIdentity = Pick<
IdentitySnapshot,
'name' | 'description' | 'uris' | 'tags' | 'extensions'
>;
/**
* A Bitcoin Cash Metadata Registry is an authenticated JSON file containing
* metadata about tokens, identities, contract applications, and other on-chain
* artifacts. BCMRs conform to the Bitcoin Cash Metadata Registry JSON Schema,
* and they can be published and maintained by any entity or individual.
*/
export type Registry = {
/**
* The schema used by this registry. Many JSON editors can automatically
* provide inline documentation and autocomplete support using the `$schema`
* property, so it is recommended that registries include it. E.g.:
* `https://cashtokens.org/bcmr-v2.schema.json`
*/
$schema?: string;
/**
* The version of this registry. Versioning adheres to Semantic Versioning
* (https://semver.org/).
*/
version: {
/**
* The major version is incremented when an identity is removed.
*/
major: number;
/**
* The minor version is incremented when an identity is added or a new
* identity snapshot is added.
*/
minor: number;
/**
* The patch version is incremented when an existing identity or identity
* snapshot is modified (e.g. to correct an error or add a missing piece of
* information) or when other registry properties (e.g. registry `name`,
* `description`, `uris`, etc.) are modified.
*
* Generally, substantive changes to an existing identity should be made
* using a new identity snapshot in a minor version upgrade – this allows
* clients to provide a better user experience by noting the change in
* relevant user interfaces.
*
* For example, patch upgrades might include spelling corrections in an
* existing snapshot or the addition of an `icon` containing a
* higher-resolution version of an existing `icon` image. On the other hand,
* a rebranding in which the icon is substantially changed may warrant a new
* identity snapshot to be added in a minor version upgrade.
*/
patch: number;
};
/**
* The timestamp of the latest revision made to this registry version. The
* timestamp must be provided in simplified extended ISO 8601 format, a
* 24-character string of format `YYYY-MM-DDTHH:mm:ss.sssZ` where timezone is
* zero UTC (denoted by `Z`). Note, this is the format returned by ECMAScript
* `Date.toISOString()`.
*/
latestRevision: string;
/**
* The identity information of this particular registry, provided as either an
* authbase (recommended) or an `IdentitySnapshot`.
*
* An authbase is a 32-byte, hex-encoded transaction hash (A.K.A. TXID) for
* which the zeroth-descendant transaction chain (ZDTC) authenticates and
* publishes all registry updates. If an authbase is provided, the registry's
* identity information can be found in `identities[authbase]`, and clients
* should immediately attempt to verify the registry's identity on-chain.
* (See https://github.com/bitjson/chip-bcmr#chain-resolved-registries)
*
* If an `IdentitySnapshot` is provided directly, this registry does not
* support on-chain resolution/authentication, and the contained
* `IdentitySnapshot` can only be authenticated via DNS/HTTPS.
*/
registryIdentity: OffChainRegistryIdentity | string;
/**
* A mapping of authbases to the `IdentityHistory` for that identity.
*
* An authbase is a 32-byte, hex-encoded transaction hash (A.K.A. TXID) for
* which the zeroth-descendant transaction chain (ZDTC) authenticates and
* publishes an identity's claimed metadata.
*
* Identities may represent metadata registries, specific types of tokens,
* companies, organizations, individuals, or other on-chain entities.
*/
identities?: {
[authbase: string]: IdentityHistory;
};
/**
* A map of registry-specific `Tag`s used by this registry to convey
* information about identities it tracks.
*
* Tags allow registries to group identities into collections of related
* identities, marking characteristics or those identities. Tags are
* standardized within a registry and may represent either labels applied by
* that registry (e.g. `individual`, `organization`, `token`, `wallet`,
* `exchange`, `staking`, `utility-token`, `security-token`, `stablecoin`,
* `wrapped`, `collectable`, `deflationary`, `governance`,
* `decentralized-exchange`, `liquidity-provider`, `sidechain`,
* `sidechain-bridge`, etc.) or designations by external authorities
* (certification, membership, ownership, etc.) that are tracked by
* that registry.
*
* Tags may be used by clients in search, discover, and filtering of
* identities, and they can also convey information like accreditation from
* investor protection organizations, public certifications by security or
* financial auditors, and other designations that signal legitimacy and value
* to users.
*/
tags?: {
[identifier: string]: Tag;
};
/**
* The split ID of the chain/network considered the "default" chain for this
* registry. Identities that do not specify a {@link IdentitySnapshot.splitId}
* are assumed to be set to this split ID. For a description of split IDs,
* see {@link Registry.chains}.
*
* If not provided, the `defaultChain` is
* `0000000000000000029e471c41818d24b8b74c911071c4ef0b4a0509f9b5a8ce`, the BCH
* side of the BCH/XEC split (mainnet). Common values include:
* - `00000000ae25e85d9e22cd6c8d72c2f5d4b0222289d801b7f633aeae3f8c6367`
* (testnet4)
* - `00000000040ba9641ba98a37b2e5ceead38e4e2930ac8f145c8094f94c708727`
* (chipnet)
*/
defaultChain?: string;
/**
* A map of split IDs tracked by this registry to the {@link ChainHistory} for
* that chain/network.
*
* The split ID of a chain is the block header hash (A.K.A. block ID) of the
* first unique block after the most recent tracked split – a split after
* which both resulting chains are considered notable or tracked by the
* registry. (For chains with no such splits, this is the ID of the
* genesis block.)
*
* Note, split ID is inherently a "relative" identifier. After a tracked
* split, both resulting chains will have a new split ID. However, if a wallet
* has not yet heard about a particular split, that wallet will continue to
* reference one of the resulting chains by its previous split ID, and the
* split-unaware wallet may create transactions that are valid on both chains
* (losing claimable value if the receivers of their transactions don't
* acknowledge transfers on both chains). When a registry trusted by the
* wallet notes the split in it's `chains` map, the wallet can represent the
* split in the user interface using the the latest {@link ChainSnapshot} for
* each chain and splitting coins prior to spending (by introducing post-split
* coins in each transaction).
*
* This map may exclude the following well-known split IDs (all clients
* supporting any of these chains should build-in {@link ChainHistory} for
* those chains):
*
* - `0000000000000000029e471c41818d24b8b74c911071c4ef0b4a0509f9b5a8ce`:
* A.K.A. mainnet – the BCH side of the BCH/XEC split.
* - `00000000ae25e85d9e22cd6c8d72c2f5d4b0222289d801b7f633aeae3f8c6367`:
* A.K.A testnet4 – the test network on which CHIPs are activated
* simultaneously with mainnet (May 15 at 12 UTC).
* - `00000000040ba9641ba98a37b2e5ceead38e4e2930ac8f145c8094f94c708727`:
* A.K.A. chipnet – the test network on which CHIPs are activated 6 months
* before mainnet (November 15 at 12 UTC).
*
* All other split IDs referenced by this registry should be included in this
* map.
*/
chains?: {
[splitId: string]: ChainHistory;
};
/**
* The license under which this registry is published. This may be specified
* as either a SPDX short identifier (https://spdx.org/licenses/) or by
* including the full text of the license.
*
* Common values include:
* - `CC0-1.0`: https://creativecommons.org/publicdomain/zero/1.0/
* - `MIT`: https://opensource.org/licenses/MIT
*/
license?: string;
/**
* A mapping of Unicode locale identifiers (conforming to those of
* ECMAScript's Intl.Locale object, e.g. `es` for Spanish) to localized
* versions of metadata registry contents.
*
* Localized values for `registryIdentity` objects and all `identities`,
* `tags`, `chains`, and `extensions` may be provided by reproducing the
* {@link Registry} object as a child of the appropriate locale property,
* e.g. `locales.es.registryIdentity.description` provides a Spanish (`es`)
* localization for the registry identity's `description`. Registries should
* not localize property keys, including URI and tag identifiers, to ensure
* that values can be associated across locales.
*
* **Outside of the locales property, metadata registries are considered to
* use the English Unicode locale (identifier: `en`)**. All other locales –
* including regional English locales like `en-US` or `en-GB` – must be
* provided via the locales property.
*
* **It is acceptable for registries to be partially-localized.** For example,
* some locales may exclude identities that appear in the `en` locale (and
* vice versa). Clients with localization support should attempt to use
* metadata from the user's preferred locale, falling back to metadata from
* the closest available locale.
*
* Note, it is not necessary for registries to include any metadata for the
* `en` locale, e.g. registries that omit the `identities`, `tags`, `chains`,
* and/or `extensions` properties from the top-level (`en` locale) may still
* include those properties for any number of other locales using the
* `locales` property.
*
* A localized registry is produced by the following algorithm:
*
* 1. Given the user's preferred locale, locate the registry's closest
* specified locale in the `locales` property. If a precise match is not
* available, fall back recursively to the closest available locale. If no
* matching language is available, default to `en`. E.g. If the user's
* preferred locale is `de-AT`, fall back to `de`, then `en`.
* 2. Beginning from the closest available locale, assemble a list of matching
* locales in reverse order of specificity. E.g. `["en", "de", "de-AT"]`.
* (Note, `en` is a special case; other `en` locales should not be included in
* this list for non-english locales.)
* 3. Create a localized registry by inheriting from each locale beginning
* with the least specific locale:
* 1. From the current locale, assign all `identities`, `tags`, `chains`,
* and `extensions` to the generated locale, overriding the full definition
* at that identifier with the localized definition from the more-specific
* locale. (Note, replacement is object-level; do not attempt to merge two
* definitions for the same identifier.)
* 2. If this client is deeply-validating the registry, verify the
* consistency of recognized, non-localized metadata and emit an error if any
* differences are found (e.g. metadata such as `token.category` and
* `token.symbol` should not vary between locales).
* 3. Repeat using the next-most-specific locale until all locales have
* been applied.
*
* When the `locales` property is specified, clients supporting localization
* should use this localized registry for all metadata.
*/
locales?: {
[localeIdentifier: string]: Pick<
Registry,
'chains' | 'extensions' | 'identities' | 'tags'
>;
};
/**
* A mapping of `Registry` extension identifiers to extension definitions.
* {@link Extensions} may be widely standardized or application-specific.
*/
extensions?: Extensions;
};