Skip to content

Commit

Permalink
Merge pull request #19 from codeSTACKr/fix-uploads-mints
Browse files Browse the repository at this point in the history
Fix uploads mints
  • Loading branch information
codeSTACKr authored Jan 3, 2022
2 parents 1745dd5 + e537394 commit 85549b0
Show file tree
Hide file tree
Showing 12 changed files with 296 additions and 131 deletions.
12 changes: 3 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
# Source Code from "How To Create An ENTIRE NFT Collection (10,000+) & MINT In Under 1 Hour Without Coding Knowledge"

## Multiple Active Branches

- [main](https://github.com/codeSTACKr/video-source-code-create-nft-collection/tree/main) = Source code from the video
- [fix-uploads-mints](https://github.com/codeSTACKr/video-source-code-create-nft-collection/tree/fix-uploads-mints) = Updated to fix issues uploading files, metadata, and minting explained [below](#quota-limit-reached-or-too-many-requests-errors).

[Video Link](https://youtu.be/AaCgydeMu64)
Video: [How To Create An ENTIRE NFT Collection (10,000+) & MINT In Under 1 Hour Without Coding Knowledge](https://youtu.be/AaCgydeMu64)

Base code is from [hashlips_art_engine](https://github.com/HashLips/hashlips_art_engine)

Expand Down Expand Up @@ -44,17 +39,16 @@ Ensure that your layer names in the `config.js` file match exactly to your layer

### "Quota Limit Reached" or "Too many requests" errors

There have been some changes made to the code in the [fix-uploads-mints](https://github.com/codeSTACKr/video-source-code-create-nft-collection/tree/fix-uploads-mints) branch resulting from some errors when uploading files, metadata, and minting using NFTPort. Depending on your plan, Free vs Community, there are rate limits.
There have been some changes made to the code from the original video resulting from some errors when uploading files, metadata, and minting using NFTPort. Depending on your plan, Free vs Community, there are rate limits.

To fix these issues, I've updated the code to include a timeout that will allow the files to be uploaded at a slower rate, instead of all at once, eliminating these errors.

**To use this code:**

- Clone this repo or download the zip file.
- Clone this repo or download the latest release zip file.
- Unzip, if needed, and open the folder in VS Code.
- From the terminal type:
- `npm install`
- Ensure you are on the `fix-uploads-mints` branch if you cloned the repo.
- Copy your image layers into the `layers` folder.
- Use the `src/config.js` file to set up your layers and NFT information.

Expand Down
Binary file removed banner.png
Binary file not shown.
Binary file added layers/Background/Blue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added layers/Background/Orange.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added layers/Background/Yellow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed logo.png
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "10k-collection-video",
"version": "0.1.0",
"version": "1.0.0",
"description": "Source code from \"How To Create An ENTIRE NFT Collection (10,000+) & MINT In Under 1 Hour Without Coding Knowledge\" video.",
"main": "index.js",
"bin": "index.js",
Expand Down
2 changes: 1 addition & 1 deletion src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const background = {
};

const extraMetadata = {
external_url: "https://codecats.xyz",
external_url: "https://codecats.xyz", // Replace with your website or remove this line if you do not have one.
};

const rarityDelimiter = "#";
Expand Down
3 changes: 1 addition & 2 deletions utils/nftport/genericMetas.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const path = require("path");
const isLocal = typeof process.pkg === "undefined";
const basePath = isLocal ? process.cwd() : path.dirname(process.execPath);
const basePath = process.cwd();
const fs = require("fs");
const buildDir = path.join(basePath, "/build");

Expand Down
150 changes: 102 additions & 48 deletions utils/nftport/mint.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,113 @@
const fetch = require("node-fetch");
const path = require("path");
const isLocal = typeof process.pkg === "undefined";
const basePath = isLocal ? process.cwd() : path.dirname(process.execPath);
const basePath = process.cwd();
const fs = require("fs");

const AUTH = 'YOUR API KEY HERE';
const CONTRACT_ADDRESS = 'YOUR CONTRACT ADDRESS HERE';
const MINT_TO_ADDRESS = 'YOUR WALLET ADDRESS HERE';
const CHAIN = 'rinkeby';
const TIMEOUT = 1000; // Milliseconds. This a timeout for errors only. If there is an error, it will wait then try again. 5000 = 5 seconds.

const ipfsMetas = JSON.parse(
fs.readFileSync(`${basePath}/build/json/_ipfsMetas.json`)
);

fs.writeFileSync(`${basePath}/build/minted.json`, "");
const writter = fs.createWriteStream(`${basePath}/build/minted.json`, {
flags: "a",
});
writter.write("[");
nftCount = ipfsMetas.length;

ipfsMetas.forEach((meta) => {
let url = "https://api.nftport.xyz/v0/mints/customizable";

const mintInfo = {
chain: CHAIN,
contract_address: CONTRACT_ADDRESS,
metadata_uri: meta.metadata_uri,
mint_to_address: MINT_TO_ADDRESS,
token_id: meta.custom_fields.edition,
};

let options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: AUTH,
},
body: JSON.stringify(mintInfo),
};

fetch(url, options)
.then((res) => res.json())
.then((json) => {
writter.write(JSON.stringify(json, null, 2));
nftCount--;

if (nftCount === 0) {
writter.write("]");
writter.end();
} else {
writter.write(",\n");
if (!fs.existsSync(path.join(`${basePath}/build`, "/minted"))) {
fs.mkdirSync(path.join(`${basePath}/build`, "minted"));
}

async function main() {
const ipfsMetas = JSON.parse(
fs.readFileSync(`${basePath}/build/ipfsMetas/_ipfsMetas.json`)
);

for (const meta of ipfsMetas) {
const mintFile = `${basePath}/build/minted/${meta.custom_fields.edition}.json`;

try {
fs.accessSync(mintFile);
const mintedFile = fs.readFileSync(mintFile)
if(mintedFile.length > 0) {
const mintedMeta = JSON.parse(mintedFile)
if(mintedMeta.mintData.response !== "OK") throw 'not minted'
}
console.log(`${meta.name} already minted`);
} catch(err) {
try {
let mintData = await fetchWithRetry(meta)
const combinedData = {
metaData: meta,
mintData: mintData
}
writeMintData(meta.custom_fields.edition, combinedData)
console.log(`Minted: ${meta.name}!`);
} catch(err) {
console.log(`Catch: ${err}`)
}
}
}
}

main();

function timer(ms) {
return new Promise(res => setTimeout(res, ms));
}

async function fetchWithRetry(meta) {
await timer(TIMEOUT);
return new Promise((resolve, reject) => {
const fetch_retry = (_meta) => {
let url = "https://api.nftport.xyz/v0/mints/customizable";

const mintInfo = {
chain: CHAIN,
contract_address: CONTRACT_ADDRESS,
metadata_uri: _meta.metadata_uri,
mint_to_address: MINT_TO_ADDRESS,
token_id: _meta.custom_fields.edition,
};

let options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: AUTH,
},
body: JSON.stringify(mintInfo),
};

return fetch(url, options).then(async (res) => {
const status = res.status;

if(status === 200) {
return res.json();
}
else {
console.error(`ERROR STATUS: ${status}`)
console.log('Retrying')
await timer(TIMEOUT)
fetch_retry(_meta)
}
})
.then(async (json) => {
if(json.response === "OK"){
return resolve(json);
} else {
console.error(`NOK: ${json.error}`)
console.log('Retrying')
await timer(TIMEOUT)
fetch_retry(_meta)
}
})
.catch(async (error) => {
console.error(`CATCH ERROR: ${error}`)
console.log('Retrying')
await timer(TIMEOUT)
fetch_retry(_meta)
});
}
return fetch_retry(meta);
});
}

console.log(`Minted: ${json.transaction_external_url}`);
})
.catch((err) => console.error("error:" + err));
});
const writeMintData = (_edition, _data) => {
fs.writeFileSync(`${basePath}/build/minted/${_edition}.json`, JSON.stringify(_data, null, 2));
};
113 changes: 84 additions & 29 deletions utils/nftport/uploadFiles.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,97 @@
const FormData = require("form-data");
const fetch = require("node-fetch");

const path = require("path");
const isLocal = typeof process.pkg === "undefined";
const basePath = isLocal ? process.cwd() : path.dirname(process.execPath);
const basePath = process.cwd();
const fs = require("fs");

const AUTH = 'YOUR API KEY HERE';
const TIMEOUT = 1000; // Milliseconds. Extend this if needed to wait for each upload. 1000 = 1 second.

fs.readdirSync(`${basePath}/build/images`).forEach((file) => {
const formData = new FormData();
const fileStream = fs.createReadStream(`${basePath}/build/images/${file}`);
formData.append("file", fileStream);

let url = "https://api.nftport.xyz/v0/files";
let options = {
method: "POST",
headers: {
Authorization: AUTH,
},
body: formData,
};

fetch(url, options)
.then((res) => res.json())
.then((json) => {
const fileName = path.parse(json.file_name).name;
let rawdata = fs.readFileSync(`${basePath}/build/json/${fileName}.json`);
let metaData = JSON.parse(rawdata);

metaData.file_url = json.ipfs_url;
const allMetadata = [];

async function main() {
const files = fs.readdirSync(`${basePath}/build/images`);
files.sort(function(a, b){
return a.split(".")[0] - b.split(".")[0];
});
for (const file of files) {
const fileName = path.parse(file).name;
let jsonFile = fs.readFileSync(`${basePath}/build/json/${fileName}.json`);
let metaData = JSON.parse(jsonFile);
if(!metaData.file_url.includes('https://')) {
const response = await fetchWithRetry(file);
metaData.file_url = response.ipfs_url;

fs.writeFileSync(
`${basePath}/build/json/${fileName}.json`,
JSON.stringify(metaData, null, 2)
);
console.log(`${response.file_name} uploaded & ${fileName}.json updated!`);
} else {
console.log(`${fileName} already uploaded.`);
}

allMetadata.push(metaData);
}
fs.writeFileSync(
`${basePath}/build/json/_metadata.json`,
JSON.stringify(allMetadata, null, 2)
);
}

main();

function timer(ms) {
return new Promise(res => setTimeout(res, ms));
}

async function fetchWithRetry(file) {
await timer(TIMEOUT)
return new Promise((resolve, reject) => {
const fetch_retry = (_file) => {
const formData = new FormData();
const fileStream = fs.createReadStream(`${basePath}/build/images/${_file}`);
formData.append("file", fileStream);

let url = "https://api.nftport.xyz/v0/files";
let options = {
method: "POST",
headers: {
Authorization: AUTH,
},
body: formData,
};

return fetch(url, options).then(async (res) => {
const status = res.status;

console.log(`${json.file_name} uploaded & ${fileName}.json updated!`);
})
.catch((err) => console.error("error:" + err));
});
if(status === 200) {
return res.json();
}
else {
console.error(`ERROR STATUS: ${status}`)
console.log('Retrying')
await timer(TIMEOUT)
fetch_retry(_file)
}
})
.then(async (json) => {
if(json.response === "OK"){
return resolve(json);
} else {
console.error(`NOK: ${json.error}`)
console.log('Retrying')
await timer(TIMEOUT)
fetch_retry(_file)
}
})
.catch(async (error) => {
console.error(`CATCH ERROR: ${error}`)
console.log('Retrying')
await timer(TIMEOUT)
fetch_retry(_file)
});
}
return fetch_retry(file);
});
}
Loading

0 comments on commit 85549b0

Please sign in to comment.