-
Notifications
You must be signed in to change notification settings - Fork 86
Add Stellar namespace CAIP-10 and CAIP-19 specifications #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pelle
wants to merge
6
commits into
ChainAgnostic:main
Choose a base branch
from
pelle:stellar-additions
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
a427693
Added CAIP-10 for stellar
pelle 736951e
Added CAIP-19 for stellar
pelle 78687ea
update with PR
pelle 178bb3c
formatting nits
bumblefudge cb8e23c
codefence nit
bumblefudge c1af9ed
Merge branch 'main' into stellar-additions
bumblefudge File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| --- | ||
| namespace-identifier: stellar-caip10 | ||
| title: Stellar Namespace - Addresses | ||
| author: Pelle Braendgaard (@pelle) | ||
| discussions-to: https://github.com/ChainAgnostic/namespaces/pull/157 | ||
| status: Draft | ||
| type: Standard | ||
| created: 2025-11-6 | ||
| requires: ["CAIP-2", "CAIP-10"] | ||
| --- | ||
|
|
||
| # CAIP-10 | ||
|
|
||
| *For context, see the [CAIP-10][] specification.* | ||
|
|
||
| ## Rationale | ||
|
|
||
| In [CAIP-10][], a string-based general account address scheme is defined. | ||
| Stellar supports multiple address formats to accommodate different use cases: | ||
|
|
||
| ### Classic Addresses (G-addresses) | ||
|
|
||
| Classic Stellar addresses are Ed25519 public keys encoded using Stellar's `strkey` format (base32 encoding as defined in [RFC 4648]). | ||
| A classic Stellar address has the following characteristics: | ||
|
|
||
| * It is exactly 56 characters long | ||
| * It starts with the character `G` | ||
| * It uses base32 encoding with character set `[A-Z][2-7]` | ||
| * It is case-insensitive (though conventionally uppercase) | ||
| * It includes a CRC16 checksum for error detection | ||
| * It may optionally include a memo appended with a hyphen (`-`) separator | ||
|
|
||
| ### Muxed Accounts (M-addresses) | ||
|
|
||
| Muxed accounts (introduced in Protocol 13, [CAP-0027]) encode both a classic address and a 64-bit unsigned integer ID into a single string. | ||
| A muxed account address has the following characteristics: | ||
|
|
||
| * It is exactly 69 characters long | ||
| * It starts with the character `M` | ||
| * It uses base32 encoding (same character set as G-addresses) | ||
| * It is case-insensitive (though conventionally uppercase) | ||
| * It encodes both the underlying G-address and a 64-bit memo ID | ||
| * It includes a checksum for validation | ||
| * Muxed accounts are a client-side abstraction; only the underlying G-address | ||
| exists on the ledger | ||
|
|
||
| ### Federated Addresses | ||
|
|
||
| Federated addresses (defined in SEP-0002) provide human-readable addressing in the format `username*domain.com`. | ||
| These addresses must be resolved to a G-address or M-address via the federation protocol before use in transactions. | ||
| For CAIP-10 purposes, federated addresses should be resolved to their canonical G or M format. | ||
|
|
||
| ### Syntax | ||
|
|
||
| The `account_id` is a case-insensitive string in the form: | ||
|
|
||
| ```sh | ||
| account_id: chain_id + ":" + account_address | ||
| chain_id: See [CAIP-2][] | ||
| account_address: classic_address | muxed_address | ||
| classic_address: G[A-Z2-7]{55} + optional_memo | ||
| optional_memo: ("-" + memo_value)? | ||
| memo_value: memo_text | memo_id | memo_hash | ||
| memo_text: [^\-]{1,28} | ||
| memo_id: [0-9]{1,20} | ||
| memo_hash: [0-9a-fA-F]{64} | ||
| muxed_address: M[A-Z2-7]{68} | ||
| ``` | ||
|
|
||
| ### Semantics | ||
|
|
||
| The `chain_id` is specified by the [CAIP-2][] which describes the blockchain id | ||
| (typically `stellar:pubnet` or `stellar:testnet`). | ||
|
|
||
| The `account_address` represents an account on the Stellar network and can be | ||
| expressed in multiple formats: | ||
|
|
||
| 1. **Classic Address (G-address)**: A base32-encoded Ed25519 public key, | ||
| optionally followed by a memo. Memos are used to identify specific recipients | ||
| or purposes at the destination address and come in several types: | ||
|
|
||
| * **MEMO_TEXT**: A string up to 28 bytes, encoded in ASCII or UTF-8 | ||
| * **MEMO_ID**: A 64-bit unsigned integer (0 to 18446744073709551615) | ||
| * **MEMO_HASH**: A 32-byte hash (64 hex characters) | ||
| * **MEMO_RETURN**: A 32-byte hash intended as the hash of a transaction being refunded | ||
|
|
||
| When included, the memo is separated from the address by a hyphen (`-`). | ||
|
|
||
| 2. **Muxed Address (M-address)**: A compact format that encodes both the classic | ||
| G-address and a 64-bit memo ID into a single base32-encoded string starting | ||
| with `M`. Muxed addresses eliminate the need for separate memo handling and | ||
| reduce user error. They are particularly useful for custodial services and | ||
| exchanges that use pooled accounts. | ||
|
|
||
| **Important Notes**: | ||
|
|
||
| * Memos (especially `MEMO_ID`) are critical for exchange deposits and withdrawals | ||
| * Forgetting a memo when sending to an exchange typically results in lost funds | ||
| or delayed crediting | ||
| * Muxed addresses provide a safer alternative by embedding the memo ID directly | ||
| in the address | ||
| * Only `MEMO_ID` can be encoded in muxed addresses; `MEMO_TEXT` and `MEMO_HASH` require | ||
| classic addresses with appended memos | ||
|
|
||
| ## Test Cases | ||
|
|
||
| This is a list of manually composed examples | ||
|
|
||
| ```sh | ||
| # Pubnet classic address (without memo) | ||
| stellar:pubnet:GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ | ||
|
|
||
| # Testnet classic address (without memo) | ||
| stellar:testnet:GCEZWKCA5VLDNRLN3RPRJMRZOX3Z6G5CHCGSNFHEYVXM3XOJMDS674JZ | ||
|
|
||
| # Classic address with MEMO_ID | ||
| stellar:pubnet:GDQP2KPQGKIHYJGXNUIYOMHARUARCA7DJT5FO2FFOOKY3B2WSQHG4W37-123456789 | ||
|
|
||
| # Classic address with MEMO_TEXT | ||
| stellar:pubnet:GDQP2KPQGKIHYJGXNUIYOMHARUARCA7DJT5FO2FFOOKY3B2WSQHG4W37-payment-reference | ||
|
|
||
| # Classic address with MEMO_HASH (hex-encoded) | ||
| stellar:pubnet:GDQP2KPQGKIHYJGXNUIYOMHARUARCA7DJT5FO2FFOOKY3B2WSQHG4W37-b64aa7c0f6d5f5f6e8f1d1c7f5e5d5c5f5e5d5c5f5e5d5c5f5e5d5c5f5e5d5c5 | ||
|
|
||
| # Muxed address (Pubnet) with embedded ID 0 | ||
| stellar:pubnet:MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAAAACJUQ | ||
|
|
||
| # Muxed address (Pubnet) with embedded ID 420 | ||
| stellar:pubnet:MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAABUTGI4 | ||
|
|
||
| # Muxed address (Testnet) | ||
| stellar:testnet:MCEZWKCA5VLDNRLN3RPRJMRZOX3Z6G5CHCGSNFHEYVXM3XOJMAAAAAAAAAAAJLKA | ||
| ``` | ||
|
|
||
| ## Backwards Compatibility | ||
|
|
||
| Classic G-addresses without memos maintain full backward compatibility with | ||
| existing Stellar implementations. Muxed M-addresses (Protocol 13+) may not be | ||
| supported by older clients and should be verified before use. | ||
|
|
||
| ## References | ||
|
|
||
| * [Stellar Account Addressing][] - Overview of Stellar account addressing | ||
| * [SEP-0023: Strkey][SEP-0023] - Specification for strkey encoding used in Stellar addresses | ||
| * [CAP-0027: Muxed Accounts][CAP-0027] - Proposal for muxed account support | ||
| * [Stellar Memos][] - Detailed explanation of memo types and usage | ||
| * [SEP-0002: Federation Protocol][SEP-0002] - Human-readable federated addresses | ||
| * [Pooled Accounts Guide][] - Guide to muxed accounts and memos for pooled accounts | ||
|
|
||
|
|
||
| [CAIP-2]: ./caip2.md | ||
| [CAIP-10]: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md | ||
| [Stellar Account Addressing]: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts | ||
| [SEP-0023]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0023.md | ||
| [CAP-0027]: https://stellar.org/protocol/cap-27 | ||
| [RFC 4648]: https://datatracker.ietf.org/doc/html/rfc4648 | ||
| [Stellar Memos]: https://developers.stellar.org/docs/learn/encyclopedia/transactions-specialized/memos | ||
| [SEP-0002]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0002.md | ||
| [Pooled Accounts Guide]: https://developers.stellar.org/docs/learn/encyclopedia/transactions-specialized/pooled-accounts-muxed-accounts-memos | ||
|
|
||
| ## Copyright | ||
|
|
||
| Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| --- | ||
| namespace-identifier: stellar-caip19 | ||
| title: Stellar Namespace - Assets | ||
| author: Pelle Braendgaard (@pelle) | ||
| discussions-to: https://github.com/ChainAgnostic/namespaces/pull/157 | ||
| status: Draft | ||
| type: Standard | ||
| created: 2025-11-06 | ||
| requires: ["CAIP-2", "CAIP-10", "CAIP-19", "CAIP-20"] | ||
| --- | ||
|
|
||
| # CAIP-19 | ||
|
|
||
| *For context, see the [CAIP-19][] specification.* | ||
|
|
||
| ## Rationale | ||
|
|
||
| In the Stellar ecosystem, assets can be represented in several distinct formats. | ||
| The native asset (lumens/XLM) is identified using the SLIP-44 coin type registry (coin type 148), while issued assets are uniquely identified by combining an asset code (1-12 characters) with an issuer account address, separated by a hyphen. | ||
| Additionally, Protocol 18 introduced liquidity pool shares (defined in [CAP-38]) which represent fractional ownership in automated market maker pools, and Protocol 20 introduced Soroban smart contract tokens following the SEP-41 token interface standard. | ||
|
|
||
| ## Syntax | ||
|
|
||
| After the [CAIP-2] namespace+chainID, a slash defines an `asset_namespace` and an `asset_reference`. | ||
| Stellar supports multiple asset types with different identification schemes: | ||
|
|
||
| ### Asset Namespaces | ||
|
|
||
| | Namespace | Description | Reference Format | | ||
| | :--- | :--- | :--- | | ||
| | `slip44` | Native lumens (XLM) via SLIP-44 | `148` (Stellar's coin type) | | ||
| | `asset` | Issued asset with code and issuer | `{asset_code}-{issuer_address}` | | ||
| | `cap38` | Liquidity pool shares (CAP-38) | `{pool_id}` (64-char hex hash) | | ||
| | `sep41` | Soroban smart contract token (SEP-41) | `{contract_address}` (56-char strkey) | | ||
|
|
||
| ### Asset Code Requirements | ||
|
|
||
| Asset codes for issued assets must: | ||
|
|
||
| - Consist of printable ASCII characters (octets `0x21` through `0x7e`) | ||
| - Be 1-12 characters in length | ||
| - Be case-sensitive | ||
| - Not contain the hyphen character (`-`) as it is used as the delimiter | ||
|
|
||
| ### Issuer Address | ||
|
|
||
| The issuer address must be a valid Stellar G-address (56 characters, starting with `G`). | ||
|
|
||
| ### Liquidity Pool ID | ||
|
|
||
| Liquidity pool IDs are deterministically calculated as: | ||
|
|
||
| - SHA-256 hash of the liquidity pool parameters | ||
| - Pool parameters include: pool type and both assets in lexicographical order | ||
| - Represented as a 64-character lowercase hexadecimal string | ||
| - Only one pool can exist for a given asset pair | ||
|
|
||
| ### Contract Address | ||
|
|
||
| Soroban contract addresses are: | ||
|
|
||
| - Stellar `strkey`-encoded contract addresses (56 characters, starting with `C`) | ||
| - For Stellar Asset Contracts (SAC), the address can be derived from the classic asset identifier | ||
| - Can be obtained using: `stellar contract id asset --asset {code}:{issuer} --network {network}` | ||
|
|
||
| ## RegEx | ||
|
|
||
| The RegEx validation strings are as follows: | ||
|
|
||
| ```sh | ||
| asset_id: asset_type | ||
| asset_type: chain_id + "/" + asset_namespace + ":" + asset_reference | ||
| chain_id: namespace + ":" + blockchain_id (as defined in [CAIP-2]) | ||
|
|
||
| asset_namespace: "slip44" | "asset" | "cap38" | "sep41" | ||
|
|
||
| asset_reference: slip44_ref | asset_ref | cap38_ref | sep41_ref | ||
| slip44_ref: "148" | ||
| asset_ref: asset_code + "-" + issuer_address | ||
| asset_code: [!-,.-~]{1,12} | ||
| issuer_address: G[A-Z2-7]{55} | ||
| cap38_ref: [0-9a-f]{64} | ||
| sep41_ref: C[A-Z2-7]{55} | ||
| ``` | ||
|
|
||
| Note: The `asset_code` regex `[!-,.-~]` excludes the hyphen character (ASCII 0x2D) from the printable ASCII range (0x21-0x7E) since hyphen is used as the delimiter. | ||
|
|
||
| ## Semantics | ||
|
|
||
| ### Native Asset (XLM/Lumens) | ||
|
|
||
| The native asset is identified using the `slip44` namespace with coin type `148` as registered in the SLIP-44 registry. | ||
| The native asset is unique and does not require an issuer. | ||
| It is used for: | ||
|
|
||
| - Transaction fees (which are burned/destroyed) | ||
| - Minimum account balance requirements (base reserves) | ||
| - Bridge currency for cross-asset transactions | ||
|
|
||
| Example: `stellar:pubnet/slip44:148` | ||
|
|
||
| ### Issued Assets | ||
|
|
||
| Issued assets are created by issuers and must be explicitly trusted by recipients before they can be received. | ||
| The combination of asset code (1-12 characters) and issuer address uniquely identifies an asset. | ||
| On the Stellar network, asset codes of 1-4 characters are stored as `AlphaNum4`, while codes of 5-12 characters are stored as `AlphaNum12`, but both use the same `asset` namespace in [CAIP-19]. | ||
|
|
||
| Examples: | ||
|
|
||
| - USDC issued by Circle: `asset:USDC-{issuer_address}` | ||
| - Custom 8-character code: `asset:MYTOKEN8-{issuer_address}` | ||
|
|
||
| ### Liquidity Pool Shares (CAP-38) | ||
|
|
||
| Liquidity pool shares represent fractional ownership in constant product automated market maker pools (CPAMM) as defined in [CAP-38]. These shares: | ||
|
|
||
| - Are non-transferable (cannot be sent between accounts) | ||
| - Can be minted by depositing assets into the pool | ||
| - Can be redeemed for the underlying assets | ||
| - Are identified by a deterministic pool ID hash | ||
| - Use the `cap38` namespace | ||
|
|
||
| ### Soroban Contract Tokens (SEP-41) | ||
|
|
||
| Soroban contract tokens follow the [SEP-41] token interface standard and include: | ||
|
|
||
| - Stellar Asset Contracts (SAC): Wrapped versions of classic Stellar assets with smart contract functionality | ||
| - Custom [CAP-46-6] -compliant tokens: Fully custom tokens implemented as Soroban smart contracts | ||
| - All tokens use the `sep41` namespace and are identified by their contract address | ||
|
|
||
| ## Examples | ||
|
|
||
| ``` | ||
| # Native asset (lumens/XLM) on Pubnet | ||
| stellar:pubnet/slip44:148 | ||
|
|
||
| # Native asset on Testnet | ||
| stellar:testnet/slip44:148 | ||
|
|
||
| # USDC (4-character code) on Pubnet | ||
| stellar:pubnet/asset:USDC-GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN | ||
|
|
||
| # Custom token with 8-character code on Pubnet | ||
| stellar:pubnet/asset:MYCOIN88-GDQP2KPQGKIHYJGXNUIYOMHARUARCA7DJT5FO2FFOOKY3B2WSQHG4W37 | ||
|
|
||
| # Single character asset code on Testnet | ||
| stellar:testnet/asset:X-GCEZWKCA5VLDNRLN3RPRJMRZOX3Z6G5CHCGSNFHEYVXM3XOJMDS674JZ | ||
|
|
||
| # Liquidity pool (XLM-USDC pool) on Pubnet | ||
| stellar:pubnet/cap38:67260c4c1807b262ff851b0a3fe141194936bb0215b2f77447f1df11998eabb9 | ||
|
|
||
| # Soroban token contract (USDC) on Pubnet | ||
| stellar:pubnet/sep41:CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75 | ||
|
|
||
| # Custom Soroban token contract on Testnet | ||
| stellar:testnet/sep41:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4 | ||
| ``` | ||
|
|
||
| ## Backwards Compatibility | ||
|
|
||
| Issued Stellar assets (represented here as the `asset` namespace) correspond to the native Stellar `alphanum4` and `alphanum12` asset types, which have been supported since the genesis of the Stellar network and maintain full backward compatibility. | ||
|
|
||
| Liquidity pool shares were introduced in Protocol 18 (November 2021) and may not be supported by older clients. | ||
|
|
||
| Soroban contract tokens were introduced in Protocol 20 (February 2024) and require Soroban-aware clients and tooling. | ||
|
|
||
| ## References | ||
|
|
||
| - [Stellar Assets Overview][] - Overview of asset types on Stellar | ||
| - [SLIP-44][] - Registered coin types for HD wallets | ||
| - [CAIP-20][] - Asset Reference for the SLIP44 Asset Namespace | ||
| - [CAP-38: Automated Market Makers][CAP-38] - Liquidity pools specification | ||
| - [CAP-46-6: Smart Contract Standardized Asset][CAP-46-6] - Soroban token standard | ||
| - [SEP-41: Token Interface][SEP-41] - Standard token interface for Soroban | ||
| - [Stellar Asset Contract][] - Documentation for Stellar Asset Contracts | ||
| - [Liquidity Pools Guide][] - Guide to using liquidity pools on Stellar | ||
|
|
||
|
|
||
| [CAIP-2]: ./caip2.md | ||
| [CAIP-10]: ./caip10.md | ||
| [CAIP-19]: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-19.md | ||
| [CAIP-20]: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-20.md | ||
| [SLIP-44]: https://github.com/satoshilabs/slips/blob/master/slip-0044.md | ||
| [Stellar Assets Overview]: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/assets | ||
| [CAP-38]: https://github.com/stellar/stellar-protocol/blob/master/core/cap-0038.md | ||
| [CAP-46-6]: https://github.com/stellar/stellar-protocol/blob/master/core/cap-0046-06.md | ||
| [SEP-41]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0041.md | ||
| [Stellar Asset Contract]: https://developers.stellar.org/docs/tokens/stellar-asset-contract | ||
| [Liquidity Pools Guide]: https://developers.stellar.org/docs/learn/encyclopedia/sdex/liquidity-on-stellar-sdex-liquidity-pools | ||
|
|
||
| ## Copyright | ||
|
|
||
| Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a little ambiguous-- is it the asset or the issuer that must be explicitly "trusted" before being received? i'm a little unclear on whether this is a UX thing (wallets MUST get user consent) or a TXN-level trust attestation or a mysterious third thing-- in any case, probably warrants another sentence!