├── README-CN.md ├── README.md └── assets ├── gen-brc721-dune.png └── ordibots-sample.png /README-CN.md: -------------------------------------------------------------------------------- 1 | # 生成式 BRC-721 2 | 3 | > ***概述**: 本提案介绍了生成式 BRC-721 标准,这是一种优化比特币序数生态系统中区块空间使用的解决方案,可容纳更多创作者并促进创新。该标准利用“部署”操作来创建具有存储在链上的独特特征的生成式 BRC-721 集合。然后,“铸造”操作引用部署操作中的特征,生成非同质化的 Ordinals(NFT)。此过程将区块空间使用量减少 50% 到 90%。通过一个名为“OrdiBots”的生成式 BRC-721 集合的案例研究证明了本提案的影响,该集合减少了 55% 区块空间。前端将需要进行调整以重新创建和显示来自铸造铭文文本数据里的图像。本提案标准为比特币区块链的高效去中心化创新奠定了基础。* 4 | 5 | 本倡议旨在在比特币序数生态系统中引发更多关于不可替代标准的交流。它旨在提高启动 Ordinals 图片集合的效率,类似于通过 BRC-20 标准创建同质化代币。 6 | 7 | **Dune 仪表板演示:** [Generative BRC-721 (WIP)](https://dune.com/j543/generative-brc-721) 8 | 此 Dune 分析仪表板目前用作监控特定生成式 BRC-721 集合的铸造活动的工具。请注意,它可能需要进一步改进才能完全满足用户的需求。 9 | 10 | ![](./assets/gen-brc721-dune.png) 11 | 12 | ## 背景 13 | 14 | 随着比特币网络费用飙升并稳定在一个新的更高的平衡点,大量的创作者正在加入这个领域。这种趋势正在增加对比特币区块空间的需求,预计在不久的将来会进一步上升。为了让创作者在比特币区块链上发布他们的创新想法敞开大门,我们必须优化当前发布 Ordinals 图片集合的标准。 15 | 16 | ## 想法 17 | 18 | 我们提出了一个新标准来启动非同质化的生成式 Ordinals 集合。该标准可以节省所有链上资源,同时实现 50% 到 90% 的区块空间优化。该过程包括三个主要操作: 19 | 20 | - 使用部署操作创建生成式 BRC-721 集合 21 | - 使用铸造操作铸造一个非同质化的 Ordinal 集合 22 | - 将非同质化 Ordinal 转移为标准序号铭文。 23 | 24 | 所有这些过程都可以在不需要外部索引器的情况下进行,前提是集合创建者按照当前要求发布其集合铭文的官方清单。 25 | 26 | ## 操作 27 | 28 | ### 部署生成式 BRC-721 29 | 30 | 部署操作使用一个 JSON/Text 铭文,其中包含集合的一般信息,以及构成集合特征的 base64 编码数据。用于创建Ordinals NFT 特征的独特图像存储在链上铭文内。铭文作为特征的参考和最终来源。 31 | 32 | 注意:也可以为同一个集合创建多个部署铭文,每个都将存储一组不同的特征。 33 | 34 | *出于演示目的,我们使用 OrdiBots 集合* 35 | *部署铭文示例:[Ord.io](https://www.ord.io/8326719)* 36 | 37 | ```javascript 38 | { 39 | "p": "gen-brc-721", 40 | "op": "deploy", 41 | "slug": "ordibots", 42 | "name": "OrdiBots", 43 | "supply": 1000, 44 | "trait_types": [ 45 | "background", 46 | "accessories", 47 | "body", 48 | "belly", 49 | "face" 50 | ], 51 | "dim": [32,32], 52 | "traits": { 53 | "background": { 54 | "blue": { 55 | "name": "Blue", 56 | "base64": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA1BMVEVkhZa3PARZAAAAC0lEQVR4AWMY5AAAAKAAAVQqnscAAAAASUVORK5CYII=" 57 | }, 58 | ... // more backgrounds 59 | }, 60 | "accessories": { 61 | "antenna": { 62 | "name": "Antenna", 63 | "base64": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAKUlEQVRYCe3BsQ0AIADDsOT/o8sJLEgssSHJhTpg4oDxmzKSJEmS5KEDUlIFA6L+DvwAAAAASUVORK5CYII=" 64 | }, 65 | ... // more accessories 66 | }, 67 | ... // other traits 68 | } 69 | } 70 | ``` 71 | 72 | | 字段 | 是否必须 | 描述 | 73 | | ----------- | -------- | ------------------------------------------------------------ | 74 | | p | 是 | 协议:帮助其他系统识别和处理 gen-brc-721 事件 | 75 | | op | 是 | 操作:事件类型(部署、铸造) | 76 | | slug | 是 | 代币:集合的标识符。如果没有索引器实施则不强制执行 | 77 | | name | 否 | 名称:集合的人类可读名称 | 78 | | supply | 否 | 供应量:集合的供应量。如果没有索引器实施则不强制执行 | 79 | | trait_types | 是 | 特征类型:这是一个数组,它规定了应该呈现特征的顺序。 | 80 | | dim | 是 | 尺寸:一个数组,表示以像素为单位的特征和最终图像的尺寸(宽度和高度),定义为 [width, height]。 | 81 | | traits | 是 | 特征:包含集合的独特特征的对象。组成为:{trait type: {trait key: {name, base64 image encoded}}} | 82 | 83 | 84 | 85 | ### 铸造生成式 BRC-721 86 | 87 | 铸造操作使用 JSON/Text 铭文,其中封装了有关正在铸造的实际非同质化 Ordinal(NFT) 的信息以及对部署铭文的引用。目的是存储生成图像的属性值、最终图像的哈希值以及链上部署铭文集合的引用。这种方法允许任何人使用链上刻录数据重新创建图像。 88 | 89 | *出于演示目的,我们使用 OrdiBots 集合* 90 | *铸造铭文示例:* [Ord.io](https://www.ord.io/8400075) 91 | 92 | ```javascript 93 | { 94 | "p":"gen-brc-721", 95 | "op":"mint", 96 | "s":"ordibots", 97 | "t_ins":[ 98 | "b7205d40f3b1b1486567f0d6e53ff2812983db4c03ad7d3606812cd150c64802i0" 99 | ], 100 | "h":"aa0d33b748e0177528a910a56a61c47bee2ba9b69749228d6520049c0fea3f4f", 101 | "id":"554", 102 | "a":[ 103 | [0,"bitcoin-orange"], 104 | [0,"rainbow"], 105 | [0,"black-and-white-triangular"], 106 | [0,"square"], 107 | [0,"happy"] 108 | ] 109 | } 110 | ``` 111 | 112 | | 字段 | 是否必须 | 描述 | 113 | | ----- | ---------- | ------------------------------------------------------------ | 114 | | p | 是 | 协议:帮助其他系统识别和处理 gen-brc-721 事件 | 115 | | op | 是 | 操作:事件类型(部署、铸造) | 116 | | s | 是 | 代币:集合的标识符。如果没有索引器实施则不强制执行 | 117 | | t_ins | 是 | 特征(部署)铭文:包含部署铭文的铭文 ID(s) 的数组 | 118 | | h | ~~是~~ 否 | 哈希:这是指生成图像的 SHA256 输出。这是一个可选元素;集合创建者可以灵活地决定是否要在他们的集合中加入这个额外的安全检查。选择不使用哈希可以提高生成铭文过程的效率。 | 119 | | id | ~~否~~ 是 | Token ID:集合中每个非同质化 Ordinal(NFT) 的唯一标识符。对于跟踪和区分单个 NFOs 至关重要。 | 120 | | a | 是 | 属性:这是一个数组,其中包含此特定非同质化 Ordinal(NFT) 的属性值。每个数组元素的结构如下:[inscription_index, traits_value]。
这里的 inscription_index 表示包含相应特征的base64数据的部署铭文ID,traits_value 表示具体特征的实际值。“a”数组中的元素顺序应与部署铭文中的“trait_types”键顺序相对应。
例如,这种情况下的顺序是:(1) background = bitcoin-orange; (2) accessories = rainbow; (3) body = black-and-white-triangular; (4) belly = square; (5) face = happy. | 121 | 122 | ## 影响 123 | 124 | 实施生成式 BRC-721 标准将提高比特币区块空间的利用效率。由于独特特征的图像在部署事务中只被记录一次,资产由引用这些特征的文本文件组成。任何人都可以使用链上部署铭文重新创建图像,并使用 SHA256 输出验证结果。 125 | 126 | ### 案例研究: OrdiBots 127 | 128 | 为了演示该提议标准的实施,我们推出了一个名为 OrdiBots 的演示生成式 BRC-721 集合。这个由 26 个不同特征组成的 1,000 个序数的集合显示,新标准的区块使用空间减少了 55%。这一结果表明,使用更复杂的特征集合可能会提高效率。 129 | 130 | 1,000 张图像加起来的总大小约为 663kb。以目前大约 30 sats/vB 的网络费用计算,刻录整个收藏的成本约为 0.293BTC(按当前价格计算为 7,850 美元)。通过实施生成式 BRC-721 标准,我们可以将整个集合的大小减少到 294kb(10kb + 284kb),因此预计总区块空间减少约 55%。这可以被认为是一个较低的门槛,因为 OrdiBots 已经是一个非常轻的集合,我们可以期望通过更复杂的特征生成的集合具有更高的效率。 131 | 132 | - 部署铭文: https://www.ord.io/8326719 (10kb) 133 | - 所有可能的资产铭文文件: [ordibots-assets.json](https://luminex-public.s3.eu-west-1.amazonaws.com/collections/ordibots/ordibots-assets.json) (284kb) 134 | - Mint 铭文示例: https://www.ord.io/8400075 (344 bytes) 135 | 136 | ![image-20230521234811232](./assets/ordibots-sample.png) 137 | 138 | ### 前端 139 | 140 | 如果这个标准被广泛的收藏和创作者采用,前端界面将需要调整以显示铸造铭文生成的实际图像,而不是文本数据。这可以通过扫描“gen-brc-721”用户文本铭文来无缝完成。然后可以使用专门的链上数据重新生成图像,并随后存储在他们的系统基础设施中,其方式与目前的做法大致相同。 141 | 142 | 事实上,大多数 ordinal 平台不会在每次需要向用户显示图像铭文时查询区块链。相反,为了方便和高效,他们通常将这些图像存储在自己的数据库中。因此,实施该标准不会对流行的方法造成重大改变。 143 | 144 | ### 重新创建链上图像 145 | 146 | 要从部署铭文重建图像,我们可以使用下面描述的简单脚本。将前面描述的铸造操作格式数据作为输入,该脚本不仅会生成 base64 编码的图像,还会生成其相应的哈希值。 147 | 148 | 但是,请务必注意,此脚本只是一个说明性示例,此时可能无法全面涵盖所有场景。 149 | 150 | ```javascript 151 | const fetch = require('node-fetch'); 152 | const { createCanvas, Image } = require('canvas'); 153 | const crypto = require('crypto'); 154 | 155 | async function createImage(attributes, t_ins) { 156 | let baseImg; 157 | let ctx; 158 | 159 | let promises = []; 160 | let images = new Array(attributes.length); 161 | 162 | for (let i = 0; i < attributes.length; i++) { 163 | let attribute = attributes[i]; 164 | let inscriptionIndex = attribute[0]; 165 | let traitValue = attribute[1]; 166 | 167 | let traitsInscriptionId = t_ins[inscriptionIndex]; 168 | 169 | let promise = fetch('https://ordinals.com/content/' + traitsInscriptionId) 170 | .then(res => res.json()) 171 | .then(data => { 172 | // Map the index of the attribute to the corresponding trait_type 173 | let traitType = data.trait_types[i]; 174 | 175 | let base64ImageString = data.traits[traitType][traitValue]['base64']; 176 | 177 | let img = new Image(); 178 | let [x_dim, y_dim] = data.dim || [32, 32]; // Default to [32, 32] if 'dim' is not defined 179 | 180 | baseImg = createCanvas(x_dim, y_dim); 181 | ctx = baseImg.getContext('2d'); 182 | 183 | return new Promise((resolve, reject) => { 184 | img.onload = () => { 185 | // Instead of drawing the image here, store it in the array 186 | images[i] = img; 187 | resolve(); 188 | }; 189 | img.onerror = reject; 190 | 191 | img.src = "data:image/png;base64," + base64ImageString; 192 | }); 193 | }); 194 | 195 | promises.push(promise); 196 | } 197 | 198 | await Promise.all(promises); 199 | // Now draw the images in order 200 | for (let i = 0; i < images.length; i++) { 201 | if (images[i]) { // Check if the image was successfully loaded 202 | ctx.drawImage(images[i], 0, 0); 203 | } 204 | } 205 | return baseImg.toDataURL(); 206 | } 207 | 208 | // Parse the command-line arguments as JSON 209 | var obj = JSON.parse(process.argv[2]); 210 | 211 | // adjust the dimensions of the image. In this case is set to 32x32 212 | createImage(obj.a, obj.t_ins).then(data => { 213 | // Split the data from the prefix 214 | let [prefix, base64Data] = data.split(","); 215 | 216 | // Convert the base64 string into bytes 217 | let imgBytes = Buffer.from(base64Data, 'base64'); 218 | console.log('base64:', base64Data) 219 | // Compute the SHA256 hash of the bytes 220 | let hash = crypto.createHash('sha256'); 221 | hash.update(imgBytes); 222 | 223 | let hashHex = hash.digest('hex'); 224 | console.log('*********************') 225 | console.log('hash:', hashHex) 226 | }).catch(error => { 227 | console.error(error); 228 | }); 229 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Generative BRC-721 2 | 3 | > ***TLDR**: This proposal introduces the Generative BRC-721 standard, a solution to optimize block space usage in the Bitcoin ordinals ecosystem, accommodating more creators and fostering innovation. The standard utilizes a "deploy" operation to create a Generative BRC-721 collection with unique traits stored on-chain. A "mint" operation then generates Non-Fungible Ordinals, referencing the traits from the deploy operation. This process cuts down block space usage between 50% and 90%. The impact of the proposed standard was demonstrated through a case study with a Generative BRC-721 collection called "OrdiBots," showing a block space reduction of 55%. Front-ends will need to adapt to recreate and display images from the mint inscription text data. This proposed standard lays the groundwork for efficient, decentralized innovation in the Bitcoin blockchain.* 4 | 5 | This initiative seeks to spark more conversations around the Non-Fungible standard within the Bitcoin ordinals ecosystem. It aims to enhance the efficiency of launching Image Ordinals Collections, similar to the creation of fungible tokens through the BRC-20 standard. 6 | 7 | **Dune Dashboard Demo:** [Generative BRC-721 (WIP)](https://dune.com/j543/generative-brc-721) 8 | This Dune Analytics dashboard currently serves as a tool to monitor the minting activity of specific Generative BRC-721 collections. Please note that it may require further refinements to fully meet the needs of users. 9 | 10 | ![](./assets/gen-brc721-dune.png) 11 | 12 | ## Context 13 | 14 | With Bitcoin network fees surging and settling at a new higher equilibrium, an influx of creators is joining the space. This trend is increasing demand for Bitcoin block space, expected to rise even further in the near future. To keep the door wide open for creators to launch their innovative ideas on the Bitcoin blockchain, we must optimize the current standard for launching Image Ordinals Collections. 15 | 16 | ## Idea 17 | 18 | We propose a new standard for launching Non-Fungible Generative Ordinals collections. This standard can conserve all on-chain resources while achieving a 50% to 90% optimization of the block space. The process includes three main operations: 19 | 20 | - Create a Generative BRC-721 collection with the deploy operation 21 | - Mint a Non-Fungible Ordinal of the collection with the mint operation 22 | - Transferring the Non-Fungible Ordinal as a standard ordinal inscription. 23 | 24 | All these processes can be conducted without the need for an external indexer, provided that the collection creators release the official list of inscriptions of their collections, as currently required. 25 | 26 | ## Operations 27 | 28 | ### Deploy Generative BRC-721 29 | 30 | The Deploy operation is a JSON/Text inscription that contains the general information of the collection, and the base64 encoded data of the traits composing the collection. The unique images of the traits used to create the Non-Fungible Ordinals are stored on-chain in this inscription. The inscription serves as the reference and the definitive source of the traits. 31 | 32 | Note: It is also possible to create multiple deploy inscription for the same collection, that each will store a set of different traits. 33 | 34 | *For demonstration purposes, we're using the OrdiBots collection* 35 | *Example of a deployed operation inscription: [Ord.io](https://www.ord.io/8326719)* 36 | 37 | ```javascript 38 | { 39 | "p": "gen-brc-721", 40 | "op": "deploy", 41 | "slug": "ordibots", 42 | "name": "OrdiBots", 43 | "supply": 1000, 44 | "trait_types": [ 45 | "background", 46 | "accessories", 47 | "body", 48 | "belly", 49 | "face" 50 | ], 51 | "dim": [32,32], 52 | "traits": { 53 | "background": { 54 | "blue": { 55 | "name": "Blue", 56 | "base64": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA1BMVEVkhZa3PARZAAAAC0lEQVR4AWMY5AAAAKAAAVQqnscAAAAASUVORK5CYII=" 57 | }, 58 | ... // more backgrounds 59 | }, 60 | "accessories": { 61 | "antenna": { 62 | "name": "Antenna", 63 | "base64": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAKUlEQVRYCe3BsQ0AIADDsOT/o8sJLEgssSHJhTpg4oDxmzKSJEmS5KEDUlIFA6L+DvwAAAAASUVORK5CYII=" 64 | }, 65 | ... // more accessories 66 | }, 67 | ... // other traits 68 | } 69 | } 70 | ``` 71 | 72 | | Key | Required | Description | 73 | | ----------- | -------- | ------------------------------------------------------------ | 74 | | p | YES | Protocol: Helps other systems identify and process gen-brc-721 events | 75 | | op | YES | Operation: Type of event (Deploy, Mint) | 76 | | slug | YES | Slug: Identifier of the collection. Not enforced if no indexer implemented | 77 | | name | NO | Name: Human readable name of the collection | 78 | | supply | NO | Supply: Supply of the collection. Not enforced if no indexer implemented | 79 | | trait_types | YES | Trait Types: This is an array which dictates the sequence in which the traits ought to be rendered. | 80 | | dim | YES | Dimensions: An array representing the dimensions (width and height) of the trait and final images in pixels, defined as [width, height]. | 81 | | traits | YES | Traits: Object containing the unique traits of teh collection. Composed as: {trait type: {trait key: {name, base64 image encoded}}} | 82 | 83 | 84 | 85 | ### Mint Generative BRC-721 86 | 87 | The Mint operation utilizes a JSON/Text inscription that encapsulates information about the actual Non-Fungible Ordinal being minted and the references to the Deploy inscription(s). The aim is to store the values of the attributes that generate the image, the hash of the final image, and the references of the collection Deploy inscription(s) on-chain. This approach allows anyone to recreate the image using on-chain inscribed data. 88 | 89 | *For demonstration purposes, we're using the OrdiBots collection* 90 | *Example of a mint operation inscription:* [Ord.io](https://www.ord.io/8400075) 91 | 92 | ```javascript 93 | { 94 | "p":"gen-brc-721", 95 | "op":"mint", 96 | "s":"ordibots", 97 | "t_ins":[ 98 | "b7205d40f3b1b1486567f0d6e53ff2812983db4c03ad7d3606812cd150c64802i0" 99 | ], 100 | "h":"aa0d33b748e0177528a910a56a61c47bee2ba9b69749228d6520049c0fea3f4f", 101 | "id":"554", 102 | "a":[ 103 | [0,"bitcoin-orange"], 104 | [0,"rainbow"], 105 | [0,"black-and-white-triangular"], 106 | [0,"square"], 107 | [0,"happy"] 108 | ] 109 | } 110 | ``` 111 | 112 | | Key | Required | Description | 113 | | ----- | ---------- | ------------------------------------------------------------ | 114 | | p | YES | Protocol: Helps other systems identify and process gen-brc-721 events | 115 | | op | YES | Operation: Type of event (Deploy, Mint) | 116 | | s | YES | Slug: Identifier of the collection. Not enforced if no indexer implemented | 117 | | t_ins | YES | Traits (Deploy) Inscription: Array containing the inscription ID(s) of the deploy inscription(s) | 118 | | h | ~~YES~~ NO | Hash: This refers to the SHA256 output of the generated image. It's an optional element; collection creators have the flexibility to decide if they want to include this additional security check on their collections. Opting not to use the hash can enhance the efficiency of the inscription process. | 119 | | id | ~~NO~~ YES | Token ID: Unique identifier for each Non-Fungible Ordinal within the collection. Essential for tracking and distinguishing individual NFOs. | 120 | | a | YES | Attributes: This is an array that carries the attribute values of this specific Non-Fungible Ordinal. Each array element is structured as follows: [inscription_index, traits_value].
Here, the inscription_index represents the deploy inscription containing the base64 data of the corresponding trait, and traits_value denotes the actual value of the specific trait. The sequence of elements in the "a" array should correspond with the "trait_types" key ordering from the deploy inscription.
As an example, the ordering in this case would be: (1) background = bitcoin-orange; (2) accessories = rainbow; (3) body = black-and-white-triangular; (4) belly = square; (5) face = happy. | 121 | 122 | ## Impact 123 | 124 | Implementing the Generative BRC-721 standard will enhance the efficiency of Bitcoin block space utilization. As the unique traits' images are inscribed just once in the deploy transaction, the assets are composed of a text file referencing these traits. Anyone can then recreate the image using the on-chain deploy inscription and verify the results with the SHA256 output. 125 | 126 | ### Case Study: OrdiBots 127 | 128 | To demonstrate the implementation of this proposed standard, we launched a demo Generative BRC-721 collection called OrdiBots. This collection of 1,000 ordinals, composed of 26 different traits, showed a 55% reduction in block space with the new standard. This result indicates a potential for even greater efficiency with more complex traits collections. 129 | 130 | The 1,000 images combined have a total size of around 663kb. At the current network fee of around 30 sats/vB, the cost to inscribe the whole collection is about 0.293BTC ($7,850 at current price). By implementing the Generative BRC-721 standard, we can reduce the size of the whole collection to 294kb (10kb + 284kb), thus having a total expected reduction of about 55% of block space. This can be considered a lower threshold, since OrdiBots is already a very light collection, and we can expect greater efficiency with collection generated by more complex traits. 131 | 132 | - Deploy inscription: https://www.ord.io/8326719 (10kb) 133 | - All possible assets inscription file: [ordibots-assets.json](https://luminex-public.s3.eu-west-1.amazonaws.com/collections/ordibots/ordibots-assets.json) (284kb) 134 | - Example Mint inscription: https://www.ord.io/8400075 (344 bytes) 135 | 136 | ![image-20230521234811232](./assets/ordibots-sample.png) 137 | 138 | ### Front-ends 139 | 140 | Should this standard become adopted by a wide array of collections and creators, front-end interfaces will need to adjust to display the actual image generated by the mint inscription, rather than the text data. This can be accomplished seamlessly by scanning user text inscriptions for a "gen-brc-721" inscription. The image can then be regenerated using exclusively on-chain data, and subsequently stored within their system infrastructure, in much the same way as it is currently done. 141 | 142 | Indeed, most ordinal platforms do not query the blockchain every time an image inscription needs to be displayed to users. Instead, they typically store these images within their own databases for convenience and efficiency. Implementing this standard, thus, shouldn't pose significant changes to the prevalent methodology. 143 | 144 | ### Re-create Onchain Images 145 | 146 | To reconstruct images from a deploy inscription, we can employ a simple script as detailed below. This script will not only generate the base64 encoded image but also its corresponding hash, taking as input the mint operation format described earlier. 147 | 148 | However, it's crucial to note that this script serves as an illustrative example and might not cover all scenarios comprehensively at this point. 149 | 150 | ```javascript 151 | const fetch = require('node-fetch'); 152 | const { createCanvas, Image } = require('canvas'); 153 | const crypto = require('crypto'); 154 | 155 | async function createImage(attributes, t_ins) { 156 | let baseImg; 157 | let ctx; 158 | 159 | let promises = []; 160 | let images = new Array(attributes.length); 161 | 162 | for (let i = 0; i < attributes.length; i++) { 163 | let attribute = attributes[i]; 164 | let inscriptionIndex = attribute[0]; 165 | let traitValue = attribute[1]; 166 | 167 | let traitsInscriptionId = t_ins[inscriptionIndex]; 168 | 169 | let promise = fetch('https://ordinals.com/content/' + traitsInscriptionId) 170 | .then(res => res.json()) 171 | .then(data => { 172 | // Map the index of the attribute to the corresponding trait_type 173 | let traitType = data.trait_types[i]; 174 | 175 | let base64ImageString = data.traits[traitType][traitValue]['base64']; 176 | 177 | let img = new Image(); 178 | let [x_dim, y_dim] = data.dim || [32, 32]; // Default to [32, 32] if 'dim' is not defined 179 | 180 | baseImg = createCanvas(x_dim, y_dim); 181 | ctx = baseImg.getContext('2d'); 182 | 183 | return new Promise((resolve, reject) => { 184 | img.onload = () => { 185 | // Instead of drawing the image here, store it in the array 186 | images[i] = img; 187 | resolve(); 188 | }; 189 | img.onerror = reject; 190 | 191 | img.src = "data:image/png;base64," + base64ImageString; 192 | }); 193 | }); 194 | 195 | promises.push(promise); 196 | } 197 | 198 | await Promise.all(promises); 199 | // Now draw the images in order 200 | for (let i = 0; i < images.length; i++) { 201 | if (images[i]) { // Check if the image was successfully loaded 202 | ctx.drawImage(images[i], 0, 0); 203 | } 204 | } 205 | return baseImg.toDataURL(); 206 | } 207 | 208 | // Parse the command-line arguments as JSON 209 | var obj = JSON.parse(process.argv[2]); 210 | 211 | // adjust the dimensions of the image. In this case is set to 32x32 212 | createImage(obj.a, obj.t_ins).then(data => { 213 | // Split the data from the prefix 214 | let [prefix, base64Data] = data.split(","); 215 | 216 | // Convert the base64 string into bytes 217 | let imgBytes = Buffer.from(base64Data, 'base64'); 218 | console.log('base64:', base64Data) 219 | // Compute the SHA256 hash of the bytes 220 | let hash = crypto.createHash('sha256'); 221 | hash.update(imgBytes); 222 | 223 | let hashHex = hash.digest('hex'); 224 | console.log('*********************') 225 | console.log('hash:', hashHex) 226 | }).catch(error => { 227 | console.error(error); 228 | }); 229 | ``` 230 | 231 | -------------------------------------------------------------------------------- /assets/gen-brc721-dune.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerryfane/generative-brc-721/756de20bc605b5097d1c277e25a5a4e0ba3a30b8/assets/gen-brc721-dune.png -------------------------------------------------------------------------------- /assets/ordibots-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerryfane/generative-brc-721/756de20bc605b5097d1c277e25a5a4e0ba3a30b8/assets/ordibots-sample.png --------------------------------------------------------------------------------