Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avalanche Ranker #1

Open
ericlam1114 opened this issue Dec 26, 2021 · 14 comments
Open

Avalanche Ranker #1

ericlam1114 opened this issue Dec 26, 2021 · 14 comments

Comments

@ericlam1114
Copy link

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

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

@IAmJaysWay
Copy link
Owner

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
Copy link
Author

ericlam1114 commented Dec 30, 2021

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
Copy link
Author

ericlam1114 commented Dec 31, 2021

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
Copy link
Author

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
Copy link
Owner

Hey @ericlam1114,

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

@IAmJaysWay
Copy link
Owner

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
Copy link
Owner

@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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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

@sudhanshucrypto
Copy link

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
Copy link
Owner

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

@IAmJaysWay
Copy link
Owner

@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
Copy link
Author

ericlam1114 commented Jan 7, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants