Skip to main content

ART_, IMAGE_, AUDIO_*

Three NFT families, one mint flow per media type. Active behind fork gates:

FamilyForkContent storage
ART (SVG)V3 (mainnet 18554)Inline svg field (text on-chain)
IMAGE (PNG/JPEG/WebP)V4 (inactive default)SOCIAL_BLOB chunks via blobId
AUDIO (WAV/MPEG/OGG)V5 (inactive default)SOCIAL_BLOB chunks via blobId

All three follow the same shape — only MINT differs in storage. TRANSFER and BURN are identical apart from the type string.

ART_MINT

FieldTypeNotes
type"ART_MINT"
fromstringOwner address (initial holder)
tokenIdstringsha256(taskId + svg) — deterministic
svgstringSanitized SVG markup, ≤ 16384 bytes
ownerstringInitial owner (often same as from)
taskIdstringSource TASK_SUBMIT (lineage)
minerIdstringMiner that generated the SVG
seedHashstringsha256(prompt + minerId + blockHash) — deterministic seed
model?stringGenerator model

Validation:

  • tokenId == sha256(taskId + svg) (helper: computeArtTokenId)
  • SVG passes sanitizer (no <script>, no onclick, no external URL refs)
  • tokenId not minted before

Effect:

  • state.artNfts[tokenId] = { svg, owner, taskId, minerId, mintedAt }
  • state.artByOwner[owner].push(tokenId)

IMAGE_MINT (Fork V4)

Same as ART_MINT, but svg field replaced with blobId pointing to a finalized SOCIAL_BLOB:

FieldTypeNotes
type"IMAGE_MINT"
tokenIdstringsha256(taskId + blobId + format + WxH)
blobIdstringPre-uploaded via SOCIAL_BLOB_INIT/CHUNK/FINALIZE
formatstring"image:png", "image:jpg", "image:webp"
width, heightnumberPixels
OthersSame as ART_MINT

Helper: computeImageTokenId(taskId, blobId, format, width, height).

AUDIO_MINT (Fork V5)

FieldTypeNotes
type"AUDIO_MINT"
tokenIdstringsha256(taskId + blobId + format + durationMs)
blobIdstringPre-uploaded SOCIAL_BLOB
formatstring"audio:wav", "audio:mpeg", "audio:ogg"
durationMsnumber
sampleRate?numberHz
OthersSame as ART_MINT

Helper: computeAudioTokenId(taskId, blobId, format, durationMs).

TRANSFER variants

ART_TRANSFER { type, from, tokenId, to, nonce, timestamp }
IMAGE_TRANSFER { type, from, tokenId, to, nonce, timestamp }
AUDIO_TRANSFER { type, from, tokenId, to, nonce, timestamp }

Effect: ownership changes hands. Token id is preserved.

BURN variants

ART_BURN { type, from, tokenId, nonce, timestamp }
IMAGE_BURN { type, from, tokenId, nonce, timestamp }
AUDIO_BURN { type, from, tokenId, nonce, timestamp }

Effect: NFT record marked burned, removed from owner index. Blob chunks (for IMAGE/AUDIO) remain on-chain as they may be referenced by other tx types.

Builders

buildArtMintTx(from, { tokenId, svg, owner, taskId, minerId, seedHash, model? }, nonce, privKey)
buildArtTransferTx(from, tokenId, to, nonce, privKey)
buildArtBurnTx(from, tokenId, nonce, privKey)
computeArtTokenId(taskId, svg)
computeArtSeedHash(prompt, minerId, blockHash)

buildImageMintTx(from, { tokenId, blobId, owner, taskId, minerId, prompt, seedHash, format, width, height, model? }, nonce, privKey)
buildImageTransferTx(...)
buildImageBurnTx(...)
computeImageTokenId(taskId, blobId, format, width, height)

buildAudioMintTx(from, { tokenId, blobId, owner, taskId, minerId, prompt, seedHash, format, durationMs, sampleRate?, model? }, nonce, privKey)
buildAudioTransferTx(...)
buildAudioBurnTx(...)
computeAudioTokenId(taskId, blobId, format, durationMs)

Large blob upload (IMAGE/AUDIO)

Before minting, upload the binary in chunks:

1. SOCIAL_BLOB_INIT — declare blobId, totalBytes, totalChunks, contentHash
2. SOCIAL_BLOB_CHUNK × N — base64-encoded chunks (≤ 400KB each)
3. SOCIAL_BLOB_FINALIZE — verifies contentHash matches assembled bytes
4. IMAGE_MINT / AUDIO_MINT — reference blobId

See Recipes › Upload large blob for a full example.

Next: Social txs →