-
Notifications
You must be signed in to change notification settings - Fork 120
ARC-89: ASA Metadata Registry #356
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
cusma
wants to merge
72
commits into
algorandfoundation:main
Choose a base branch
from
cusma:arc89
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 16 commits
Commits
Show all changes
72 commits
Select commit
Hold shift + click to select a range
4f82219
docs: arc-89 draft
cusma 511832e
docs: add arc links
cusma 1bf26cc
docs: better examples
cusma 8833870
docs: arc3 compliance
cusma 5b755d9
docs: security considerations
cusma 955e0d2
docs: rationale
cusma 2544522
docs: backward compatibility
cusma 958cc87
docs: immutable asset metadata
cusma 6aa1474
nit: encoded asset id as box name
cusma e5f7c03
docs: general refactoring
cusma 4be3593
docs: fix headings
cusma b9c5feb
docs: add arc4 interface
cusma 876010b
docs: improve security considerations
cusma 663982c
chore: update header
cusma c160686
fix: discussion-to link
cusma 6f78e5b
chore: add size limits to the rationale
cusma bf1a827
docs: clarify asset manager wording
cusma f57ade3
docs: clarify box name base64 encoding
cusma 35f681f
docs: add arc89_get_metadata_mbr_delta
cusma 4e4383c
docs: add a dedicated mbr section
cusma 411097a
docs: add clarification on mbr delta getter
cusma 27050a4
docs: nit
cusma 568c552
docs: add metadata header and set immutable
cusma 2f92345
docs: add extra payload helper, add get metadata
cusma 71213b0
docs: add useful getters and helpers
cusma 4acb5ef
docs: nit
cusma 2073d56
docs: link mbr delta and improve its semantic in update
cusma ab76891
docs: fix typos
cusma 3779bc7
docs: improve header specs, require utf-8 json object, add arc62 flag…
cusma 97fea48
docs: minor enhancements
cusma e6fa49c
docs: mark reserved bit of the metadata header
cusma c16cacc
docs: add supported arcs getters
cusma 9ef51a5
docs: update create metadata interface, minor enhancements
cusma 8fdb7a0
docs: nit
cusma dab7ae3
docs: nit
cusma d1e5bd0
docs: no need to specify endianness with 1-byte bitmask
cusma b7cf26a
docs: add reserved header flags getters
cusma 3ca51ca
docs: simplify header flags setters
cusma 977953a
docs: rename header arg in signatures
cusma e5fa5b7
docs: add asset url requirements
cusma ebe9e4f
docs: major update after first dev council feedback
cusma 273c696
docs: add events
cusma 77d2067
docs: improve events, minor enhancements
cusma 2c51c8f
docs: add the last modified round to two-way bits
cusma c2472de
docs: clarify base64url vs base64
cusma 36f022c
docs: clarify arc69 and arc19 backward compatibility
cusma 7687a1d
docs: add get metadata registry params
cusma 59e6117
docs: update asset metadata hash
cusma 182007e
docs: nit
cusma 4407b1d
docs: nit
cusma 1f619b8
docs: remove timestamp from header, add hash to header, reframe backw…
cusma ce7b868
docs: update metadata hash specifications
cusma 69467e6
docs: add last modified round to updates, nits
cusma a4a5ed0
docs: add metadata identifier per-compute and validation, nits
cusma 461b74e
docs: use camelcase for events
cusma b1a5f1b
docs: nit
cusma d4e3b7b
docs: add arc-22 requirement
cusma f1a167d
docs: specify extra-payload in top-level or inner-level group
cusma 947f3bc
docs: remove permissions on extra payload
cusma ee84946
docs: require explicit metadata size on create and replace
cusma a8a296d
docs: revert authorization on extra payload
cusma 219a988
docs: add arc-28 event signatures and selectors
cusma 1563f82
docs: consider metadata hash for empty metadata edge case
cusma 1444596
docs: convert arc3 and arc89 identifiers into flags
cusma 9c1a0cd
docs: nit
cusma c7501db
docs: nit
cusma 473fb8b
docs: nit
cusma 11c50d0
docs: nit
cusma 38cc19c
docs: nit
cusma cc8bb6c
docs: nit
cusma 0b10a57
docs: clarify paging order
cusma 5f52d14
docs: validate arc89 uri on creation
cusma 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,327 @@ | ||
| --- | ||
| arc: 89 | ||
| title: ASA Metadata Registry | ||
| description: Singleton Application providing ASA metadata via Algod API | ||
| author: Cosimo Bassi (@cusma) | ||
| discussions-to: https://github.com/algorandfoundation/ARCs/issues/356 | ||
| status: Draft | ||
| type: Standards Track | ||
| category: Interface | ||
| sub-category: Asa | ||
| created: 2025-09-22 | ||
| requires: 4, 56, 82 | ||
| extends: 3 | ||
| replaces: 69 | ||
| --- | ||
|
|
||
| ## Abstract | ||
|
|
||
| This ARC defines the interface and the implementation of a singleton Application | ||
| that provides Algorand Standard Assets metadata through the Algod API. | ||
|
|
||
| ## Motivation | ||
|
|
||
| Algorand Standard Assets (ASA) lack a dedicated metadata field on the Algorand ledger | ||
| for storing additional asset information. | ||
|
|
||
| Although it's generally not advisable to use Algorand as a distributed storage system | ||
| for data that could easily reside elsewhere, the absence of a native metadata store | ||
| on the ledger has led the ecosystem to adopt less-than-ideal solutions for discovering | ||
| and fetching off-chain asset data, involving the usage of an Indexer or external | ||
| infrastructure (such as IPFS), or hacking on the ASA RBAC roles to get asset metadata | ||
| mutability. | ||
|
|
||
| While storing huge data, such as images, off-chain is a practical (and recommended) | ||
| approach, smaller, more pertinent data should not incur the expenses, availability | ||
| challenges, and latency typically associated with external infrastructure. | ||
|
|
||
| This ARC establishes a standardized URI within the ASA URL field to solve this simple | ||
| use case: _directly retrieving ASA metadata using the Algod API_. | ||
|
|
||
| ## Specification | ||
|
|
||
| The keywords "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", "**SHALL NOT**", | ||
| "**SHOULD**", "**SHOULD NOT**", "**RECOMMENDED**", "**MAY**", and "**OPTIONAL**" | ||
| in this document are to be interpreted as described in <a href="https://datatracker.ietf.org/doc/html/rfc2119">RFC 2119</a>. | ||
|
|
||
| > Notes like this are non-normative. | ||
|
|
||
| ### ASA Metadata Registry | ||
|
|
||
| The ASA Metadata Registry is an _immutable singleton_ Application that stores _mutable_ | ||
| or _immutable_ Asset Metadata. | ||
|
|
||
| #### ASA Metadata Box | ||
|
|
||
| The Asset Metadata are stored in a dedicated Box, called _Asset Metadata Box_. | ||
|
|
||
| The Asset Metadata Box Name **MUST** be equal to the _Asset ID_ (`uint64`). | ||
|
|
||
| The Asset Metadata **MUST** fit into a single Box. | ||
|
|
||
| #### [ARC-4](./arc-0004.md) Interface | ||
|
|
||
| ```json | ||
| { | ||
| "name": "ASA Metadata Registry", | ||
| "desc": "Singleton Application providing ASA metadata via Algod API", | ||
| "methods": [ | ||
| { | ||
| "name": "arc89_create_metadata", | ||
| "desc": "Create Asset Metadata for an existing ASA, restricted to the Asset Manager", | ||
| "args": [ | ||
| { "type": "uint64", "name": "asset_id", "desc": "The Asset ID to create the Asset Metadata for" }, | ||
| { "type": "bool", "name": "immutable", "desc": "Whether the Asset Metadata is immutable" }, | ||
| { "type": "tbd", "name": "tbd", "desc": "TBD" } | ||
| ], | ||
| "returns": { "type": "tbd", "desc": "tbd" } | ||
| }, | ||
| { | ||
| "name": "arc89_update_metadata", | ||
| "desc": "Update mutable Asset Metadata for an existing ASA, restricted to the Asset Manager", | ||
| "args": [ | ||
| { "type": "uint64", "name": "asset_id", "desc": "The Asset ID to update the Asset Metadata for" }, | ||
| { "type": "tbd", "name": "tbd", "desc": "TBD" } | ||
| ], | ||
| "returns": { "type": "tbd", "desc": "tbd" } | ||
| }, | ||
| { | ||
| "name": "arc89_delete_metadata", | ||
| "desc": "Delete Asset Metadata for an ASA, restricted to the Asset Manager (if the ASA still exists)", | ||
| "args": [ | ||
| { "type": "uint64", "name": "asset_id", "desc": "The Asset ID to delete the Asset Metadata for" }, | ||
| { "type": "tbd", "name": "tbd", "desc": "TBD" } | ||
| ], | ||
| "returns": { "type": "tbd", "desc": "tbd" } | ||
| }, | ||
| { | ||
| "name": "arc89_...", | ||
| "desc": "...", | ||
| "args": [ | ||
| { "type": "tbd", "name": "tbd", "desc": "TBD" } | ||
| ], | ||
| "returns": { "type": "tbd", "desc": "tbd" } | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| > Refer to the [AppSpec section](#appspec) for the detailed [ARC-56](./arc-0056.md) | ||
| > Application Specification of the singleton reference implementation. | ||
|
|
||
| ##### Create Metadata | ||
|
|
||
| To create the Asset Metadata: | ||
|
|
||
| - The ASA **MUST** _exist_, and | ||
|
|
||
| - The Asset URL (`au`) **MUST** conform to this specification (see the [Asset URL | ||
| section](#asset-url)), and | ||
|
|
||
| - The authorization **MUST** be restricted to the Asset Manager. | ||
|
|
||
| The Asset Metadata **MAY** be set as _immutable_. | ||
|
|
||
| The Asset Metadata **MUST** be stored as value of a new Asset Metadata Box. | ||
|
|
||
| The MBR of the created Asset Metadata Box **MUST** be provided contextually. | ||
|
|
||
| ##### Update Metadata | ||
|
|
||
| To update the Asset Metadata: | ||
|
|
||
| - The ASA **MUST** still _exist_, and | ||
|
|
||
| - The Asset Metadata **MUST NOT** be _immutable_, and | ||
|
|
||
| - The authorization **MUST** be restricted to the Asset Manager. | ||
|
|
||
| The updated Asset Metadata **MUST** replace the value of the existing Asset Metadata | ||
| Box. | ||
|
|
||
| The MBR of the updated Asset Metadata Box **MUST** be managed contextually: | ||
|
|
||
| - If the Asset Metadata Box size is increased, the additional MBR **MUST** be provided; | ||
|
|
||
| - If the Asset Metadata Box size is decreased, the freed-up MBR **MUST** be returned | ||
| to the Asset Manager. | ||
|
|
||
| ##### Delete Metadata | ||
|
|
||
| To delete the Asset Metadata: | ||
|
|
||
| - If the ASA still _exists_: | ||
|
|
||
| - The Asset Metadata **MUST NOT** _immutable_, and | ||
|
|
||
| - The authorization **MUST** be restricted to the Asset Manager. | ||
|
|
||
| - If the ASA has been _destroyed_: | ||
|
|
||
| - The authorization **MUST NOT** be restricted. | ||
|
|
||
| > Not even the Asset Manager can delete the _immutable_ Asset Metadata of an _existing_ | ||
| > ASA, while anyone can delete Asset Metadata if the ASA has been _destroyed_, regardless | ||
| > of being _immutable_ or not. | ||
|
|
||
| The Asset Metadata Box **MUST** be deleted. | ||
|
|
||
| The MBR of the deleted Asset Metadata Box **MUST** be managed contextually: | ||
|
|
||
| - If the ASA _exists_, it **MUST** be returned to the Asset Manager, otherwise | ||
|
|
||
| - It **MUST** be split among the caller (10%) and the Fee Sink (90%). | ||
|
|
||
| ### Asset URL | ||
|
|
||
| The _Asset URL_ (`au`) field is used as a _partial_ URI pointing to the Asset Metadata | ||
| on the Algorand ledger. | ||
|
|
||
| The _Asset URL_ (`au`) **MUST** be the _partial_ [ARC-82](./arc-0082.md) URI: | ||
|
|
||
| `algorand://app/<singleton_arc89_app_id>?box=` | ||
|
|
||
| Refer to the [Asset Metadata URI section](#asset-metadata-uri) for details about | ||
| the _complete_ [ARC-82](./arc-0082.md) _Asset Metadata URI_. | ||
|
|
||
| ### [ARC-3](./arc-0003.md) Compliance | ||
|
|
||
| The compliance with [ARC-3](./arc-0003.md) is **OPTIONAL** but **RECOMMENDED**. | ||
|
|
||
| If the ASA conforms to [ARC-3](./arc-0003.md), then: | ||
|
|
||
| - The ASA **MUST** comply with the [_ARC-3 ASA Parameters Conventions_](./arc-0003.md#asa-parameters-conventions) | ||
| for the _Asset Name_ (`an`) and the _Asset URL_ (`au`) fields. | ||
|
|
||
| - It is **RECOMMENDED** to use the `#arc3` _Asset URL_ (`au`) suffix option, so | ||
| the _partial_ [ARC-82](./arc-0082.md) URI would be: `algorand://app/<singleton_arc89_app_id>?box=#arc3` | ||
|
|
||
| - If the Asset Metadata are _immutable_, the ASA **MUST** comply with the [_ARC-3 | ||
| ASA Parameters Conventions_](./arc-0003.md#asa-parameters-conventions) for the _Asset | ||
| Metadata Hash_ (`an`) field. | ||
|
|
||
| - The Asset Metadata **MUST** comply with the [_ARC-3 JSON Metadata File Schema_](./arc-0003.md#json-metadata-file-schema). | ||
|
|
||
| Refer to the [Asset Metadata URI section](#asset-metadata-uri) for details about | ||
| the _complete_ [ARC-82](./arc-0082.md) _Asset Metadata URI_. | ||
|
|
||
| ### Asset Metadata URI | ||
|
|
||
| To get the [ARC-82](./arc-0082.md) _Asset Metadata URI_, clients **SHALL** complete | ||
| the _Asset URL_ with the `boxparam` filled with the Asset Metadata Box Name, equal | ||
| to the _Asset ID_ (encoded as `base64url`): | ||
|
|
||
| `algorand://app/<singleton_arc89_app_id>?box=<base64url_encoded_asset_id>` | ||
|
|
||
| #### Examples | ||
|
|
||
| > The _Asset Metadata URI_ for the ASA `12345` would be: | ||
| > | ||
| > `algorand://app/<singleton_arc89_app_id>?box=MDk=` | ||
| > | ||
| > The _Asset Metadata URI_ for the [ARC-3](./arc-0003.md) ASA | ||
| > `12345` would be: | ||
| > | ||
| > `algorand://app/<singleton_arc89_app_id>?box=MDk=#arc3` | ||
|
|
||
| ## Rationale | ||
|
|
||
| The _singleton_ ASA Metadata Registry Application and the standard [ARC-82](./arc-0082.md) | ||
| _Asset Metadata URI_ are a simple and efficient way to provide _mutable_ and _immutable_ | ||
| Asset Metadata to the clients directly through the <a href="https://dev.algorand.co/reference/rest-api/algod/">Algod API</a>, | ||
| without the need of an additional infrastructure. | ||
|
|
||
| The Asset Metadata size is limited on purpose to a single Box. This is a reasonable | ||
| trade-off between simplicity (avoiding Box chaining), data size (at most 32kB), and | ||
| Algod efficiency (discouraging the usage of Algorand as a distributed storage system). | ||
| Additional large metadata related to the ASA (such as images) can still be referenced | ||
| in the Asset Metadata, stored in the Box, through their external URI (e.g., `ipfs://...` | ||
| or `https://...`). | ||
|
|
||
| The standard supports two different entrypoints for the Asset Metadata discovery | ||
| and retrieval: the _Asset ID_ (available on the Algorand ledger) or the _Asset Metadata | ||
| URI_ (which could be distributed on the Web or by other external channels). | ||
|
|
||
| > Refer to the [Usage section](#usage) for details. | ||
|
|
||
| The compliance with [ARC-3](./arc-0003.md) ensures interoperability with existing | ||
| infrastructures, such as explorers and wallets, and other applications. | ||
|
|
||
| The deletion of (abandoned) Asset Metadata related to destroyed ASAs is incentivized | ||
| by returning a small fraction (10%) of the Asset Metadata Box MBR to the caller, | ||
| while the remainder (90%) is donated to the Fee Sink. | ||
|
|
||
| ## Backwards Compatibility | ||
|
|
||
| Backwards compatibility for existing ASA is not possible, since the _Asset URL_ (`au`) | ||
| field is immutable. | ||
|
|
||
| ## Reference Implementation | ||
|
|
||
| TBD | ||
|
|
||
| ### AppSpec | ||
|
|
||
| TBD | ||
|
|
||
| ### Usage | ||
|
|
||
| The clients use the Algod API to retrieve the Asset Metadata from two entrypoints: | ||
|
|
||
| 1. The _Asset ID_; | ||
|
|
||
| 1. The _Asset Metadata URI_. | ||
|
|
||
| > A minimal [Python SDK]() is provided with the reference implementation. | ||
|
|
||
| #### Example 1: Get [ARC-3](./arc-0003.md) Metadata from the Asset ID | ||
|
|
||
| Given the _Asset ID_ `12345`, the client: | ||
|
|
||
| 1. Calls the Algod API <a href="https://dev.algorand.co/reference/rest-api/algod/#getassetbyid">GetAssetByID</a> | ||
| endpoint to get the _Asset URL_ field (`url`) from the response and drops the `#arc3` | ||
| suffix (if present), obtaining: | ||
|
|
||
| `algorand://app/<singleton_arc89_app_id>?box=`; | ||
|
|
||
| 1. Encodes the _Asset ID_ as `base64url` to get the Asset Metadata Box Name (`<base64url_encoded_asset_id>`); | ||
|
|
||
| 1. Calls the Algod API <a href="https://dev.algorand.co/reference/rest-api/algod/#getapplicationboxbyname">GetApplicationBoxByName</a> | ||
| endpoint to get the content of the _Asset Metadata Box_ from the response: | ||
|
|
||
| ```shell | ||
| curl -X GET http://localhost/v2/applications/<singleton_arc89_app_id>/box?name=<base64_encoded_asset_id> \ | ||
| -H 'Accept: application/json' \ | ||
| -H 'X-Algo-API-Token: API_KEY' | ||
| ``` | ||
|
|
||
| The `value` field of the response contains the Asset [ARC-3](./arc-0003.md) JSON | ||
| Metadata. | ||
|
|
||
| #### Example 2: Get [ARC-3](./arc-0003.md) Metadata from Asset Metadata URI | ||
|
|
||
| Given the _Asset Metadata URI_ `algorand://app/<singleton_arc89_app_id>?box=<base64_encoded_asset_id>#arc3`, | ||
| the client: | ||
|
|
||
| 1. Calls the Algod API <a href="https://dev.algorand.co/reference/rest-api/algod/#getapplicationboxbyname">GetApplicationBoxByName</a> | ||
| endpoint to get the content of the _Asset Metadata Box_ from the response: | ||
|
|
||
| ```shell | ||
| curl -X GET http://localhost/v2/applications/<singleton_arc89_app_id>/box?name=<base64_encoded_asset_id> \ | ||
| -H 'Accept: application/json' \ | ||
| -H 'X-Algo-API-Token: API_KEY' | ||
| ``` | ||
|
|
||
| The `value` field of the response contains the Asset [ARC-3](./arc-0003.md) JSON | ||
| Metadata. | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| The authorization to create the Asset Metadata and update and delete _mutable_ Asset | ||
| Metadata is granted to the Asset Manager to preserve the ASA trust model. The authorization | ||
| is not granted to the Asset Creator, since this role could be performed programmatically | ||
| by Applications and is not supposed to be the long-lasting maintainer of the ASA. | ||
|
|
||
| ## Copyright | ||
|
|
||
| Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>. | ||
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.