forked from Deploydon/TerraNFTSnapshot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
snapshot.js
97 lines (87 loc) · 3.58 KB
/
snapshot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
require('dotenv').config();
var terrajs = require("@terra-money/terra.js");
var fs = require("fs");
const DEFAULTRPC = "https://lcd.terra.dev";
const terra = new terrajs.LCDClient({
URL: process.env.RPCURL || DEFAULTRPC,
chainID: 'columbus-5',
});
console.log("RPC URL : " + process.env.RPCURL);
const SKIPCONTRACTS = process.env.SKIPCONTRACTS === "true" || false; //if true, NFTs held by contracts will not be included. (Marketplace settlement contracts, Multi-Sig wallets, etc)
const SNAPFOLDER = process.env.SNAPSHOTFOLDER || "snapshots";
const numTokens = process.env.NUMTOKENS || null;
const nftContract = process.env.NFTCONTRACT || null;
if (!numTokens || !nftContract){
console.log("Missing token count or contract address. Please set the environment variables.");
process.exit(0);
}
var waitDelay = 0; //If using the default public RPC, a wait delay is attached to avoid rate limits.
if (terra.config.URL == DEFAULTRPC) {
console.log("Using public RPC, rate limit added.");
waitDelay = 100;
}
const d = new Date();
var snapshotTime = d.toLocaleDateString() + `-${d.getHours()}-${d.getMinutes()}-${d.getSeconds()}`;
const snapshotFile = "./snapshots/snapshot-" + snapshotTime + ".json";
console.log("Saving To: " + snapshotFile);
var snapshot = { contract: nftContract, startTime: null, endTime: null, startBlock: null, endBlock: null, unique: null, holders: [] };
const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
var contractAddresses = [];
async function checkIfContract(address) {
var foundAddress = contractAddresses.find(x => x.address == address);
if (foundAddress) {
return foundAddress.isContract;
}
try {
var contractInfo = await terra.wasm.contractInfo(address);
contractAddresses.push({ address: address, isContract: true });
return true;
} catch (err) {
contractAddresses.push({ address: address, isContract: false });
return false;
}
}
async function main() {
if (!fs.existsSync(SNAPFOLDER)) {
fs.mkdirSync(SNAPFOLDER);
}
var uniqueHolders = [];
console.log("Snapshot Started...");
var blockInfo = await terra.tendermint.blockInfo();
snapshot.startTime = blockInfo.block.header.time;
snapshot.startBlock = blockInfo.block.header.height;
for (var i = 1; i <= numTokens; i++) {
var tokenID = i;
var resp = await terra.wasm.contractQuery(nftContract, { owner_of: { token_id: tokenID.toString() } });
var owner = resp.owner;
if (SKIPCONTRACTS) {
if (await checkIfContract(owner)) {
console.log(tokenID + " - Skipping contract: " + owner);
continue;
}
}
var token = {
id: tokenID,
owner: owner
}
snapshot.holders.push(token);
if (!uniqueHolders.includes(owner)) {
uniqueHolders.push(owner);
}
console.log(tokenID + " - Owner: " + owner);
await sleep(waitDelay);
}
blockInfo = await terra.tendermint.blockInfo();
snapshot.endTime = blockInfo.block.header.time;
snapshot.endBlock = blockInfo.block.header.height;
snapshot.unique = uniqueHolders.length;
console.log("Unique Holders: " + uniqueHolders.length);
fs.writeFileSync(snapshotFile, JSON.stringify(snapshot));
console.log("Snapshot Complete. Written to: " + snapshotFile);
var csv = "";
for (var i = 0; i < uniqueHolders.length; i++) {
csv += uniqueHolders[i] + "\n";
}
fs.writeFileSync("./snapshots/snapshot-" + snapshotTime + "-Unique.csv", csv);
}
main();