Skip to content Skip to sidebar Skip to footer

Cara Membuat Ribuan NFT Cryptopunks dengan Nodejs Terbaru

Cara Membuat Ribuan NFT Cryptopunks Nodejs Terbaru


Cara Membuat Ribuan NFT Cryptopunks Nodejs Terbaru - CryptoPunks adalah salah satu proyek NFT paling populer di luar sana. Dan sekarang, mereka menjual jutaan dolar. Ya aku tahu! Mengejutkan! Hanya ada 10.000 anak punk yang unik. Masing-masing dari mereka memiliki seperangkat atribut yang membuat mereka istimewa dan menonjol dari yang lain.

Jenis dan Atribut Cryptopunk

Tipe Punk

  1. Asing
  2. Kera
  3. zombie
  4. Perempuan
  5. Pria

Atribut

Ada sekitar 89 atribut yang tersedia untuk setiap tipe punk.

punk attributes

Jumlah Atribut

Setiap punk tidak boleh memiliki satu pun atau hingga 7 atribut sekaligus.

Dari materi yang diberikan, kami berpotensi membuat lebih dari 800.000 nfts cryptopunk.


Mari kesampingkan semuanya dan tulis sedikit aplikasi baris perintah Javascript untuk menghasilkan sekelompok bajingan ini. Selain itu, kita akan mendapatkan kesempatan untuk menyelesaikan tantangan "produk kartesius dari beberapa array" dalam Javascript.

Pengaturan

Silakan unduh semua lapisan sifat dan gambar punk di sini .

Struktur folder:

Folder structure

Kami akan menggunakan paket node-canvas untuk menggambar gambar dalam proyek ini. Harap pastikan bahwa Anda mengikuti petunjuk penginstalan jika Anda mengalami masalah. Lebih banyak bantuan dapat ditemukan di sini .

npm install canvas

Tambahkan variabel impor dan konfigurasi


const  fs = require("fs");

const { createCanvas, loadImage } = require("canvas");

const  console = require("console");

const  imageFormat = {

    width: 24,

    height: 24

};

// initialize canvas and context in 2d
const  canvas = createCanvas(imageFormat.width, imageFormat.height);

const  ctx = canvas.getContext("2d");

// some folder directories that we will use throughout the script
const  dir = {

    traitTypes  : `./layers/trait_types`,

    outputs: `./outputs`,

    background: `./layers/background`,

}

// we will update this total punks in the following steps.
let  totalOutputs = 0;

// set the order of layers that you want to print first
const  priorities = ['punks','top','beard'];

Segarkan fungsi keluaran

  • Buat fungsi untuk menghapus data keluaran untuk kita. Kemudian ia membuat ulang folder output bersama dengan metadata baru dan folder punk di dalamnya.
const  recreateOutputsDir = () => {

    if (fs.existsSync(dir.outputs)) {

        fs.rmdirSync(dir.outputs, { recursive: true });

    }

    fs.mkdirSync(dir.outputs);

    fs.mkdirSync(`${dir.outputs}/metadata`);

    fs.mkdirSync(`${dir.outputs}/punks`);

};

 

Hitung semua hasil yang mungkin

Pada langkah ini, kita akan mengetahui cara menghasilkan kombinasi dari beberapa larik lapisan sifat. Sekarang mari kita turun ke bisnis dan bersenang-senang. Jangan salin dan tempel kodenya dulu.

Ada banyak cara untuk mengimplementasikan apa yang disebut fungsi sederhana ini.

  • Pertama adalah menggunakan fungsi Reduce dan FlatMap yang diperkenalkan di ECMAScript 2019. Ini adalah opsi terpendek dan paling mudah untuk dipahami.


const cartesian = (...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())));

 

  • Opsi umum lainnya adalah menggunakan fungsi Rekursi


const cartesian = (arr) => {
  if (arr.length == 1) {
    return arr[0];
  } else {
    var result = [];
    var allCasesOfRest = cartesian (arr.slice(1)); // recur with the rest of array
    for (var i = 0; i < allCasesOfRest.length; i++) {
      for (var j = 0; j < arr[0].length; j++) {
        var childArray = [].concat(arr[0][j], allCasesOfRest[i])
        result.push(childArray);
      }
    }
    return result;
  }
}

Sebagian besar opsi memerlukan jumlah rekursi yang tidak masuk akal, atau loop yang sangat bersarang atau untuk menyimpan larik permutasi dalam memori. Ini akan menjadi sangat berantakan ketika kita menjalankannya terhadap ratusan lapisan sifat yang berbeda. Ini akan menghabiskan semua memori perangkat Anda dan akhirnya membuat PC/laptop Anda crash. Saya membuat PC saya digoreng beberapa kali. Jadi jangan jadi aku.

  • Alih-alih menggunakan fungsi rekursi atau loop bersarang, kita dapat membuat fungsi untuk menghitung total hasil yang mungkin yang merupakan produk dari semua panjang array.

 

var permsCount = arraysToCombine[0].length;
for(var i = 1; i < arraysToCombine.length; i++) {
    permsCount *= arraysToCombine[i].length;
}
  • Selanjutnya, kita akan mengatur nilai pembagi untuk menyelesaikan perbedaan ukuran array



for (var i = arraysToCombine.length - 1; i >= 0; i--) {
      divisors[i] = divisors[i + 1] ? divisors[i + 1] * arraysToCombine[i + 1].length : 1;
   }

 

Tambahkan fungsi lain untuk mengembalikan permutasi unik antara indeks '0' dan 'numPerms - 1' dengan menghitung indeks yang diperlukan untuk mengambil karakternya, berdasarkan 'n'


const getPermutation = (n, arraysToCombine) => {

    var  result = [],

    curArray;

    for (var  i = 0; i < arraysToCombine.length; i++) {

        curArray = arraysToCombine[i];

        result.push(curArray[Math.floor(n / divisors[i]) % curArray.length]);

    }

    return result;
}

 

Selanjutnya kita akan memanggil fungsi getPermutation (n) menggunakan for loop


 for(var i = 0; i < numPerms; i++) {
        combinations.push(getPermutation(i, arraysToCombine));
    }

 

Script lengkap yang kita butuhkan.


const  allPossibleCases = (arraysToCombine) => {

    const  divisors = [];

    let  permsCount = 1;

    for (let  i = arraysToCombine.length - 1; i >= 0; i--) {

        divisors[i] = divisors[i + 1] ? divisors[i + 1] * arraysToCombine[i + 1].length : 1;

        permsCount *= (arraysToCombine[i].length || 1);

    }

    totalOutputs = permsCount;

    const  getCombination = (n, arrays, divisors) =>  arrays.reduce((acc, arr, i) => {

        acc.push(arr[Math.floor(n / divisors[i]) % arr.length]);

        return  acc;

    }, []);



    const  combinations = [];

    for (let  i = 0; i < permsCount; i++) {

        combinations.push(getCombination(i, arraysToCombine, divisors));

    }

    return  combinations;

};

Menurut tes kinerja cepat ini, versi terakhir benar-benar mengungguli yang lain. Tampak menjanjikan bagi saya!

performance test

Buat fungsi gambar gambar


const  drawImage= async (traitTypes, background, index) => {

    // draw background

    const  backgroundIm = await  loadImage(`${dir.background}/${background}`);

    ctx.drawImage(backgroundIm,0,0,imageFormat.width,imageFormat.height);



    //'N/A': means that this punk doesn't have this trait type

    const  drawableTraits = traitTypes.filter(x=>  x.value !== 'N/A')

    // draw all the trait layers for this one punk

    for (let  index = 0; index < drawableTraits.length; index++) {

        const  val = drawableTraits[index];

        const  image = await  loadImage(`${dir.traitTypes}/${val.trait_type}/${val.value}`);

        ctx.drawImage(image,0,0,imageFormat.width,imageFormat.height);

    }

    console.log(`Progress: ${index}/ ${totalOutputs}`)

    // save metadata
    fs.writeFileSync(

        `${dir.outputs}/metadata/${index}.json`,

            JSON.stringify({

            name: `punk ${index}`,

            attributes: drawableTraits

        }),
        function(err){
            if(err) throw  err;
        })

        // save image as png file

        fs.writeFileSync(
            `${dir.outputs}/punks/${index}.png`,
            canvas.toBuffer("image/png")
        );

}

Buat fungsi utama


const  main = async () => {

const  traitTypesDir = dir.traitTypes;

// register all the traits 

const  types = fs.readdirSync(traitTypesDir);

// set all prioritised layers which will be drawn first. for eg: punk type, hair and then hat. You can set these values in the priorities array in line 21
const  traitTypes = priorities.concat(types.filter(x=> !priorities.includes(x)))

                                .map(traitType  => ( 
                                    fs.readdirSync(`${traitTypesDir}/${traitType}/`)

                                .map(value=> { 
                                    return {trait_type: traitType, value: value}

                                    }).concat({trait_type: traitType, value: 'N/A'})
                                ));

// register all the backgrounds
const  backgrounds = fs.readdirSync(dir.background);

// trait type avail for each punk

const  combinations = allPossibleCases(traitTypes)

    for (var  n = 0; n < combinations.length; n++) {

        const  randomBackground = backgrounds[Math.floor(Math.random() * backgrounds.length)]

        await  drawImage(combinations[n] , randomBackground, n);
    }

Panggil register direktori keluaran dan fungsi utama


 (() => {

    recreateOutputsDir();

    main();

})();

 

Jalankan index.js

Buka cmd/powershell dan jalankan


node index.js

 

Atau


npm build

 

Ta-da. Mari jalankan aplikasi dan buat semua nft untuk kita.

Sumber daya

  1. Kode sumber: victorquanlam/cryptopunk-nft-generator)
  2. Stackoverflow: Produk Cartesian dari nilai array

Silakan tinggalkan suka jika Anda menyukai posting ini.

 

Post a Comment for "Cara Membuat Ribuan NFT Cryptopunks dengan Nodejs Terbaru"