Metadata
URI and hash commitments for bounties, submissions, and disputes.
MosaicBounties.sol stores metadata on bounties, submissions, and disputes as metadataURI plus metadataHash.
The current website writes inline JSON data:application/json URIs. External clients may use any non-empty URI accepted by the contract, but the website only renders metadata it can parse locally.
Contract Requirements
| Field | Requirement |
|---|---|
metadataURI | Non-empty string. |
metadataHash | Non-zero bytes32. |
The contract does not fetch, parse, or validate the referenced payload. Clients verify payloads against metadataHash.
Bounty Payload Example
{
"version": 1,
"title": "Find a reproducible bug",
"brief": "Submit a minimal reproduction and a fix suggestion.",
"acceptanceCriteria": "Reproduction runs from a clean checkout, explains the cause, and includes a patch or pull request.",
"createdAt": "2026-05-28T00:00:00.000Z"
}The TypeScript MosaicMetadata type contains version, title, brief, optional acceptanceCriteria, and optional createdAt.
Submission Payload Example
{
"version": 1,
"type": "submission",
"content": "Minimal reproduction and fix suggestion.",
"createdAt": "2026-05-28T00:00:00.000Z"
}Dispute Payload Example
{
"version": 1,
"type": "dispute",
"reason": "Submission does not satisfy the acceptance criteria.",
"createdAt": "2026-05-28T00:00:00.000Z"
}TypeScript Hashing
import { canonicalJson, metadataToDataUri } from "@usemosiac/ts-sdk";
import { keccak256, stringToBytes } from "viem";
const metadata = {
version: 1,
title: "Find a reproducible bug",
brief: "Submit a minimal reproduction and a fix suggestion.",
};
const metadataUri = metadataToDataUri(metadata);
const metadataHash = keccak256(stringToBytes(canonicalJson(metadata)));canonicalJson(value) sorts object keys and drops undefined fields. metadataToDataUri(metadata) encodes that canonical JSON as a data:application/json URI.
Python Hashing
from mosaic_sdk import canonical_metadata_hash
metadata = {
"version": 1,
"title": "Find a reproducible bug",
"brief": "Submit a minimal reproduction and a fix suggestion.",
}
metadata_hash = canonical_metadata_hash(metadata)canonical_metadata_hash(metadata) hashes sorted compact JSON with Keccak.
Website Behavior
Website posting creates:
- Bounty metadata with
version,title,brief, optionalacceptanceCriteria, andcreatedAt. - Submission metadata with
version,type: "submission",content, andcreatedAt. - Dispute metadata with
version,type: "dispute",reason, andcreatedAt.
Website rendering parses inline JSON and raw JSON strings. It displays bounty title, brief, and acceptanceCriteria; submission content; and dispute reason.
The website does not fetch ar://, ipfs://, http://, or https:// metadata bodies for display.
URI Formats
| URI | Website Behavior | SDK Behavior |
|---|---|---|
data:application/json,... | Posted and rendered. | TypeScript parseMetadataUri parses inline JSON. |
data:application/json;base64,... | Rendered if indexed. | TypeScript parseMetadataUri parses inline base64 JSON. |
| Raw JSON string | Rendered if indexed. | TypeScript parseMetadataUri parses strings that start with {. |
ar://... | Not fetched or rendered. | Python load_metadata fetches through the configured gateway. |
ipfs://... | Not fetched or rendered. | No SDK fetch helper. |
https://... | Not fetched or rendered. | Python load_metadata fetches the URL directly. |
load_metadata(uri, expected_hash) raises when the downloaded JSON hash does not match expected_hash.
Hash Input
Hash the exact JSON payload referenced by the URI. Do not hash rendered Markdown, preview text, or formatted display output.
