Dynamic Vault listing (database-based metadata)
Flexible approach to list your dapp on the Chromia Vault using database-stored metadata. Perfect for production dapps or when you need frequent content updates.
Prerequisites
- A deployed dapp on Chromia (Mainnet or Testnet)
- Media files for your dapp (icons, screenshots, etc.)
- Admin key pair for managing operations
Implementation
Create a new module for Vault listing functionality. Copy this complete implementation into your
dynamic_vault_listing.rell
file:
You only need to change "My dapp name" to your actual dapp's name in this code. All other parts can remain as shown.
module;
struct module_args {
admin_pubkey: byte_array;
dapp_name: text;
}
function require_admin_signer() =
require(op_context.is_signer(chain_context.args.admin_pubkey), "The operation requires admin signer");
enum dapp_content_type {
landscape,
portrait,
promotional,
video,
icon
}
entity dapp {
key name;
mutable description: text = "";
mutable launch_url: text = "";
mutable genre: text = "";
}
entity dapp_media {
key dapp, name;
mutable url: text = "";
type: dapp_content_type;
}
entity blockchain {
key dapp, brid: byte_array;
index brid;
index mutable name: text;
mutable role: text;
}
operation create_or_update_dapp(description: text, launch_url: text, genre: text) {
require_admin_signer();
functions.create_or_update_dapp(chain_context.args.dapp_name, description, launch_url, genre);
}
operation create_or_update_blockchain(brid: byte_array, chain_name: text, role: text) {
require_admin_signer();
val dapp = get_dapp_by_name(chain_context.args.dapp_name);
functions.create_or_update_blockchain(dapp, brid, chain_name, role);
}
operation create_or_update_dapp_media(name, url: text, type: dapp_content_type) {
require_admin_signer();
functions.create_or_update_dapp_media(chain_context.args.dapp_name, name, url, type);
}
query find_dapp_details(dapp_rowid: rowid, requested_content_types: list<dapp_content_type>? = null){
val dapp = get_dapp_by_name(chain_context.args.dapp_name);
return map_dapp_details(dapp, requested_content_types);
}
namespace functions {
function create_or_update_blockchain(dapp, brid: byte_array, name: text, role: text) {
val blockchain = blockchain @? { brid };
if (empty(blockchain)) {
create blockchain ( dapp, brid, name, role );
} else {
update blockchain ( name, role );
}
}
function create_or_update_dapp(name, description: text, launch_url: text, genre: text) {
val dapp = dapp @? { name };
if (empty(dapp)) {
create dapp ( name, description, launch_url, genre );
} else {
update dapp ( description, launch_url, genre );
}
}
function create_or_update_dapp_media(dapp_name: text, name, url: text, type: dapp_content_type) {
val dapp = dapp @? { dapp_name == .name };
require(not empty(dapp), "dapp not found");
val media = dapp_media @? { dapp!!, name };
if (empty(media)) {
create dapp_media ( dapp, name, url, type );
} else {
update media ( url );
}
}
}
function get_dapp_by_name(name) = dapp @ { name };
function map_dapp_details(dapp, requested_content_types: list<dapp_content_type>? = null) {
val blockchains = find_and_map_dapp_blockchains(dapp);
val dapp_media = if (not empty(requested_content_types)) find_and_map_dapp_media(
dapp,
requested_content_types
) else null;
return (
rowid = dapp.rowid,
name = dapp.name,
description = dapp.description,
launch_url = dapp.launch_url,
genre = dapp.genre,
chain_list = blockchains,
content = dapp_media
).to_gtv_pretty();
}
function find_and_map_dapp_blockchains(dapp) =
blockchain @* { dapp } (
@omit @sort .rowid,
name = .name,
brid = .brid,
role = .role
);
function find_and_map_dapp_media(dapp, requested_content_types: list<dapp_content_type>) =
dapp_media @* {
dapp,
.type in requested_content_types
} (
@omit @sort .rowid,
name = .name,
url = .url,
type = .type
);
Configuration
1. Include the module in your main Rell file
Add the following line to your main Rell file (e.g., main.rell
) to import the vault listing module:
import dynamic_vault_listing;
2. Update your chromia.yml
file
Update your chromia.yml
file to include the Vault listing module with admin authentication:
blockchains:
<blockchain_name>:
module: main
moduleArgs:
dynamic_vault_listing:
admin_pubkey: x"<public_key>" # Your admin public key
dapp_name: <blockchain_name>
Deployment
1. Update your dapp with Vault module
After adding the code, deploy your changes to either Testnet or Mainnet:
chr deployment update --network <deployment_name> --blockchain <blockchain_name>
2. Create dapp metadata
chr tx --network <deployment_name> --blockchain <blockchain_name> create_or_update_dapp "Your dapp description" "https://your-dapp-url.com" "Your genre"
Expected output:
transaction with rid A9B05BCC105E69AD627984463BF0B6A9496CF3D9AFD721683B21DC1C91382BCB was posted and confirmed
3. Create blockchain data
chr tx --network <deployment_name> --blockchain <blockchain_name> create_or_update_blockchain 'x"D2...3B2"' <blockchain_name> "Role description"
Expected output:
transaction with rid A9B05BCC105E69AD627984463BF0B6A9496CF3D9AFD721683B21DC1C91382BCB was posted and confirmed
4. Create media data (use a link to Filehub or external image service)
chr tx --network <deployment_name> --blockchain <blockchain_name> create_or_update_dapp_media "icon" "https://pbs.twimg.com/profile_images/1928427668728598528/xbFphaFl_400x400.jpg" 4
Expected output:
transaction with rid A9B05BCC105E69AD627984463BF0B6A9496CF3D9AFD721683B21DC1C91382BCB was posted and confirmed
The media type parameter uses the enum index: landscape=0
, portrait=1
, promotional=2
, video=3
, icon=4
.
Verify the data
# Basic verification (no media content)
chr query --network <deployment_name> --blockchain <blockchain_name> --output-format json find_dapp_details dapp_rowid=0 'requested_content_types=[]'
# Get all media content
chr query --network <deployment_name> --blockchain <blockchain_name> --output-format json find_dapp_details dapp_rowid=0 'requested_content_types=["landscape", "portrait", "promotional", "video", "icon"]'
Automatic listing
Once you implement the query and functions, your dapp will be automatically listed in the Chromia Vault based on the information it provides.
Making changes
To update your dapp's metadata, call the appropriate operations:
- Update description/URL/genre: Use
create_or_update_dapp
- Update blockchain info: Use
create_or_update_blockchain
- Add/update media: Use
create_or_update_dapp_media
No redeployment is required - changes are immediate!
Admin key management
Keep your admin key secure and accessible for making updates. The admin key is specified in your chromia.yml
file and
is required for all metadata operations.
Optional: Storing media content on chain
If you want to store your media files on-chain for enhanced decentralization, you can use Filehub, Chromia's decentralized storage platform.
Consider using Filehub for decentralized media storage. Fixed cost of $0.10 per MB for perpetual storage with free access for everyone. Requires CHR tokens on the Economy Chain (minimum 1 CHR deposit).
Recommended image sizes:
- Horizontal image preview - 180px x 100px (recommended x3 - 540px x 300px)
- Vertical image preview - 180px x 240px (recommended x3 - 540px x 720px)
- Big image - 510px x 286px (recommended x3 - 1530px x 858px)
- Pagination image - 86px x 48px (recommended x3 - 258px x 144px)