[개발] steem-punks 판매량 정보 가져오기

[스샷 - 대략 22.03.18 08시 기준 정보]

스팀 펑크에서는 graphql 을 제공합니다.

https://www.steempunks.xyz/graphql

위에서 정보를 가져와 판매량 정보를 계산할 수 있습니다 :)

( scrap.js ) - graphql 을 이용하여 1만개의 nft 정보를 가져올 수 있도록 구성합니다.

import fetch from "node-fetch";

function _getOp(id) {
  return {
    operationName: null,
    query: `{\n  getMyNFTDetail(SteempunksNFTInput: {id: ${id}}) {\n    success\n    steempunksNFT {\n      id\n      score\n      ranking\n      rarity\n      owner_account\n    }\n  }\n}\n`,
    variables: {},
  };
}

async function _call(id, url = GRAPH_URL) {
  return fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(_getOp(id)),
  })
    .then((res) => res.json())
    .then((res) =>
      res.data.getMyNFTDetail ? res.data.getMyNFTDetail.steempunksNFT : {}
    );
}

export default async function status() {
  let start = 0;
  let end = 0;
  let results = [];
  let buffer = [];

  const MAX_LOOP = 50;
  const MAX_COUNT = 9999;
  const PER_COUNT = 200;
  const SLEEP_SEC = 1000 * 1;
  for (let k = 0; k < MAX_LOOP; k++) {
    start = k * PER_COUNT;
    end = Math.min(PER_COUNT + k * PER_COUNT, MAX_COUNT);
    for (let i = start; i < end; i++) {
      buffer.push(_call(i));
    }
    await Promise.all(buffer).then((res) => results.push(...res));
    await new Promise((r) => setTimeout(r, SLEEP_SEC));
    buffer = [];
    console.log(k + 1, "/", MAX_LOOP);
  }
  return results;
}

( save.js ) - 이렇게 가져온 정보를 파일에 기록 합니다.

import fs from "fs";
import status from "./scrap.js";

status().then((res) => {
  fs.writeFileSync("./output.json", JSON.stringify(res, null, 2));
  console.log(res);
});

( print.js ) - 나름 보기 쉽게 화면에 출력 해 봅니다. ( node-canvas 를 통해 이미지로 만들면 더 좋지만 그냥 귀찮으니 pass )

import fs from "fs";
let ori = JSON.parse(fs.readFileSync("./output.json"));

let lpad = (s, len = 20, char = " ") => s.toString().padStart(len, char);
let rpad = (s, len = 20, char = " ") => s.toString().padEnd(len, char);
let print = (...s) => console.log(lpad(s[0]), ...s.slice(1));
let line = (len, char = "=") => console.log(rpad("", len, char));

line(40);
print("PACKS INFO");
line(40);

print("TOTAL PACKS : ", ori.length / 10);
let notyet = ori.filter((x) => x.owner_account == null);
print("SELL PACKS : ", (ori.length - notyet.length) / 10);
print("REMAIN PACKS : ", notyet.length / 10);

line(40);
print("NFTs MINTING INFO");
line(40);

print("NFTs : ", ori.length);

let common = ori.filter((x) => x.rarity.indexOf("C") == 0);
let rare = ori.filter((x) => x.rarity.indexOf("R") == 0);
let epic = ori.filter((x) => x.rarity.indexOf("E") == 0);
let legendary = ori.filter((x) => x.rarity.indexOf("L") == 0);

let c1 = ori.filter(
  (x) => x.rarity.indexOf("C") == 0 && x.owner_account != null
);
print(
  "COMMON NFTs : ",
  common.length - c1.length,
  "/",
  c1.length,
  "/",
  common.length
);

let r1 = ori.filter(
  (x) => x.rarity.indexOf("R") == 0 && x.owner_account != null
);
print(
  "RARE NFTs : ",
  rare.length - r1.length,
  "/",
  r1.length,
  "/",
  rare.length
);

let e1 = ori.filter(
  (x) => x.rarity.indexOf("E") == 0 && x.owner_account != null
);
print(
  "EPIC NFTs : ",
  epic.length - e1.length,
  "/",
  e1.length,
  "/",
  epic.length
);

let l1 = ori.filter(
  (x) => x.rarity.indexOf("L") == 0 && x.owner_account != null
);
print(
  "LEGENDARY NFTs : ",
  legendary.length - l1.length,
  "/",
  l1.length,
  "/",
  legendary.length
);

line(40);
print("BUY PACKS TOP 10");
line(40);

// let EXCEPT_IDS = ["null", "happyberrysboy", "donekim", "realmankwon"];
let EXCEPT_IDS = ["null"];
let buy_buffer = {};
for (let r of ori) {
  buy_buffer[r.owner_account] = buy_buffer[r.owner_account]
    ? buy_buffer[r.owner_account] + 1
    : 1;
}
let buy_buffer2 = [];
for (let kv of Object.entries(buy_buffer)) {
  buy_buffer2.push({ id: kv[0], nfts: kv[1] });
}
buy_buffer2 = buy_buffer2.filter((x) => !EXCEPT_IDS.includes(x.id));
buy_buffer2.sort((a, b) => b.nfts - a.nfts);
for (let i = 0; i < 10; i++) {
  console.log(
    lpad(buy_buffer2[i].id),
    " : ",
    buy_buffer2[i].nfts / 10,
    "packs"
  );
}

line(40);
print("AVG PACKS BUY");
line(40);

let avg =
  buy_buffer2.reduce((prev, curr) => {
    return prev + curr.nfts;
  }, 0) /
  buy_buffer2.length /
  10;
print("JOINED STEEMIANs", buy_buffer2.length);
print("AVG BUY PACKs", avg);
// console.log(buy_buffer2);

line(40);
print("Has Legendary Account");
line(40);

let legen_buffer = {};
for (let r of l1) {
  legen_buffer[r.owner_account] = legen_buffer[r.owner_account]
    ? legen_buffer[r.owner_account] + 1
    : 1;
}
let legen_buffer2 = [];
for (let kv of Object.entries(legen_buffer)) {
  legen_buffer2.push({ id: kv[0], nfts: kv[1] });
}
legen_buffer2 = legen_buffer2.filter((x) => !EXCEPT_IDS.includes(x.id));
legen_buffer2.sort((a, b) => b.nfts - a.nfts);
for (let i = 0; i < legen_buffer2.length; i++) {
  console.log(lpad(legen_buffer2[i].id), " : ", legen_buffer2[i].nfts, "nfts");
}

참 쉽죠 ?

Sort:  

참 쉽...군요...(?!?!)

팩 판매량에 비해서 레전더리가 많이 풀렸네요.

@wonsama transfered 2 KRWP to @krwp.burn. voting percent : 62.10%, voting power : 17.75%, steem power : 1939938.08, STU KRW : 1200.
@wonsama staking status : 1793.429 KRWP
@wonsama limit for KRWP voting service : 1.793 KRWP (rate : 0.001)
What you sent : 2 KRWP
Refund balance : 0.207 KRWP [62513663 - 780fcda6f99d9a73915d165ef487d4385910bd24]

.... 코드 공유 감사합니당. 혹시.... 위에 코드를 복붙해서 실행하면 결과가 나오는 걸까요? 구글코랩에서 해보려구요. 코드 복붙은 할 수 있어서요^^

역시 전문가는 다르시군요~^^

Coin Marketplace

STEEM 0.19
TRX 0.15
JST 0.029
BTC 63811.18
ETH 2610.29
USDT 1.00
SBD 2.83