Mint an SVG NFT (ART)
Mint an SVG generated by the network as an on-chain ART NFT (Fork V3, active on mainnet).
Flow
1. Submit TASK_SUBMIT type="nft_svg" with prompt
2. Wait for TASK_REWARD (best miner produces SVG)
3. Fetch SVG from /api/chain/task/:id → bestResponse.content
4. Build ART_MINT tx with deterministic tokenId
5. Broadcast
6. NFT appears at /api/nft/:tokenId
Full code
import {
OmbraClient, Wallet,
buildTaskSubmitTx, buildArtMintTx,
computeArtTokenId, computeArtSeedHash,
} from "@ombrachain/sdk";
import { randomBytes } from "crypto";
const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" });
const wallet = Wallet.fromMnemonic("...");
async function mintArt(prompt: string) {
// 1. Submit NFT SVG task
const taskId = randomBytes(16).toString("hex");
let acct = await client.chain.getAccount(wallet.address);
const submitTx = buildTaskSubmitTx(
wallet.address, taskId, "nft_svg", prompt,
500_000n, // 0.5 OMBRA — fair for quality SVG
acct.nonce, wallet.privateKey,
);
await client.chain.submitTx(submitTx);
console.log("task submitted:", taskId);
// 2. Poll for rewarded
for (let i = 0; i < 90; i++) {
await new Promise((r) => setTimeout(r, 2_000));
const task = await client.chain.getTask(taskId);
if (task.status === "rewarded") {
// 3. Get best SVG content
const bestResponse = task.responses.find((r: any) => r.minerId === task.bestMinerId);
const svg = bestResponse.content;
const minerId = task.bestMinerId;
const model = bestResponse.model;
const blockHash = bestResponse.blockHash;
// 4. Build ART_MINT
const tokenId = computeArtTokenId(taskId, svg);
const seedHash = computeArtSeedHash(prompt, minerId, blockHash);
acct = await client.chain.getAccount(wallet.address);
const mintTx = buildArtMintTx(wallet.address, {
tokenId,
svg,
owner: wallet.address,
taskId,
minerId,
seedHash,
model,
}, acct.nonce, wallet.privateKey);
await client.chain.submitTx(mintTx);
console.log("minted NFT:", tokenId);
console.log("explorer:", `https://ombra-net.com/nft/${tokenId}`);
return { tokenId, svg };
}
}
throw new Error("task did not complete in 3 minutes");
}
await mintArt("Minimal red triangle with crimson glow on dark background");
SVG sanitizer rules
The chain rejects unsafe SVG. Your SVG must:
- Start with
<svgand end with</svg> - Have
xmlns="http://www.w3.org/2000/svg" - NOT contain:
<script>,<foreignObject>,<iframe>,<image>,<link>,<style>with@import - NOT use:
on*attributes (onclick,onload),javascript:URLs, externalhref - Be ≤ 16384 bytes total
The network's nft_svg task prompt wrapper enforces these rules on the miner side. If you build a custom SVG, sanitize before mint.
Browser via extension
const result = await window.ombra.request({
method: "ombra_mintArt",
params: {
svg: "<svg xmlns=...>...</svg>",
taskId,
minerId,
model,
},
}) as { tokenId: string; txHash: string };
Extension computes tokenId deterministically and shows the SVG preview before approval.
Verify the mint
# Metadata
curl https://api.ombra-net.com/api/nft/YOUR_TOKEN_ID
# Raw SVG
curl https://api.ombra-net.com/api/nft/YOUR_TOKEN_ID/svg
Or open https://ombra-net.com/nft/YOUR_TOKEN_ID in the explorer.
Transfer / burn
import { buildArtTransferTx, buildArtBurnTx } from "@ombrachain/sdk";
// Transfer
const xferTx = buildArtTransferTx(wallet.address, tokenId, recipientAddr, nonce, privKey);
await client.chain.submitTx(xferTx);
// Burn
const burnTx = buildArtBurnTx(wallet.address, tokenId, nonce, privKey);
await client.chain.submitTx(burnTx);