Skip to content

Commit 0cbc57e

Browse files
whoabuddyclaude
andcommitted
feat(stacks): add CAIP-19 asset specification
Adds comprehensive CAIP-19 specification for Stacks token assets, supporting SIP-010 fungible tokens and SIP-009 non-fungible tokens. Asset reference format: {address}.{contract}.{token-name} This addresses the feedback from PR ChainAgnostic#68 including: - Clear documentation of all syntax components - Case sensitivity handling (addresses vs contract/token names) - Complete RegEx validation patterns - Semantics section for each token type Examples verified against on-chain data (sBTC, Megapont Ape Club). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fc77c08 commit 0cbc57e

2 files changed

Lines changed: 166 additions & 0 deletions

File tree

stacks/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ the Stacks ecosystem.
1818
- [Stacks developer documentation][]
1919
- [CAIP-2][]
2020
- [CAIP-10][]
21+
- [CAIP-19][]
2122

2223
[SIP-005]: https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md
2324
[Stacks developer documentation]: https://docs.stacks.co/
2425
[CAIP-2]: https://github.com/chainagnostic/caips/blob/master/caips/caip-2.md
2526
[CAIP-10]: https://github.com/chainagnostic/caips/blob/master/caips/caip-10.md
27+
[CAIP-19]: https://github.com/chainagnostic/caips/blob/master/caips/caip-19.md
2628

2729
## Copyright
2830

stacks/caip19.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
---
2+
namespace-identifier: stacks-caip19
3+
title: Stacks Namespace - Assets
4+
author: Friedger Müffke (@friedger), Jason Schrader (@whoabuddy)
5+
discussions-to: https://github.com/ChainAgnostic/namespaces/pull/68
6+
status: Draft
7+
type: Standard
8+
created: 2023-05-21
9+
updated: 2025-01-14
10+
requires: ["CAIP-2", "CAIP-10", "CAIP-19"]
11+
---
12+
13+
# CAIP-19
14+
15+
*For context, see the [CAIP-19][] specification.*
16+
17+
## Rationale
18+
19+
In the Stacks ecosystem, token assets are defined within smart contracts written in [Clarity][], a decidable language with native asset primitives.
20+
A single contract can define multiple fungible tokens (FTs) and non-fungible tokens (NFTs), each identified by a unique name within the contract.
21+
22+
Token assets are uniquely identified by combining the deployer address, contract name, and the token name declared within that contract using `define-fungible-token` or `define-non-fungible-token`.
23+
24+
The Stacks community has established standard interfaces for tokens:
25+
26+
- [SIP-010][]: Fungible Token Standard (analogous to ERC-20)
27+
- [SIP-009][]: Non-Fungible Token Standard (analogous to ERC-721)
28+
29+
## Syntax
30+
31+
After the [CAIP-2][] namespace+chainID, a slash defines an `asset_namespace` and an `asset_reference`.
32+
33+
### Asset Namespaces
34+
35+
| Namespace | Description | Reference Format |
36+
| :--- | :--- | :--- |
37+
| `sip010` | Fungible token ([SIP-010][]) | `{contract-principal}.{token-name}` |
38+
| `sip009` | Non-fungible token ([SIP-009][]) | `{contract-principal}.{token-name}` |
39+
40+
### Asset Reference Components
41+
42+
The asset reference combines the contract principal with the token identifier:
43+
44+
```
45+
{address}.{contract}.{token-name}
46+
```
47+
48+
- **address**: A valid Stacks address in [c32check][] encoding (starts with `SP` for mainnet, `ST` for testnet)
49+
- **contract**: The deployed contract name (1-40 characters, alphanumeric with hyphens and underscores, must start with a letter)
50+
- **token-name**: The identifier used in the contract's `define-fungible-token` or `define-non-fungible-token` declaration
51+
52+
All three components are separated by periods (`.`).
53+
The first period separates the address from the contract name (forming the contract principal), and the second period separates the contract principal from the token name.
54+
55+
Note: In Clarity source code, the fully-qualified asset identifier uses `::` as a separator (e.g., `SP...contract::token`).
56+
For CAIP-19 compatibility, this specification uses `.` as the separator since colons are not permitted in asset references per the [CAIP-19][] specification.
57+
58+
### Token ID (NFTs)
59+
60+
For non-fungible tokens (SIP-009), an optional token ID can be appended after a forward slash (`/`) to identify a specific token instance.
61+
Token IDs are typically unsigned integers starting from 1, as returned by the contract's `get-last-token-id` function.
62+
63+
## RegEx
64+
65+
The RegEx validation strings are as follows:
66+
67+
```
68+
asset_id: asset_type + "/" + token_id (optional for sip009)
69+
asset_type: chain_id + "/" + asset_namespace + ":" + asset_reference
70+
chain_id: namespace + ":" + blockchain_id (as defined in CAIP-2)
71+
72+
asset_namespace: "sip010" | "sip009"
73+
74+
asset_reference: address + "." + contract_name + "." + token_name
75+
address: S[PMNT][A-Z0-9]{38,39}
76+
contract_name: [a-zA-Z][a-zA-Z0-9_-]{0,39}
77+
token_name: [a-zA-Z][a-zA-Z0-9_-]{0,127}
78+
79+
token_id: [1-9][0-9]{0,38}
80+
```
81+
82+
Note: Stacks mainnet addresses start with `SP` or `SM`, while testnet addresses start with `ST` or `SN`.
83+
84+
### Case Sensitivity
85+
86+
Stacks addresses use [c32check][] encoding, which is case-insensitive but canonically represented in uppercase (as specified in [CAIP-10][]).
87+
However, contract names and token names in Clarity are case-sensitive.
88+
89+
Implementations SHOULD:
90+
- Accept addresses in any case but normalize to uppercase for comparison
91+
- Preserve exact case for contract names and token names as deployed on-chain
92+
93+
Note: The total `asset_reference` (address + contract + token name) must not exceed 128 characters per the [CAIP-19][] specification.
94+
95+
## Semantics
96+
97+
### Fungible Tokens (SIP-010)
98+
99+
Fungible tokens following the [SIP-010][] standard implement a common interface for token transfers, balance queries, and metadata.
100+
The standard requires implementation of:
101+
102+
- `transfer`: Move tokens between principals
103+
- `get-balance`: Query token balance for an address
104+
- `get-total-supply`: Query total token supply
105+
- `get-name`, `get-symbol`, `get-decimals`: Token metadata
106+
107+
Each fungible token is uniquely identified by its contract principal and the token name declared via `(define-fungible-token <token-name>)`.
108+
109+
### Non-Fungible Tokens (SIP-009)
110+
111+
Non-fungible tokens following the [SIP-009][] standard represent unique digital assets.
112+
The standard requires implementation of:
113+
114+
- `transfer`: Move NFT ownership
115+
- `get-owner`: Query current owner of a token ID
116+
- `get-last-token-id`: Query the highest minted token ID
117+
- `get-token-uri`: Query metadata URI for a token
118+
119+
Each NFT collection is identified by its contract principal and token name declared via `(define-non-fungible-token <token-name> <token-type>)`.
120+
Individual tokens within a collection are distinguished by their token ID.
121+
122+
## Examples
123+
124+
```
125+
# SIP-010 Fungible Token: sBTC on Mainnet
126+
stacks:1/sip010:SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token.sbtc-token
127+
128+
# SIP-009 NFT Collection: Megapont Ape Club on Mainnet
129+
stacks:1/sip009:SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft.Megapont-Ape-Club
130+
131+
# SIP-009 NFT: Specific Megapont Ape (#4) on Mainnet
132+
stacks:1/sip009:SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft.Megapont-Ape-Club/4
133+
134+
# SIP-010 Fungible Token on Testnet
135+
stacks:2147483648/sip010:ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.my-token.my-ft
136+
137+
# SIP-009 NFT on Testnet
138+
stacks:2147483648/sip009:ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.my-nft.my-nft-token/1
139+
```
140+
141+
## Backwards Compatibility
142+
143+
This specification supersedes the approach proposed in [PR #68][], which used `sip9` and `sip10` namespaces without the token name component.
144+
The updated format provides more precise asset identification by including the token name as declared in the smart contract, which is necessary because a single Stacks contract can define multiple distinct tokens.
145+
146+
## References
147+
148+
- [Clarity Language Reference][Clarity] - Smart contract language documentation
149+
- [SIP-009][] - Non-Fungible Token Standard
150+
- [SIP-010][] - Fungible Token Standard
151+
- [c32check][] - Stacks address encoding
152+
153+
[CAIP-2]: ./caip2.md
154+
[CAIP-10]: ./caip10.md
155+
[CAIP-19]: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-19.md
156+
[Clarity]: https://docs.stacks.co/clarity/overview
157+
[SIP-009]: https://github.com/stacksgov/sips/blob/main/sips/sip-009/sip-009-nft-standard.md
158+
[SIP-010]: https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md
159+
[c32check]: https://github.com/stacks-network/c32check
160+
[PR #68]: https://github.com/ChainAgnostic/namespaces/pull/68
161+
162+
## Copyright
163+
164+
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

0 commit comments

Comments
 (0)