ARC-87
ARC-87 (Draft, Standards Track) standardizes the key names used to store complex data (JSON, blobs) in application state, so any reader can address a single value directly on-chain. StoreKit is one of its reference implementations; the language-neutral vectors live in arc-87-reference.
Rules
All rules are about key names:
- SHOULD be prefixed with
o_(for discovery/indexing). - MUST separate nested object keys with
.. - SHOULD index collections with
[N]; readers MUST also accept.N(o_blobs[1]ando_blobs.1address the same value). - SHALL escape a segment that contains
.,[,],$or{by wrapping the literal segment as${literal}; readers MUST NOT interpret.or[N]inside an escaped span.
Objects
{ "alice": "APZK5I5UAURBDSGFBEHYK3B235CDGYGXG6BAGC34ZHGDPQOJTBM5OSG6IE", "bob": "BX2RWWE77PA7JNNIPWUBQYX44LDHDE6EBRFEPLJUOMBNLT4ATQ3SA7UGEQ", "metadata": { "rp": "algorand.co" }}| key | value |
|---|---|
o_alice | APZK5I5UAURBDSGFBEHYK3B235CDGYGXG6BAGC34ZHGDPQOJTBM5OSG6IE |
o_bob | BX2RWWE77PA7JNNIPWUBQYX44LDHDE6EBRFEPLJUOMBNLT4ATQ3SA7UGEQ |
o_metadata.rp | algorand.co |
Collections and blobs
A value larger than one box is chunked into a collection:
{ "index": 2, "mime": "text/plain", "blobs": ["...", "..."] }| key | value |
|---|---|
o_index | 2 |
o_mime | text/plain |
o_blobs[0] | ... |
o_blobs[1] | ... |
Escaping
{ "a.b": "dotted", "c[0]": "indexed" }| key | value |
|---|---|
o_${a.b} | dotted |
o_${c[0]} | indexed |
The ${literal} span is opaque to readers and is unwrapped to the original
segment when the object is assembled.
Out of scope
- Long keys. A box name is at most 64 bytes, prefix included. Templating longer paths is left to a future specification; the reference implementation rejects them.
- Value encoding. Values that are ARC-4 encoded need knowledge of their types to decode; mapping ARC-4 containers to key paths is left to a future specification.
- Private data is not addressed.
How StoreKit lays out a store
One store is one Lodash application; every leaf of the object is one box whose name is the prefix plus the leaf’s path. For example, the Quick Start store with a list added:
new Store({ count: 5, type: "Grizzly", tags: ["brown", "big"] })| box name | value |
|---|---|
orm_count | 5 |
orm_type | "Grizzly" |
orm_tags[0] | "brown" |
orm_tags[1] | "big" |
- Nested keys are joined with
.and array items written as[N]; on read both[N]and.Nare accepted. - Without a schema each value is the UTF-8 JSON of the leaf. With a JSON
Schema, covered paths hold raw ARC-4 bytes, and
x-storekit-box: "whole"packs a subtree into one box. - Names are limited to 64 bytes and values to 32 KiB (
MAX_KEY_SIZE,MAX_BOX_SIZE).
Because every value is directly addressable, reading a store needs nothing but the app’s boxes — and reading the boxes at a past round gives the store’s past state. See Time travel.