$dmt-nat
Recursive demonstration
Last updated
Recursive demonstration
Last updated
To create UNAT mint inscriptions with rendered content, the following represents an example that utilized recursive inscriptions. Feel free to use the open source script to your advantage to create your own UNAT.
The mint inscription of a $dmt-nat looks like the following:
{
"p": "tap",
"op": "dmt-mint",
"dep": "4d967af36dcacd7e6199c39bda855d7b1b37268f4c8031fed5403a99ac57fe67i0",
"tick": "nat",
"blk": "319924"
}
If rendered properly, the inscription will appear like the following:
Mint inscriptions use the "dep" attribute in the JSON to point back to the $dmt-nat deployment inscription that looks like the following:
{
"p": "tap",
"op": "dmt-deploy",
"elem": "63b5bd2e28c043c4812981718e65d202ab8f68c0f6a1834d9ebea49d8fac7e62i0",
"tick": "nat",
"dt": "n",
"id": "61756c3e2dbcfbdb889f7176014e583e94800721a7379a616ec2c031563a5000i0"
}
The deployment inscription above has an "id" attribute that points back to an on-chain script where an algorithm is inscribed as JavaScript, and instantiated from multiple inscriptions with unique seeds from the mint inscription above. The unique seed being the block height inside the mint inscription.
The following script was used to render the images that make up the UNAT for $dmt-nat mints. Each mint inscription is a unique art piece rendered from Bitcoin's block data. Recursive images were used in this script and serves as a starting point for any creator to use this script to render their own content.
<canvas id="root" width="256" height="256"></canvas>
<input id="input" type="number" style="display:none" />
<script id="preview" mint="MINT_INSCRIPTION_ID">
const canvas = document.getElementById('root')
const ctx = canvas.getContext('2d')
canvas.parentElement.style.width = '100%'
canvas.parentElement.style.height = '100%'
canvas.parentElement.style.padding = '0px'
canvas.parentElement.style.margin = '0px'
const orgWidth = 462
const orgHeight = 462
let blockNumber = '0'
let scaleW = 0
let scaleH = 0
let offsetX = 0
let offsetY = 0
let background = new Image()
background.onload = redraw
background.src = '/content/45a7abf8aeab54c8b1ae87e05e502fd13b13984cc60101fd862c954b60cce678i0'
let center = new Image()
center.onload = redraw
let orb0 = new Image()
orb0.onload = redraw
let orb60 = new Image()
orb60.onload = redraw
let orb120 = new Image()
orb120.onload = redraw
let orb180 = new Image()
orb180.onload = redraw
let orb240 = new Image()
orb240.onload = redraw
let orb300 = new Image()
orb300.onload = redraw
window.addEventListener('resize', resize, true)
resize()
// Retrieve mint inscription id
let mintText = document.getElementById('preview').getAttribute('mint')
// Check no mint provided
if(mintText.includes('MINT_INSCRIPTION_ID')) {
let input = document.getElementById('input')
input.style.display = 'block'
input.style.position = 'absolute'
input.style.fontSize = '20px'
input.style.margin = '20px'
input.style.top = '0'
input.value = blockNumber
input.addEventListener('input',(event) => {
blockNumber = input.value
update()
})
update()
}
// Mint was provided
else {
const request = new XMLHttpRequest()
try {
request.open('GET', '/content/' + mintText)
request.responseType = 'text'
request.addEventListener('load', () => initialize(request.response))
request.addEventListener('error', () => console.error('XHR error'))
request.send()
} catch (error) {
console.error(`XHR error ${request.status}`)
}
}
function initialize(result) {
if(result) {
console.log('Result', result)
data = JSON.parse(result)
blockNumber = data.blk
}
update()
}
function update() {
center.src = getCent(getChar(blockNumber, 0))
orb0.src = getOrb(getChar(blockNumber, 1))
orb180.src = getOrb(getChar(blockNumber, 2))
orb60.src = getOrb(getChar(blockNumber, 3))
orb240.src = getOrb(getChar(blockNumber, 4))
orb120.src = getOrb(getChar(blockNumber, 5))
orb300.src = getOrb(getChar(blockNumber, 6))
}
function resize(event) {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
scaleW = canvas.width / orgWidth
scaleH = canvas.height / orgHeight
offsetX = 0
offsetY = 0
if(scaleH < scaleW) {
scaleW = scaleH
offsetX = (canvas.width - orgWidth * scaleW) / 2
}
else {
scaleH = scaleW
offsetY = (canvas.height - orgHeight * scaleH) / 2
}
redraw('resize')
}
function redraw(item) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
drawImageScaled(background, orgWidth/2, orgHeight/2)
drawLineScaled(getColor(getChar(blockNumber, 7)), 231, 231, 231, 98)
drawLineScaled(getColor(getChar(blockNumber, 9)), 231, 231, 341, 158)
drawLineScaled(getColor(getChar(blockNumber, 11)), 231, 231, 341, 291)
drawLineScaled(getColor(getChar(blockNumber, 8)), 231, 231, 231, 364)
drawLineScaled(getColor(getChar(blockNumber, 10)), 231, 231, 121, 291)
drawLineScaled(getColor(getChar(blockNumber, 12)), 231, 231, 121, 158)
drawArcScaled(getColor(getChar(blockNumber, 13)), 231, 230, 132, 0, 60)
drawArcScaled(getColor(getChar(blockNumber, 15)), 231, 230, 132, 60, 120)
drawArcScaled(getColor(getChar(blockNumber, 17)), 231, 230, 132, 120, 180)
drawArcScaled(getColor(getChar(blockNumber, 14)), 231, 230, 132, 180, 240)
drawArcScaled(getColor(getChar(blockNumber, 16)), 231, 230, 132, 240, 300)
drawArcScaled(getColor(getChar(blockNumber, 18)), 231, 230, 132, 300, 0)
drawImageScaled(center, 231, 231)
drawImageScaled(orb0, 231, 100)
drawImageScaled(orb60, 341, 158)
drawImageScaled(orb120, 344, 294)
drawImageScaled(orb180, 231, 362)
drawImageScaled(orb240, 118, 294)
drawImageScaled(orb300, 121, 158)
}
function drawArcScaled(color, x, y, radius, startDeg, endDeg) {
ctx.strokeStyle = color
ctx.lineWidth = 6 * scaleW
ctx.beginPath()
ctx.arc(offsetX + x * scaleW, offsetY + y * scaleH, radius * scaleH, (-90 + startDeg) * Math.PI/180, (-90 + endDeg) * Math.PI/180)
ctx.stroke()
}
function drawLineScaled(color, x1, y1, x2, y2) {
ctx.strokeStyle = color
ctx.lineWidth = 6 * scaleW
ctx.beginPath()
ctx.moveTo(offsetX + x1 * scaleW, offsetY + y1 * scaleH)
ctx.lineTo(offsetX + x2 * scaleW, offsetY + y2 * scaleH)
ctx.stroke()
}
function drawImageScaled(img, x, y) {
if(img == null) return
ctx.drawImage(img, offsetX + (x - img.width/2) * scaleW, offsetY + (y - img.height/2) * scaleH, scaleW * img.width, scaleH * img.height)
}
function getChar(str, char) {
return char >= str.length ? '0' : str.charAt(str.length - 1 - char)
}
function getCent(char) {
switch(char) {
case '0': // red
default:
return '/content/4ccae73d757bc81567c08b178dadc0f941ca5b590d8872d20b91b9aa0026c094i0'
case '1': // orange
return '/content/071839e2b743d6f0dde610318a94ea31688ad1ef7a466e1e49effd0bcbbc5ec2i0'
case '2': // green
return '/content/57389900ae0d2f5e78a3f0837f3e2ca807a6564f02c1e91c7547087551eb6d37i0'
case '3': // blue
return '/content/e7f83ec5fb95780f91a6ab9de90b5a00161521b2972abc32abe3726d559b17f8i0'
case '4': // yellow
return '/content/f76f76b594c5fa4f249b262e5bc68ee86a7a57afa90805843da0de64011dba39i0'
case '5': // purple
return '/content/255c0405421faf818b873b2a28dad78e06412763cd7b9c008223bde37df16d6ai0'
case '6': // gray
return '/content/dc8586612e28d1147aaa4bd059b18e479ee81c51bd33120f9234a2623fce6d2di0'
case '7': // light blue
return '/content/a4e15da4d0fe1590d0447f4bebf1ac6503e2d800473d8417b866c8db79e86fbci0'
case '8': // white
return '/content/b5dea9454f94220b826e9a40a9550b06fdaeda99a7dc125506511744de881237i0'
case '9': // black
return '/content/497b17636cf3410ed01853a203f32bd19c73deadd13fa583706e18bbc84d0805i0'
}
}
function getOrb(char) {
switch(char) {
case '0': // white
default:
return '/content/a44586031e19333c2ddeb3857ac8074897b4b7a9b5eb357cac02d9f960cc6087i0'
case '1': // red
return '/content/b641bfec1b6bec4f1a2ec26c269499dbad6192efbefff022e9a13d1436f435f2i0'
case '2': // green
return '/content/7416640b32d0423396374a9ea8da123b227ef0b99fcaa3f9b95de8a01f6fba35i0'
case '3': // blue
return '/content/9204e4f746de0a0e33fbd2454592473dc7aa027f251ac4147e4f96af91cad394i0'
case '4': // yellow
return '/content/2af78ab55427c0dffa501df64d8b9a5465a88e604bc878d33a1aafd9aeaf94bdi0'
case '5': // purple
return '/content/71cce084b6c1e01899e1917e7dc550053018629a930a3220382efabecb06a203i0'
case '6': // gray
return '/content/333ca2ee2b5399816a9b6eb2947ec19ab8a8a30470440e39bb4ce193ca24c2dfi0'
case '7': // light blue
return '/content/040378d2779d7d7f2a3df6d7de31e0e42f473c6b8428f070d94392ffa4ef196ci0'
case '8': // orange
return '/content/f20842305e554aa10e5266cf4cc119083c2a4928114195f40740075e4b70142ei0'
case '9': // black
return '/content/8ba3ff03dbc33a8d45b294a79ca91e9c8c2c8fc03a363f98e5c517422f49e13ai0'
}
}
function getColor(character) {
switch (character) {
case '0': return 'white'
case '1': return 'red'
case '2': return 'green'
case '3': return 'blue'
case '4': return 'yellow'
case '5': return 'purple'
case '6': return 'gray'
case '7': return 'lightblue'
case '8': return 'orange'
case '9': return 'black'
}
}
</script>