IAmJaysWay / Rarity-Ranking-NFT

Moralis Project
93 stars 79 forks source link

Avalanche Ranker #1

Open ericlam1114 opened 2 years ago

ericlam1114 commented 2 years ago

Hey. This is amazing. Thank you so much for your work.

How do we get this to work with avalanche instead of ethereum?

IAmJaysWay commented 2 years ago

Glad you like it @ericlam1114! You can check out the Moralis documentation for getting NFT collections here:

https://docs.moralis.io/moralis-server/web3-sdk/token#getalltokenids

But essentially to get NFT collections on AVAX just pass as a parameter avax chain to the getAllTokenIds call :)

ericlam1114 commented 2 years ago

Thanks for your help @IAmJaysWay

i'm trying to show this collection.

https://twitter.com/Avaxdogs?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor

this is my code...

`const Moralis = require("moralis/node"); const { timer } = require("rxjs");

const serverUrl = "https://wurgiuz7dwbk.usemoralis.com:2053/server"; //Moralis Server Url here const appId = "IqqOHWe5SsvBQkg3FC7Vn3KXZXLiQ8NI5xUULXvG"; //Moralis Server App ID here Moralis.start({ serverUrl, appId });

const resolveLink = (url) => { if (!url || !url.includes("ipfs://")) return url; return url.replace("ipfs://", "https://gateway.ipfs.io/ipfs/"); };

const collectionAddress = "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"; //Collection Address Here const collectionName = "AvalancheDogsReborn"; //CollectioonName Here

async function generateRarity() { const NFTs = await Moralis.Web3API.token.getAllTokenIds({ address: collectionAddress, chain: "0xa86a" }) console.log(NFTs);

;

const totalNum = NFTs.total; const pageSize = NFTs.page_size; console.log(totalNum); console.log(pageSize); let allNFTs = NFTs.result;

const timer = (ms) => new Promise((res) => setTimeout(res, ms));

for (let i = pageSize; i < totalNum; i = i + pageSize) { const NFTs = await Moralis.Web3API.token.getAllTokenIds({ address: collectionAddress, offset: i, chain: "0xa86a" }); allNFTs = allNFTs.concat(NFTs.result); await timer(6000); }

let metadata = allNFTs.map((e) => JSON.parse(e.metadata).attributes);

let tally = { TraitCount: {} };

for (let j = 0; j < metadata.length; j++) { let nftTraits = metadata[j].map((e) => e.trait_type); let nftValues = metadata[j].map((e) => e.value);

let numOfTraits = nftTraits.length;

if (tally.TraitCount[numOfTraits]) {
  tally.TraitCount[numOfTraits]++;
} else {
  tally.TraitCount[numOfTraits] = 1;
}

for (let i = 0; i < nftTraits.length; i++) {
  let current = nftTraits[i];
  if (tally[current]) {
    tally[current].occurences++;
  } else {
    tally[current] = { occurences: 1 };
  }

  let currentValue = nftValues[i];
  if (tally[current][currentValue]) {
    tally[current][currentValue]++;
  } else {
    tally[current][currentValue] = 1;
  }
}

}

const collectionAttributes = Object.keys(tally); let nftArr = []; for (let j = 0; j < metadata.length; j++) { let current = metadata[j]; let totalRarity = 0; for (let i = 0; i < current.length; i++) { let rarityScore = 1 / (tally[current[i].trait_type][current[i].value] / totalNum); current[i].rarityScore = rarityScore; totalRarity += rarityScore; }

let rarityScoreNumTraits =
  8 * (1 / (tally.TraitCount[Object.keys(current).length] / totalNum));
current.push({
  trait_type: "TraitCount",
  value: Object.keys(current).length,
  rarityScore: rarityScoreNumTraits,
});
totalRarity += rarityScoreNumTraits;

if (current.length < collectionAttributes.length) {
  let nftAttributes = current.map((e) => e.trait_type);
  let absent = collectionAttributes.filter(
    (e) => !nftAttributes.includes(e)
  );

  absent.forEach((type) => {
    let rarityScoreNull =
      1 / ((totalNum - tally[type].occurences) / totalNum);
    current.push({
      trait_type: type,
      value: null,
      rarityScore: rarityScoreNull,
    });
    totalRarity += rarityScoreNull;
  });
}

if (allNFTs[j]?.metadata) {
  allNFTs[j].metadata = JSON.parse(allNFTs[j].metadata);
  allNFTs[j].image = resolveLink(allNFTs[j].metadata?.image);
} else if (allNFTs[j].token_uri) {
  try {
    await fetch(allNFTs[j].token_uri)
      .then((response) => response.json())
      .then((data) => {
        allNFTs[j].image = resolveLink(data.image);
      });
  } catch (error) {
    console.log(error);
  }
}

nftArr.push({
  Attributes: current,
  Rarity: totalRarity,
  token_id: allNFTs[j].token_id,
  image: allNFTs[j].image,
});

}

nftArr.sort((a, b) => b.Rarity - a.Rarity);

for (let i = 0; i < nftArr.length; i++) { nftArr[i].Rank = i + 1; const newClass = Moralis.Object.extend(collectionName); const newObject = new newClass();

newObject.set("attributes", nftArr[i].Attributes);
newObject.set("rarity", nftArr[i].Rarity);
newObject.set("tokenId", nftArr[i].token_id);
newObject.set("rank", nftArr[i].Rank);
newObject.set("image", nftArr[i].image);

await newObject.save();
console.log(i);

} }

generateRarity();`

do you know why it's not working properly? am i using moralis wrong?

ericlam1114 commented 2 years ago

I tried this as well and it did not work.

Screen Shot 2021-12-30 at 5 11 51 PM Screen Shot 2021-12-30 at 5 13 54 PM

the screen ends up looking like this. no results

ericlam1114 commented 2 years ago

I tried using the avalanche chain code for the avax testnet too

avalanche testnet, 0xa869

that one. still nothin.

sorry for the sporadic updates. really trying to figure this out. so excited at the possibilities!!

IAmJaysWay commented 2 years ago

Hey @ericlam1114,

I opened this back up and will have a look on it today and come back to you with any updates :)

IAmJaysWay commented 2 years ago

import fetch from "node-fetch"; import Moralis from 'moralis/node.js';

const serverUrl = "";//Server URL Here const appId = "";//App ID here Moralis.start({ serverUrl, appId });

const resolveLink = (url) => { if (!url || !url.includes("ipfs://")) return url; return url.replace("ipfs://", "https://gateway.ipfs.io/ipfs/"); };

const collectionAddress = "0x2cca3a1a45c1b1036d7194cd15a981b8c2f9dee4"; //Collection Address Here const collectionName = "AvalancheDogsReborn"; //CollectioonName Here

async function generateRarity() { const NFTs = await Moralis.Web3API.token.getAllTokenIds({ address: collectionAddress, chain: "avalanche", });

let totalNum = NFTs.total;//NFTs.total; const pageSize = NFTs.page_size; console.log(totalNum); console.log(pageSize); let allNFTs = NFTs.result;

const timer = (ms) => new Promise((res) => setTimeout(res, ms));

for (let i = pageSize; i < totalNum; i = i + pageSize) { const NFTs = await Moralis.Web3API.token.getAllTokenIds({ address: collectionAddress, offset: i, chain: "avalanche", }); allNFTs = allNFTs.concat(NFTs.result); await timer(6000); console.log(i); }

let metadata = await Promise.all(allNFTs.map(async (e) => { if(e.metadata){ return JSON.parse(e.metadata).attributes; }else{ const response = await fetch(e.token_uri, {method: 'GET'}); const data = await response.json(); return data.attributes } }));

console.log(metadata);

let tally = { TraitCount: {} };

for (let j = 0; j < metadata.length; j++) { let nftTraits = metadata[j].map((e) => e.trait_type); let nftValues = metadata[j].map((e) => e.value);

let numOfTraits = nftTraits.length;

if (tally.TraitCount[numOfTraits]) {
  tally.TraitCount[numOfTraits]++;
} else {
  tally.TraitCount[numOfTraits] = 1;
}

for (let i = 0; i < nftTraits.length; i++) {
  let current = nftTraits[i];
  if (tally[current]) {
    tally[current].occurences++;
  } else {
    tally[current] = { occurences: 1 };
  }

  let currentValue = nftValues[i];
  if (tally[current][currentValue]) {
    tally[current][currentValue]++;
  } else {
    tally[current][currentValue] = 1;
  }
}

}

const collectionAttributes = Object.keys(tally); let nftArr = []; for (let j = 0; j < metadata.length; j++) { let current = metadata[j]; let totalRarity = 0; for (let i = 0; i < current.length; i++) { let rarityScore = 1 / (tally[current[i].trait_type][current[i].value] / totalNum); current[i].rarityScore = rarityScore; totalRarity += rarityScore; }

let rarityScoreNumTraits =
  8 * (1 / (tally.TraitCount[Object.keys(current).length] / totalNum));
current.push({
  trait_type: "TraitCount",
  value: Object.keys(current).length,
  rarityScore: rarityScoreNumTraits,
});
totalRarity += rarityScoreNumTraits;

if (current.length < collectionAttributes.length) {
  let nftAttributes = current.map((e) => e.trait_type);
  let absent = collectionAttributes.filter(
    (e) => !nftAttributes.includes(e)
  );

  absent.forEach((type) => {
    let rarityScoreNull =
      1 / ((totalNum - tally[type].occurences) / totalNum);
    current.push({
      trait_type: type,
      value: null,
      rarityScore: rarityScoreNull,
    });
    totalRarity += rarityScoreNull;
  });
}

if (allNFTs[j]?.metadata) {
  allNFTs[j].metadata = JSON.parse(allNFTs[j].metadata);
  allNFTs[j].image = resolveLink(allNFTs[j].metadata?.image);
} else if (allNFTs[j].token_uri) {
  try {
    await fetch(allNFTs[j].token_uri)
      .then((response) => response.json())
      .then((data) => {
        allNFTs[j].image = resolveLink(data.image);
      });
  } catch (error) {
    console.log(error);
  }
}

nftArr.push({
  Attributes: current,
  Rarity: totalRarity,
  token_id: allNFTs[j].token_id,
  image: allNFTs[j].image,
});

}

nftArr.sort((a, b) => b.Rarity - a.Rarity);

for (let i = 0; i < nftArr.length; i++) { nftArr[i].Rank = i + 1; const newClass = Moralis.Object.extend(collectionName); const newObject = new newClass();

newObject.set("attributes", nftArr[i].Attributes);
newObject.set("rarity", nftArr[i].Rarity);
newObject.set("tokenId", nftArr[i].token_id);
newObject.set("rank", nftArr[i].Rank);
newObject.set("image", nftArr[i].image);

await newObject.save();
console.log(i);

} }

generateRarity();

IAmJaysWay commented 2 years ago

@ericlam1114 this seems to work :), I think you may have had the wrong contract address for the nft collection... I also added a manual fetch of the metadata for when there is missing metadata in the web3 api call so for that to work you will have to add :

"type" = "module"

into the package.json file!

Hope this works for you

Screenshot 2022-01-03 at 13 52 18
ericlam1114 commented 2 years ago

Thank you so much for your help.

Screen Shot 2022-01-03 at 11 32 04 AM

I keep getting this error now once I load up the collection

Screen Shot 2022-01-03 at 11 31 27 AM

Should I just redownload the code from github? Not sure why this keeps crashing.

ericlam1114 commented 2 years ago

Ok I got the error to go away. Now i'm having a problem where the program just hangs when I load up the Avalanche dogs.

Screen Shot 2022-01-03 at 12 55 45 PM
ericlam1114 commented 2 years ago

Here is my code. https://github.com/ericlam1114/Rarity-Ranking-NFT

sudhanshucrypto commented 2 years ago

Hey sir it is great to build this one and everything is working nice in app but one question in rarity tools there is trait rarity ,statistical rarity , average rarity can u update repo or give the mathematical calculations to calculate these rarity score.. bcz I search but I don't get these calculations method

IAmJaysWay commented 2 years ago

@ericlam1114 when you run the generator are the NFTs being saved in your database in the AvalancheDogsReborn class?

IAmJaysWay commented 2 years ago

@Lalaji23 you can view the video on Moralis youtube channel as to how this generator calculates rarity :)https://www.youtube.com/watch?v=TXpfRRHwjak&t=1s

ericlam1114 commented 2 years ago

They don’t appear to be, no. Does my code attached previously help?

Sent from my iPhone

On Jan 7, 2022, at 3:52 AM, IAmJaysWay @.***> wrote:

 @ericlam1114 when you run the generator are the NFTs being saved in your database in the AvalancheDogsReborn class?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.