Skip to content
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 Sep 22, 2025
511832e
docs: add arc links
cusma Sep 22, 2025
1bf26cc
docs: better examples
cusma Sep 22, 2025
8833870
docs: arc3 compliance
cusma Sep 23, 2025
5b755d9
docs: security considerations
cusma Sep 23, 2025
955e0d2
docs: rationale
cusma Sep 23, 2025
2544522
docs: backward compatibility
cusma Sep 23, 2025
958cc87
docs: immutable asset metadata
cusma Sep 23, 2025
6aa1474
nit: encoded asset id as box name
cusma Sep 23, 2025
e5f7c03
docs: general refactoring
cusma Sep 23, 2025
4be3593
docs: fix headings
cusma Sep 23, 2025
b9c5feb
docs: add arc4 interface
cusma Sep 23, 2025
876010b
docs: improve security considerations
cusma Sep 24, 2025
663982c
chore: update header
cusma Sep 24, 2025
c160686
fix: discussion-to link
cusma Sep 24, 2025
6f78e5b
chore: add size limits to the rationale
cusma Sep 24, 2025
bf1a827
docs: clarify asset manager wording
cusma Sep 25, 2025
f57ade3
docs: clarify box name base64 encoding
cusma Sep 25, 2025
35f681f
docs: add arc89_get_metadata_mbr_delta
cusma Sep 25, 2025
4e4383c
docs: add a dedicated mbr section
cusma Sep 26, 2025
411097a
docs: add clarification on mbr delta getter
cusma Sep 26, 2025
27050a4
docs: nit
cusma Sep 26, 2025
568c552
docs: add metadata header and set immutable
cusma Sep 26, 2025
2f92345
docs: add extra payload helper, add get metadata
cusma Sep 26, 2025
71213b0
docs: add useful getters and helpers
cusma Sep 26, 2025
4acb5ef
docs: nit
cusma Sep 26, 2025
2073d56
docs: link mbr delta and improve its semantic in update
cusma Sep 26, 2025
ab76891
docs: fix typos
cusma Sep 26, 2025
3779bc7
docs: improve header specs, require utf-8 json object, add arc62 flag…
cusma Sep 29, 2025
97fea48
docs: minor enhancements
cusma Sep 30, 2025
e6fa49c
docs: mark reserved bit of the metadata header
cusma Oct 1, 2025
c16cacc
docs: add supported arcs getters
cusma Oct 2, 2025
9ef51a5
docs: update create metadata interface, minor enhancements
cusma Oct 2, 2025
8fdb7a0
docs: nit
cusma Oct 2, 2025
dab7ae3
docs: nit
cusma Oct 2, 2025
d1e5bd0
docs: no need to specify endianness with 1-byte bitmask
cusma Oct 2, 2025
b7cf26a
docs: add reserved header flags getters
cusma Oct 2, 2025
3ca51ca
docs: simplify header flags setters
cusma Oct 2, 2025
977953a
docs: rename header arg in signatures
cusma Oct 2, 2025
e5fa5b7
docs: add asset url requirements
cusma Oct 3, 2025
ebe9e4f
docs: major update after first dev council feedback
cusma Oct 10, 2025
273c696
docs: add events
cusma Oct 16, 2025
77d2067
docs: improve events, minor enhancements
cusma Oct 16, 2025
2c51c8f
docs: add the last modified round to two-way bits
cusma Oct 16, 2025
c2472de
docs: clarify base64url vs base64
cusma Oct 16, 2025
36f022c
docs: clarify arc69 and arc19 backward compatibility
cusma Oct 16, 2025
7687a1d
docs: add get metadata registry params
cusma Oct 17, 2025
59e6117
docs: update asset metadata hash
cusma Oct 17, 2025
182007e
docs: nit
cusma Oct 17, 2025
4407b1d
docs: nit
cusma Oct 17, 2025
1f619b8
docs: remove timestamp from header, add hash to header, reframe backw…
cusma Oct 22, 2025
ce7b868
docs: update metadata hash specifications
cusma Oct 22, 2025
69467e6
docs: add last modified round to updates, nits
cusma Oct 22, 2025
a4a5ed0
docs: add metadata identifier per-compute and validation, nits
cusma Oct 22, 2025
461b74e
docs: use camelcase for events
cusma Oct 28, 2025
b1a5f1b
docs: nit
cusma Oct 28, 2025
d4e3b7b
docs: add arc-22 requirement
cusma Oct 30, 2025
f1a167d
docs: specify extra-payload in top-level or inner-level group
cusma Oct 30, 2025
947f3bc
docs: remove permissions on extra payload
cusma Oct 30, 2025
ee84946
docs: require explicit metadata size on create and replace
cusma Oct 30, 2025
a8a296d
docs: revert authorization on extra payload
cusma Oct 30, 2025
219a988
docs: add arc-28 event signatures and selectors
cusma Oct 30, 2025
1563f82
docs: consider metadata hash for empty metadata edge case
cusma Oct 30, 2025
1444596
docs: convert arc3 and arc89 identifiers into flags
cusma Oct 30, 2025
9c1a0cd
docs: nit
cusma Oct 30, 2025
c7501db
docs: nit
cusma Oct 31, 2025
473fb8b
docs: nit
cusma Oct 31, 2025
11c50d0
docs: nit
cusma Oct 31, 2025
38cc19c
docs: nit
cusma Oct 31, 2025
cc8bb6c
docs: nit
cusma Oct 31, 2025
0b10a57
docs: clarify paging order
cusma Nov 3, 2025
5f52d14
docs: validate arc89 uri on creation
cusma Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
327 changes: 327 additions & 0 deletions ARCs/arc-0089.md
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>.
Loading