@gooddollar/goodprotocol 2.0.5 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/scripts/analytics/activeUsersCount.ts +0 -1
- package/scripts/analytics/activeWalletsStats.ts +13 -29
- package/scripts/analytics/claimIncidentStats.ts +6 -25
- package/scripts/analytics/faucetStats.ts +7 -19
- package/scripts/analytics/gdinflow.ts +3 -5
- package/scripts/analytics/goodHolders.ts +7 -11
- package/scripts/analytics/p2pTxs.ts +5 -23
- package/scripts/analytics/tokenInOutStats.ts +1 -5
- package/scripts/governance/airdropCalculation.ts +75 -206
- package/scripts/governance/goodCheckpointSorted.ts +35 -112
- package/scripts/keeper/fishInactive.ts +10 -20
- package/scripts/voltageswaps.ts +0 -1
package/package.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { range, sortBy } from "lodash";
|
|
2
|
-
import fetch from "node-fetch";
|
|
3
2
|
import PromisePool from "async-promise-pool";
|
|
4
3
|
import fs from "fs";
|
|
5
4
|
import { ethers } from "hardhat";
|
|
@@ -33,9 +32,7 @@ const main = async () => {
|
|
|
33
32
|
// );
|
|
34
33
|
// fs.writeFileSync("activeWalletsBalances.json", JSON.stringify(balances));
|
|
35
34
|
|
|
36
|
-
balances = JSON.parse(
|
|
37
|
-
fs.readFileSync("activeWalletsBalances.json").toString()
|
|
38
|
-
);
|
|
35
|
+
balances = JSON.parse(fs.readFileSync("activeWalletsBalances.json").toString());
|
|
39
36
|
|
|
40
37
|
const EPOCH = 60 * 60 * 6;
|
|
41
38
|
const pool = new PromisePool({ concurrency: 30 });
|
|
@@ -44,9 +41,7 @@ const main = async () => {
|
|
|
44
41
|
|
|
45
42
|
const graphQuery = async (start, skip) => {
|
|
46
43
|
const query = `{
|
|
47
|
-
walletStats(first: 1000 skip:${skip} where: { dateAppeared_gte: ${start} dateAppeared_lt:${
|
|
48
|
-
start + EPOCH
|
|
49
|
-
} }) {
|
|
44
|
+
walletStats(first: 1000 skip:${skip} where: { dateAppeared_gte: ${start} dateAppeared_lt:${start + EPOCH} }) {
|
|
50
45
|
id
|
|
51
46
|
dateAppeared
|
|
52
47
|
balance
|
|
@@ -57,16 +52,13 @@ const main = async () => {
|
|
|
57
52
|
}`;
|
|
58
53
|
// console.log({ query });
|
|
59
54
|
try {
|
|
60
|
-
const { data = {}, errors } = await fetch(
|
|
61
|
-
"
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
body: JSON.stringify({ query })
|
|
68
|
-
}
|
|
69
|
-
).then(_ => _.json());
|
|
55
|
+
const { data = {}, errors } = await fetch("https://api.thegraph.com/subgraphs/name/gooddollar/gooddollarfuse", {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: {
|
|
58
|
+
"Content-Type": "application/json"
|
|
59
|
+
},
|
|
60
|
+
body: JSON.stringify({ query })
|
|
61
|
+
}).then(_ => _.json());
|
|
70
62
|
errors && console.log({ errors });
|
|
71
63
|
if (data?.walletStats?.length === 1000) {
|
|
72
64
|
return data.walletStats.concat(await graphQuery(start, skip + 1000));
|
|
@@ -116,9 +108,7 @@ const etl = async () => {
|
|
|
116
108
|
.join("\r\n"); // rows starting on new lines
|
|
117
109
|
}
|
|
118
110
|
|
|
119
|
-
const balances = JSON.parse(
|
|
120
|
-
fs.readFileSync("activeWalletsLastUsed.json").toString()
|
|
121
|
-
);
|
|
111
|
+
const balances = JSON.parse(fs.readFileSync("activeWalletsLastUsed.json").toString());
|
|
122
112
|
|
|
123
113
|
let result = [];
|
|
124
114
|
|
|
@@ -131,24 +121,18 @@ const etl = async () => {
|
|
|
131
121
|
}
|
|
132
122
|
const top100 = result.slice(0, 100);
|
|
133
123
|
const pool = new PromisePool({ concurrency: 30 });
|
|
134
|
-
const provider = new ethers.providers.JsonRpcBatchProvider(
|
|
135
|
-
"https://rpc.fuse.io"
|
|
136
|
-
);
|
|
124
|
+
const provider = new ethers.providers.JsonRpcBatchProvider("https://rpc.fuse.io");
|
|
137
125
|
|
|
138
126
|
for (let idx in top100) {
|
|
139
127
|
pool.add(async () => {
|
|
140
128
|
const record = top100[idx];
|
|
141
|
-
let isContract =
|
|
142
|
-
(await provider.getCode(record[0]).catch(e => "0x")) !== "0x";
|
|
129
|
+
let isContract = (await provider.getCode(record[0]).catch(e => "0x")) !== "0x";
|
|
143
130
|
record[3] = isContract;
|
|
144
131
|
});
|
|
145
132
|
}
|
|
146
133
|
await pool.all();
|
|
147
134
|
console.log({ top100 });
|
|
148
|
-
fs.writeFileSync(
|
|
149
|
-
"activeWalletsLastUsed.csv",
|
|
150
|
-
arrayToCsv(sortBy(result, _ => -Number(_[1])))
|
|
151
|
-
);
|
|
135
|
+
fs.writeFileSync("activeWalletsLastUsed.csv", arrayToCsv(sortBy(result, _ => -Number(_[1]))));
|
|
152
136
|
};
|
|
153
137
|
// main().catch(e => console.log(e));
|
|
154
138
|
etl();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { countBy, chunk, difference, flatten, sortBy } from "lodash";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
import fetch from "node-fetch";
|
|
4
3
|
import { network, ethers, upgrades } from "hardhat";
|
|
5
4
|
import { Contract, Provider, setMulticallAddress } from "ethers-multicall";
|
|
6
5
|
import Identity from "../../artifacts/contracts/Interfaces.sol/IIdentity.json";
|
|
@@ -54,16 +53,11 @@ const hasRefunded = async wallets => {
|
|
|
54
53
|
let startBlock = CLAIM_START_BLOCK;
|
|
55
54
|
while (startBlock <= curBlock) {
|
|
56
55
|
const events = await gd.queryFilter(
|
|
57
|
-
gd.filters.Transfer(
|
|
58
|
-
undefined,
|
|
59
|
-
"0xd253A5203817225e9768C05E5996d642fb96bA86"
|
|
60
|
-
),
|
|
56
|
+
gd.filters.Transfer(undefined, "0xd253A5203817225e9768C05E5996d642fb96bA86"),
|
|
61
57
|
startBlock,
|
|
62
58
|
toBlock
|
|
63
59
|
);
|
|
64
|
-
const accounts = events
|
|
65
|
-
.filter(e => e.args.amount >= 9622260)
|
|
66
|
-
.map(_ => _.args.from.toLowerCase());
|
|
60
|
+
const accounts = events.filter(e => e.args.amount >= 9622260).map(_ => _.args.from.toLowerCase());
|
|
67
61
|
refunded.push(...accounts);
|
|
68
62
|
console.log("has refunded:", {
|
|
69
63
|
startBlock,
|
|
@@ -81,10 +75,7 @@ const whereIsTheMoney = async noBalance => {
|
|
|
81
75
|
for (let batch of chunk(noBalance, 100)) {
|
|
82
76
|
const tos = await Promise.all(
|
|
83
77
|
batch.map(async a => {
|
|
84
|
-
const e = await gd.queryFilter(
|
|
85
|
-
gd.filters.Transfer(a),
|
|
86
|
-
CLAIM_START_BLOCK
|
|
87
|
-
);
|
|
78
|
+
const e = await gd.queryFilter(gd.filters.Transfer(a), CLAIM_START_BLOCK);
|
|
88
79
|
const tos = e.filter(_ => _.args.amount > 1000000).map(_ => _.args.to);
|
|
89
80
|
return tos;
|
|
90
81
|
})
|
|
@@ -92,24 +83,14 @@ const whereIsTheMoney = async noBalance => {
|
|
|
92
83
|
targets.push(...flatten(tos));
|
|
93
84
|
}
|
|
94
85
|
const targetCounter = countBy(targets, _ => _);
|
|
95
|
-
console.log(
|
|
96
|
-
"transfer targets:",
|
|
97
|
-
sortBy(Object.entries(targetCounter), "1").reverse()
|
|
98
|
-
);
|
|
86
|
+
console.log("transfer targets:", sortBy(Object.entries(targetCounter), "1").reverse());
|
|
99
87
|
};
|
|
100
88
|
const main = async () => {
|
|
101
|
-
const wallets = JSON.parse(fs.readFileSync("torefund.json").toString()).map(
|
|
102
|
-
_ => _.toLowerCase()
|
|
103
|
-
);
|
|
89
|
+
const wallets = JSON.parse(fs.readFileSync("torefund.json").toString()).map(_ => _.toLowerCase());
|
|
104
90
|
console.log("Total Claimed:", wallets.length);
|
|
105
91
|
const refunded = await hasRefunded(wallets);
|
|
106
92
|
const notRefunded = difference(wallets, refunded);
|
|
107
|
-
console.log(
|
|
108
|
-
"refunded:",
|
|
109
|
-
refunded.length,
|
|
110
|
-
"not refunded:",
|
|
111
|
-
notRefunded.length
|
|
112
|
-
);
|
|
93
|
+
console.log("refunded:", refunded.length, "not refunded:", notRefunded.length);
|
|
113
94
|
|
|
114
95
|
const noBalanceToRefund = await hasBalanceToRefund(notRefunded);
|
|
115
96
|
await whereIsTheMoney(noBalanceToRefund);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { range, sortBy, toPairs } from "lodash";
|
|
2
|
-
import fetch from "node-fetch";
|
|
3
2
|
import PromisePool from "async-promise-pool";
|
|
4
3
|
import fs from "fs";
|
|
5
4
|
import { ethers } from "hardhat";
|
|
@@ -37,14 +36,7 @@ const main = async () => {
|
|
|
37
36
|
const dailyBalance = [];
|
|
38
37
|
for (let day of days) {
|
|
39
38
|
dailyBalance.push(
|
|
40
|
-
(
|
|
41
|
-
await archive.getBalance(
|
|
42
|
-
"0x01ab5966C1d742Ae0CFF7f14cC0F4D85156e83d9",
|
|
43
|
-
day
|
|
44
|
-
)
|
|
45
|
-
)
|
|
46
|
-
.div(1e10)
|
|
47
|
-
.toNumber() / 1e8
|
|
39
|
+
(await archive.getBalance("0x01ab5966C1d742Ae0CFF7f14cC0F4D85156e83d9", day)).div(1e10).toNumber() / 1e8
|
|
48
40
|
);
|
|
49
41
|
}
|
|
50
42
|
let curBlock = startBlock;
|
|
@@ -60,19 +52,15 @@ const main = async () => {
|
|
|
60
52
|
const toBlock = Math.min(fromBlock + blockStep, endBlock);
|
|
61
53
|
pool.add(async () => {
|
|
62
54
|
const f = faucet.filters.WalletTopped();
|
|
63
|
-
const events = await faucet
|
|
64
|
-
.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return [];
|
|
68
|
-
});
|
|
55
|
+
const events = await faucet.queryFilter(f, fromBlock, toBlock).catch(e => {
|
|
56
|
+
console.log("failed", { fromBlock, toBlock });
|
|
57
|
+
return [];
|
|
58
|
+
});
|
|
69
59
|
events.forEach(e => {
|
|
70
60
|
totalToppings += 1;
|
|
71
61
|
totalAmount += Number(e.args.amount);
|
|
72
|
-
toppingsByAddress[e.args.user] =
|
|
73
|
-
|
|
74
|
-
toppingsByAmount[e.args.amount] =
|
|
75
|
-
(toppingsByAmount[e.args.amount] || 0) + 1;
|
|
62
|
+
toppingsByAddress[e.args.user] = (toppingsByAddress[e.args.user] || 0) + 1;
|
|
63
|
+
toppingsByAmount[e.args.amount] = (toppingsByAmount[e.args.amount] || 0) + 1;
|
|
76
64
|
});
|
|
77
65
|
console.log("fetched events", {
|
|
78
66
|
fromBlock,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { maxBy, range, sortBy, uniq, sum, flatten, countBy } from "lodash";
|
|
2
|
-
import fetch from "node-fetch";
|
|
3
2
|
import PromisePool from "async-promise-pool";
|
|
4
3
|
import fs from "fs";
|
|
5
4
|
import { ethers } from "hardhat";
|
|
@@ -39,10 +38,9 @@ const main = async () => {
|
|
|
39
38
|
const incomingTxs = result
|
|
40
39
|
.filter(
|
|
41
40
|
_ =>
|
|
42
|
-
[
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
].includes(_.from) === false
|
|
41
|
+
["0xca2f09c3ccfd7ad5cb9276918bd1868f2b922ea0", "0xd253a5203817225e9768c05e5996d642fb96ba86"].includes(
|
|
42
|
+
_.from
|
|
43
|
+
) === false
|
|
46
44
|
)
|
|
47
45
|
.filter(_ => _.to === address.toLowerCase());
|
|
48
46
|
const totalEarned = sum(incomingTxs.map(_ => Number(_.value))) / 100;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { last, range, sortBy } from "lodash";
|
|
2
|
-
import fetch from "node-fetch";
|
|
3
2
|
import PromisePool from "async-promise-pool";
|
|
4
3
|
import fs from "fs";
|
|
5
4
|
import { ethers } from "hardhat";
|
|
@@ -19,16 +18,13 @@ const main = async () => {
|
|
|
19
18
|
}`;
|
|
20
19
|
// console.log({ query });
|
|
21
20
|
try {
|
|
22
|
-
const { data = {}, errors } = await fetch(
|
|
23
|
-
"
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
body: JSON.stringify({ query })
|
|
30
|
-
}
|
|
31
|
-
).then(_ => _.json());
|
|
21
|
+
const { data = {}, errors } = await fetch("https://api.thegraph.com/subgraphs/name/gooddollar/gooddollarfuse2", {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: {
|
|
24
|
+
"Content-Type": "application/json"
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify({ query })
|
|
27
|
+
}).then(_ => _.json());
|
|
32
28
|
errors && console.log({ errors });
|
|
33
29
|
if (data?.goodBalances?.length === 1000) {
|
|
34
30
|
const nextAddr = last(data?.goodBalances).id;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { maxBy, range, sortBy, flatten, uniq } from "lodash";
|
|
2
|
-
import fetch from "node-fetch";
|
|
3
2
|
import PromisePool from "async-promise-pool";
|
|
4
3
|
import fs from "fs";
|
|
5
4
|
import { Contract, Provider, setMulticallAddress } from "ethers-multicall";
|
|
@@ -487,9 +486,7 @@ const allProtocolAddresses: Array<string> = [
|
|
|
487
486
|
];
|
|
488
487
|
|
|
489
488
|
setMulticallAddress(122, "0x3CE6158b7278Bf6792e014FA7B4f3c6c46fe9410");
|
|
490
|
-
const fuseProvider = new ethers.providers.WebSocketProvider(
|
|
491
|
-
"wss://rpc.gooddollar.org"
|
|
492
|
-
);
|
|
489
|
+
const fuseProvider = new ethers.providers.WebSocketProvider("wss://rpc.gooddollar.org");
|
|
493
490
|
const ethcallProvider = new Provider(fuseProvider, 122);
|
|
494
491
|
|
|
495
492
|
const GD_FUSE = "0x495d133b938596c9984d462f007b676bdc57ecec";
|
|
@@ -534,31 +531,16 @@ const main = async () => {
|
|
|
534
531
|
)
|
|
535
532
|
);
|
|
536
533
|
|
|
537
|
-
const checkWhitelisted = uniq(
|
|
538
|
-
|
|
539
|
-
clean.map(_ => [_.args.from.toLowerCase(), _.args.to.toLowerCase()])
|
|
540
|
-
)
|
|
541
|
-
);
|
|
542
|
-
const calls = checkWhitelisted.map(d =>
|
|
543
|
-
identityContract.isWhitelisted(d)
|
|
544
|
-
);
|
|
534
|
+
const checkWhitelisted = uniq(flatten(clean.map(_ => [_.args.from.toLowerCase(), _.args.to.toLowerCase()])));
|
|
535
|
+
const calls = checkWhitelisted.map(d => identityContract.isWhitelisted(d));
|
|
545
536
|
const result = await ethcallProvider.all(calls);
|
|
546
537
|
const whitelisted = checkWhitelisted.filter((v, i) => result[i]);
|
|
547
538
|
const p2p = clean.filter(
|
|
548
|
-
_ =>
|
|
549
|
-
whitelisted.includes(_.args.to.toLowerCase()) ||
|
|
550
|
-
whitelisted.includes(_.args.from.toLowerCase())
|
|
539
|
+
_ => whitelisted.includes(_.args.to.toLowerCase()) || whitelisted.includes(_.args.from.toLowerCase())
|
|
551
540
|
);
|
|
552
541
|
p2pTxs = p2pTxs.concat(p2p);
|
|
553
542
|
uniques = uniques.concat(whitelisted);
|
|
554
|
-
console.log(
|
|
555
|
-
{ fromBlock },
|
|
556
|
-
results.length,
|
|
557
|
-
clean.length,
|
|
558
|
-
checkWhitelisted.length,
|
|
559
|
-
whitelisted.length,
|
|
560
|
-
p2p.length
|
|
561
|
-
);
|
|
543
|
+
console.log({ fromBlock }, results.length, clean.length, checkWhitelisted.length, whitelisted.length, p2p.length);
|
|
562
544
|
});
|
|
563
545
|
});
|
|
564
546
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { maxBy, range, sortBy } from "lodash";
|
|
2
|
-
import fetch from "node-fetch";
|
|
3
2
|
import PromisePool from "async-promise-pool";
|
|
4
3
|
import fs from "fs";
|
|
5
4
|
import { ethers } from "hardhat";
|
|
@@ -43,10 +42,7 @@ const main = async () => {
|
|
|
43
42
|
ins.push(r);
|
|
44
43
|
}
|
|
45
44
|
});
|
|
46
|
-
fs.writeFileSync(
|
|
47
|
-
"tokenInOut.json",
|
|
48
|
-
JSON.stringify({ incoming, outgoing, ins })
|
|
49
|
-
);
|
|
45
|
+
fs.writeFileSync("tokenInOut.json", JSON.stringify({ incoming, outgoing, ins }));
|
|
50
46
|
};
|
|
51
47
|
|
|
52
48
|
main().catch(e => console.log(e));
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { get, range, chunk, flatten, mergeWith, sortBy, uniq } from "lodash";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
import MerkleTree, {
|
|
4
|
-
checkProof,
|
|
5
|
-
checkProofOrdered
|
|
6
|
-
} from "merkle-tree-solidity";
|
|
3
|
+
import MerkleTree, { checkProof, checkProofOrdered } from "merkle-tree-solidity";
|
|
7
4
|
import coreContracts from "@gooddollar/goodcontracts/releases/deployment.json";
|
|
8
5
|
import stakingContracts from "@gooddollar/goodcontracts/stakingModel/releases/deployment.json";
|
|
9
6
|
import upgradablesContracts from "@gooddollar/goodcontracts/upgradables/releases/deployment.json";
|
|
10
7
|
import SimpleDAIStaking from "@gooddollar/goodcontracts/stakingModel/build/contracts/SimpleDAIStaking.min.json";
|
|
11
8
|
import { ethers as Ethers } from "hardhat";
|
|
12
|
-
import fetch from "node-fetch";
|
|
13
9
|
import { request, gql } from "graphql-request";
|
|
14
10
|
import { Retrier } from "@jsier/retrier";
|
|
15
11
|
import PromisePool from "async-promise-pool";
|
|
@@ -56,9 +52,7 @@ const otherContracts = [
|
|
|
56
52
|
|
|
57
53
|
const systemContracts = {};
|
|
58
54
|
const allContracts = flatten(
|
|
59
|
-
[coreContracts, stakingContracts, upgradablesContracts].map(_ =>
|
|
60
|
-
Object.values(_).map(_ => Object.values(_))
|
|
61
|
-
)
|
|
55
|
+
[coreContracts, stakingContracts, upgradablesContracts].map(_ => Object.values(_).map(_ => Object.values(_)))
|
|
62
56
|
);
|
|
63
57
|
flatten(
|
|
64
58
|
[].concat(
|
|
@@ -89,27 +83,17 @@ const quantile = (sorted, q) => {
|
|
|
89
83
|
let FUSE_SNAPSHOT_BLOCK = 13175510; //September-29-2021 03:00:00 PM +3 UTC
|
|
90
84
|
let ETH_SNAPSHOT_BLOCK = 13320531; //first blocka after 12pm Sep-29-2021 12:00:20 PM +UTC
|
|
91
85
|
|
|
92
|
-
export const airdrop = (
|
|
93
|
-
ethers: typeof Ethers,
|
|
94
|
-
ethplorer_key,
|
|
95
|
-
etherscan_key
|
|
96
|
-
) => {
|
|
86
|
+
export const airdrop = (ethers: typeof Ethers, ethplorer_key, etherscan_key) => {
|
|
97
87
|
const fusePoktProvider = new ethers.providers.JsonRpcProvider({
|
|
98
88
|
url: "https://fuse-mainnet.gateway.pokt.network/v1/lb/60ee374fc6318362996a1fb0",
|
|
99
89
|
user: "",
|
|
100
90
|
password: "d57939c260bdf0a6f22550e2350b4312" //end point will be removed, so its ok to keep clear text password
|
|
101
91
|
});
|
|
102
92
|
|
|
103
|
-
const fuseProvider = new ethers.providers.JsonRpcProvider(
|
|
104
|
-
"https://rpc.fuse.io"
|
|
105
|
-
);
|
|
93
|
+
const fuseProvider = new ethers.providers.JsonRpcProvider("https://rpc.fuse.io");
|
|
106
94
|
|
|
107
|
-
const fuseGDProvider = new ethers.providers.JsonRpcProvider(
|
|
108
|
-
|
|
109
|
-
);
|
|
110
|
-
const fuseArchiveProvider = new ethers.providers.JsonRpcBatchProvider(
|
|
111
|
-
"https://explorer-node.fuse.io/"
|
|
112
|
-
);
|
|
95
|
+
const fuseGDProvider = new ethers.providers.JsonRpcProvider("https://gooddollar-rpc.fuse.io");
|
|
96
|
+
const fuseArchiveProvider = new ethers.providers.JsonRpcBatchProvider("https://explorer-node.fuse.io/");
|
|
113
97
|
|
|
114
98
|
const poktArchiveProvider = new ethers.providers.JsonRpcProvider({
|
|
115
99
|
url: "https://eth-trace.gateway.pokt.network/v1/lb/6130bad2dc57c50036551041",
|
|
@@ -182,8 +166,7 @@ export const airdrop = (
|
|
|
182
166
|
const nowBlock = ETH_SNAPSHOT_BLOCK; //await staking.provider.getBlockNumber();
|
|
183
167
|
let toAggregate = events.map(_ => [
|
|
184
168
|
_.args.staker.toLowerCase(),
|
|
185
|
-
parseFloat(ethers.utils.formatEther(_.args.daiValue)) *
|
|
186
|
-
(nowBlock - _.blockNumber), //value staked multiplied by time staked (there where no withdraws so far besides foundation account)
|
|
169
|
+
parseFloat(ethers.utils.formatEther(_.args.daiValue)) * (nowBlock - _.blockNumber), //value staked multiplied by time staked (there where no withdraws so far besides foundation account)
|
|
187
170
|
parseFloat(ethers.utils.formatEther(_.args.daiValue))
|
|
188
171
|
]);
|
|
189
172
|
|
|
@@ -200,16 +183,12 @@ export const airdrop = (
|
|
|
200
183
|
.filter(_ => !isSystemContract(_.args.from))
|
|
201
184
|
.map(e => [
|
|
202
185
|
e.args.from.toLowerCase(),
|
|
203
|
-
parseFloat(ethers.utils.formatEther(e.args.value)) *
|
|
204
|
-
(nowBlock - e.blockNumber),
|
|
186
|
+
parseFloat(ethers.utils.formatEther(e.args.value)) * (nowBlock - e.blockNumber),
|
|
205
187
|
parseFloat(ethers.utils.formatEther(e.args.value))
|
|
206
188
|
]);
|
|
207
189
|
|
|
208
190
|
//read eth donations and calculate period * $ value
|
|
209
|
-
let provider = new ethers.providers.EtherscanProvider(
|
|
210
|
-
"homestead",
|
|
211
|
-
etherscan_key
|
|
212
|
-
);
|
|
191
|
+
let provider = new ethers.providers.EtherscanProvider("homestead", etherscan_key);
|
|
213
192
|
|
|
214
193
|
//use etherscan to read past eth transfers to the donation contract
|
|
215
194
|
let historyPromises = (
|
|
@@ -222,9 +201,9 @@ export const airdrop = (
|
|
|
222
201
|
.filter(_ => _.value.gt(ethers.constants.Zero))
|
|
223
202
|
.map(async _ => {
|
|
224
203
|
const data = await fetch(
|
|
225
|
-
`https://poloniex.com/public?command=returnChartData¤cyPair=USDT_ETH&start=${
|
|
226
|
-
_.timestamp
|
|
227
|
-
}&
|
|
204
|
+
`https://poloniex.com/public?command=returnChartData¤cyPair=USDT_ETH&start=${_.timestamp}&end=${
|
|
205
|
+
_.timestamp + 30000
|
|
206
|
+
}&period=300`
|
|
228
207
|
).then(_ => _.json());
|
|
229
208
|
const price = data[0].weightedAverage || data[0].open;
|
|
230
209
|
if (price == 0) console.error("error 0 price", { data });
|
|
@@ -234,18 +213,13 @@ export const airdrop = (
|
|
|
234
213
|
timestamp: _.timestamp,
|
|
235
214
|
price,
|
|
236
215
|
usdvalue: price * parseFloat(ethers.utils.formatEther(_.value)),
|
|
237
|
-
share:
|
|
238
|
-
price *
|
|
239
|
-
parseFloat(ethers.utils.formatEther(_.value)) *
|
|
240
|
-
(nowBlock - _.blockNumber) //value staked multiplied by time staked
|
|
216
|
+
share: price * parseFloat(ethers.utils.formatEther(_.value)) * (nowBlock - _.blockNumber) //value staked multiplied by time staked
|
|
241
217
|
};
|
|
242
218
|
});
|
|
243
219
|
|
|
244
220
|
let ethDonations = await Promise.all(historyPromises);
|
|
245
221
|
|
|
246
|
-
let donationsToAggregate = daiDonationsToAggregate.concat(
|
|
247
|
-
ethDonations.map(_ => [_.from, _.share, _.usdvalue])
|
|
248
|
-
);
|
|
222
|
+
let donationsToAggregate = daiDonationsToAggregate.concat(ethDonations.map(_ => [_.from, _.share, _.usdvalue]));
|
|
249
223
|
|
|
250
224
|
const stakerToTotal: { [key: string]: number } = {};
|
|
251
225
|
toAggregate = toAggregate.concat(donationsToAggregate);
|
|
@@ -265,8 +239,7 @@ export const airdrop = (
|
|
|
265
239
|
withdrawevents.forEach(
|
|
266
240
|
_ =>
|
|
267
241
|
(stakerToTotal[_.args.staker.toLowerCase()] -=
|
|
268
|
-
parseFloat(ethers.utils.formatEther(_.args.daiValue)) *
|
|
269
|
-
(nowBlock - _.blockNumber))
|
|
242
|
+
parseFloat(ethers.utils.formatEther(_.args.daiValue)) * (nowBlock - _.blockNumber))
|
|
270
243
|
);
|
|
271
244
|
|
|
272
245
|
//filter contracts + calculate total shares
|
|
@@ -323,10 +296,7 @@ export const airdrop = (
|
|
|
323
296
|
liquidityPositions(
|
|
324
297
|
orderDirection: desc
|
|
325
298
|
orderBy: liquidityTokenBalance
|
|
326
|
-
where: {
|
|
327
|
-
pair: "0xa56a281cd8ba5c083af121193b2aaccaaac9850a"
|
|
328
|
-
liquidityTokenBalance_gt: 0
|
|
329
|
-
}
|
|
299
|
+
where: { pair: "0xa56a281cd8ba5c083af121193b2aaccaaac9850a", liquidityTokenBalance_gt: 0 }
|
|
330
300
|
) {
|
|
331
301
|
id
|
|
332
302
|
user {
|
|
@@ -341,10 +311,7 @@ export const airdrop = (
|
|
|
341
311
|
}
|
|
342
312
|
`;
|
|
343
313
|
|
|
344
|
-
let pair = await ethers.getContractAt(
|
|
345
|
-
"UniswapPair",
|
|
346
|
-
"0xa56a281cd8ba5c083af121193b2aaccaaac9850a"
|
|
347
|
-
);
|
|
314
|
+
let pair = await ethers.getContractAt("UniswapPair", "0xa56a281cd8ba5c083af121193b2aaccaaac9850a");
|
|
348
315
|
pair = pair.connect(poktArchiveProvider);
|
|
349
316
|
|
|
350
317
|
const pairTotalSupply = await pair
|
|
@@ -358,10 +325,7 @@ export const airdrop = (
|
|
|
358
325
|
console.log("uniswap pair data:", { reserve0, pairTotalSupply });
|
|
359
326
|
|
|
360
327
|
//TODO: read supplier balance at snapshot
|
|
361
|
-
const { liquidityPositions } = await request(
|
|
362
|
-
"https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2",
|
|
363
|
-
query
|
|
364
|
-
);
|
|
328
|
+
const { liquidityPositions } = await request("https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2", query);
|
|
365
329
|
|
|
366
330
|
const gdHoldings = liquidityPositions.map(async pos => {
|
|
367
331
|
const uAddress = pos.user.id.toLowerCase();
|
|
@@ -376,8 +340,7 @@ export const airdrop = (
|
|
|
376
340
|
`${uAddress}.isNotContract`,
|
|
377
341
|
(await gdMainnet.provider.getCode(uAddress).catch(e => "0x")) === "0x"
|
|
378
342
|
);
|
|
379
|
-
const newBalance =
|
|
380
|
-
(get(addresses, `${uAddress}.balance`, 0) as number) + gdShare;
|
|
343
|
+
const newBalance = (get(addresses, `${uAddress}.balance`, 0) as number) + gdShare;
|
|
381
344
|
console.log("uniswap position:", {
|
|
382
345
|
pos,
|
|
383
346
|
newBalance,
|
|
@@ -396,11 +359,7 @@ export const airdrop = (
|
|
|
396
359
|
return addresses;
|
|
397
360
|
};
|
|
398
361
|
|
|
399
|
-
const getFuseSwapBalances = async (
|
|
400
|
-
graphqlUrl,
|
|
401
|
-
tokenId,
|
|
402
|
-
addresses: Balances = {}
|
|
403
|
-
) => {
|
|
362
|
+
const getFuseSwapBalances = async (graphqlUrl, tokenId, addresses: Balances = {}) => {
|
|
404
363
|
const _calcHoldings = async (pair, addresses: Balances = {}) => {
|
|
405
364
|
const { liquidityPositions, reserve0: isReserve0, id } = pair;
|
|
406
365
|
let pairContract = await ethers.getContractAt("UniswapPair", id);
|
|
@@ -443,8 +402,7 @@ export const airdrop = (
|
|
|
443
402
|
reserve: reserve
|
|
444
403
|
});
|
|
445
404
|
|
|
446
|
-
const newBalance =
|
|
447
|
-
(get(addresses, `${uAddress}.balance`, 0) as number) + gdShare;
|
|
405
|
+
const newBalance = (get(addresses, `${uAddress}.balance`, 0) as number) + gdShare;
|
|
448
406
|
|
|
449
407
|
addresses[uAddress] = updateBalance(addresses[uAddress], {
|
|
450
408
|
balance: newBalance
|
|
@@ -516,8 +474,7 @@ export const airdrop = (
|
|
|
516
474
|
);
|
|
517
475
|
|
|
518
476
|
const farmers = {};
|
|
519
|
-
const yieldFarmingRep =
|
|
520
|
-
addresses[usdcgdYieldFarming.address.toLowerCase()]?.balance || 0;
|
|
477
|
+
const yieldFarmingRep = addresses[usdcgdYieldFarming.address.toLowerCase()]?.balance || 0;
|
|
521
478
|
if (yieldFarmingRep > 0) {
|
|
522
479
|
const [totalStaked, ,] = await usdcgdYieldFarming.interestData({
|
|
523
480
|
blockTag: FUSE_SNAPSHOT_BLOCK
|
|
@@ -525,19 +482,14 @@ export const airdrop = (
|
|
|
525
482
|
|
|
526
483
|
await Promise.all(
|
|
527
484
|
staked.map(async e => {
|
|
528
|
-
const [balance] = await usdcgdYieldFarming.getStakerData(
|
|
529
|
-
e.args.staker,
|
|
530
|
-
{ blockTag: FUSE_SNAPSHOT_BLOCK }
|
|
531
|
-
);
|
|
485
|
+
const [balance] = await usdcgdYieldFarming.getStakerData(e.args.staker, { blockTag: FUSE_SNAPSHOT_BLOCK });
|
|
532
486
|
|
|
533
487
|
if (balance > 0) {
|
|
534
488
|
const share = balance.toNumber() / totalStaked.toNumber();
|
|
535
489
|
const uAddress = e.args.staker;
|
|
536
490
|
const repShare = parseInt((share * yieldFarmingRep).toFixed(0));
|
|
537
491
|
farmers[uAddress] = [share, repShare];
|
|
538
|
-
const newBalance =
|
|
539
|
-
(get(addresses, `${uAddress}.balance`, 0) as number) +
|
|
540
|
-
share * yieldFarmingRep;
|
|
492
|
+
const newBalance = (get(addresses, `${uAddress}.balance`, 0) as number) + share * yieldFarmingRep;
|
|
541
493
|
|
|
542
494
|
addresses[uAddress] = updateBalance(addresses[uAddress], {
|
|
543
495
|
balance: newBalance
|
|
@@ -563,16 +515,8 @@ export const airdrop = (
|
|
|
563
515
|
return addresses;
|
|
564
516
|
};
|
|
565
517
|
|
|
566
|
-
const getFuseHolders = async (
|
|
567
|
-
|
|
568
|
-
onlyBalances = false,
|
|
569
|
-
onlyFailed = false
|
|
570
|
-
) => {
|
|
571
|
-
console.log(
|
|
572
|
-
"getFuseHolders",
|
|
573
|
-
{ onlyBalances, onlyFailed },
|
|
574
|
-
Object.keys(addresses).length
|
|
575
|
-
);
|
|
518
|
+
const getFuseHolders = async (addresses: Balances = {}, onlyBalances = false, onlyFailed = false) => {
|
|
519
|
+
console.log("getFuseHolders", { onlyBalances, onlyFailed }, Object.keys(addresses).length);
|
|
576
520
|
const toFetch = {};
|
|
577
521
|
|
|
578
522
|
const step = 1000;
|
|
@@ -596,11 +540,7 @@ export const airdrop = (
|
|
|
596
540
|
const logs = await retrier.resolve(attempt => {
|
|
597
541
|
console.log("fetching block transfer logs", { attempt, bc });
|
|
598
542
|
|
|
599
|
-
return contracts[idx++ % contracts.length].queryFilter(
|
|
600
|
-
filter,
|
|
601
|
-
bc,
|
|
602
|
-
Math.min(bc + step - 1, latestBlock)
|
|
603
|
-
);
|
|
543
|
+
return contracts[idx++ % contracts.length].queryFilter(filter, bc, Math.min(bc + step - 1, latestBlock));
|
|
604
544
|
});
|
|
605
545
|
|
|
606
546
|
logs.forEach(l => (toFetch[l.args.to.toLowerCase()] = true));
|
|
@@ -652,14 +592,11 @@ export const airdrop = (
|
|
|
652
592
|
for (let addrChunk of chunk(addrs, 50)) {
|
|
653
593
|
balancesPool.add(async () => {
|
|
654
594
|
const ps = addrChunk.map(async (uAddress: string) => {
|
|
655
|
-
const curBalance = onlyFailed
|
|
656
|
-
? 0
|
|
657
|
-
: get(addresses, `${uAddress}.balance`, 0);
|
|
595
|
+
const curBalance = onlyFailed ? 0 : get(addresses, `${uAddress}.balance`, 0);
|
|
658
596
|
const isNotContract = get(
|
|
659
597
|
addresses,
|
|
660
598
|
`${uAddress}.isNotContract`,
|
|
661
|
-
(await gdNonArchive.provider.getCode(uAddress).catch(e => "0x")) ===
|
|
662
|
-
"0x"
|
|
599
|
+
(await gdNonArchive.provider.getCode(uAddress).catch(e => "0x")) === "0x"
|
|
663
600
|
);
|
|
664
601
|
const balance = await gd
|
|
665
602
|
.balanceOf(uAddress)
|
|
@@ -682,8 +619,7 @@ export const airdrop = (
|
|
|
682
619
|
|
|
683
620
|
await balancesPool.all();
|
|
684
621
|
console.log("fuseHolders failed:", failed.length);
|
|
685
|
-
if (!onlyFailed)
|
|
686
|
-
fs.writeFileSync("airdrop/failed.tmp", JSON.stringify(failed));
|
|
622
|
+
if (!onlyFailed) fs.writeFileSync("airdrop/failed.tmp", JSON.stringify(failed));
|
|
687
623
|
return addresses;
|
|
688
624
|
};
|
|
689
625
|
|
|
@@ -706,8 +642,7 @@ export const airdrop = (
|
|
|
706
642
|
const isNotContract = get(
|
|
707
643
|
addresses,
|
|
708
644
|
`${uAddress}.isNotContract`,
|
|
709
|
-
(await gdNonArchive.provider.getCode(b[0]).catch(e => "0x")) ===
|
|
710
|
-
"0x"
|
|
645
|
+
(await gdNonArchive.provider.getCode(b[0]).catch(e => "0x")) === "0x"
|
|
711
646
|
);
|
|
712
647
|
const cleanBalance = await gdNonArchive
|
|
713
648
|
.balanceOf(uAddress, { blockTag: FUSE_SNAPSHOT_BLOCK })
|
|
@@ -738,9 +673,7 @@ export const airdrop = (
|
|
|
738
673
|
}
|
|
739
674
|
|
|
740
675
|
if (items && items.length) {
|
|
741
|
-
const foundBalances = items.map(i =>
|
|
742
|
-
i.match(/(0x\w{20,})|([0-9\.,]+ G\$)/g)
|
|
743
|
-
);
|
|
676
|
+
const foundBalances = items.map(i => i.match(/(0x\w{20,})|([0-9\.,]+ G\$)/g));
|
|
744
677
|
analyzedPages++;
|
|
745
678
|
analyzedBalances += foundBalances.length;
|
|
746
679
|
toFetch = toFetch.concat(foundBalances);
|
|
@@ -795,13 +728,11 @@ export const airdrop = (
|
|
|
795
728
|
.then(_ => _.toNumber())
|
|
796
729
|
.catch(e => failedAccounts.push(uAddress));
|
|
797
730
|
|
|
798
|
-
const newBalance =
|
|
799
|
-
get(addresses, `${uAddress}.balance`, 0) + cleanBalance;
|
|
731
|
+
const newBalance = get(addresses, `${uAddress}.balance`, 0) + cleanBalance;
|
|
800
732
|
const isNotContract = get(
|
|
801
733
|
addresses,
|
|
802
734
|
`${uAddress}.isNotContract`,
|
|
803
|
-
(await gdMainnet.provider.getCode(uAddress).catch(e => "0x")) ===
|
|
804
|
-
"0x"
|
|
735
|
+
(await gdMainnet.provider.getCode(uAddress).catch(e => "0x")) === "0x"
|
|
805
736
|
);
|
|
806
737
|
addresses[uAddress] = updateBalance(addresses[uAddress], {
|
|
807
738
|
balance: newBalance,
|
|
@@ -820,10 +751,7 @@ export const airdrop = (
|
|
|
820
751
|
return addresses;
|
|
821
752
|
};
|
|
822
753
|
|
|
823
|
-
const getClaimsPerAddress = async (
|
|
824
|
-
balances: Balances = {},
|
|
825
|
-
ubiContract = ubi
|
|
826
|
-
) => {
|
|
754
|
+
const getClaimsPerAddress = async (balances: Balances = {}, ubiContract = ubi) => {
|
|
827
755
|
const ubiFuse = ubiContract.connect(fuseProvider);
|
|
828
756
|
const ubiPokt = ubiContract.connect(fusePoktProvider);
|
|
829
757
|
const ubiGD = ubiContract.connect(fuseGDProvider);
|
|
@@ -831,11 +759,7 @@ export const airdrop = (
|
|
|
831
759
|
const pool = new PromisePool({ concurrency: 50 });
|
|
832
760
|
const step = 1000;
|
|
833
761
|
const latestBlock = FUSE_SNAPSHOT_BLOCK; //await ubiContract.provider.getBlockNumber();
|
|
834
|
-
const blocks = range(
|
|
835
|
-
ubiContract === ubi ? 6276288 : 9376522,
|
|
836
|
-
ubiContract === ubi ? 9497482 : latestBlock,
|
|
837
|
-
step
|
|
838
|
-
);
|
|
762
|
+
const blocks = range(ubiContract === ubi ? 6276288 : 9376522, ubiContract === ubi ? 9497482 : latestBlock, step);
|
|
839
763
|
const filter = ubiContract.filters.UBIClaimed();
|
|
840
764
|
const contracts = [ubiFuse, ubiGD];
|
|
841
765
|
let idx = 0;
|
|
@@ -847,11 +771,7 @@ export const airdrop = (
|
|
|
847
771
|
const logs = await retrier.resolve(attempt => {
|
|
848
772
|
console.log("fetching block ubiclaimed logs", { attempt, bc });
|
|
849
773
|
|
|
850
|
-
return contracts[idx++ % contracts.length].queryFilter(
|
|
851
|
-
filter,
|
|
852
|
-
bc,
|
|
853
|
-
Math.min(bc + step - 1, latestBlock)
|
|
854
|
-
);
|
|
774
|
+
return contracts[idx++ % contracts.length].queryFilter(filter, bc, Math.min(bc + step - 1, latestBlock));
|
|
855
775
|
});
|
|
856
776
|
|
|
857
777
|
console.log("found claim logs in block:", { bc }, logs.length);
|
|
@@ -870,20 +790,12 @@ export const airdrop = (
|
|
|
870
790
|
};
|
|
871
791
|
|
|
872
792
|
const calcRelativeRep = (balances: Balances) => {
|
|
873
|
-
const totalSupply = Object.values(balances).reduce(
|
|
874
|
-
|
|
875
|
-
0
|
|
876
|
-
);
|
|
877
|
-
const totalClaims = Object.values(balances).reduce(
|
|
878
|
-
(cur, data) => cur + (data.claims || 0),
|
|
879
|
-
0
|
|
880
|
-
);
|
|
793
|
+
const totalSupply = Object.values(balances).reduce((cur, data) => cur + data.balance, 0);
|
|
794
|
+
const totalClaims = Object.values(balances).reduce((cur, data) => cur + (data.claims || 0), 0);
|
|
881
795
|
|
|
882
796
|
for (let addr in balances) {
|
|
883
|
-
balances[addr].gdRepShare =
|
|
884
|
-
|
|
885
|
-
balances[addr].claimRepShare =
|
|
886
|
-
totalClaims > 0 ? balances[addr].claims / totalClaims : 0;
|
|
797
|
+
balances[addr].gdRepShare = totalSupply > 0 ? balances[addr].balance / totalSupply : 0;
|
|
798
|
+
balances[addr].claimRepShare = totalClaims > 0 ? balances[addr].claims / totalClaims : 0;
|
|
887
799
|
}
|
|
888
800
|
return { totalSupply, totalClaims, balances };
|
|
889
801
|
};
|
|
@@ -903,35 +815,26 @@ export const airdrop = (
|
|
|
903
815
|
|
|
904
816
|
ps[0] = _timer(
|
|
905
817
|
"getFuseSwapBalances",
|
|
906
|
-
getFuseSwapBalances(
|
|
907
|
-
"https://graph.fuse.io/subgraphs/name/fuseio/fuseswap",
|
|
908
|
-
GD_FUSE
|
|
909
|
-
).then(r =>
|
|
818
|
+
getFuseSwapBalances("https://graph.fuse.io/subgraphs/name/fuseio/fuseswap", GD_FUSE).then(r =>
|
|
910
819
|
fs.writeFileSync("airdrop/fuseswapBalances.json", JSON.stringify(r))
|
|
911
820
|
)
|
|
912
821
|
);
|
|
913
822
|
|
|
914
823
|
ps[1] = _timer(
|
|
915
824
|
"getUniswapBalances",
|
|
916
|
-
getUniswapBalances().then(r =>
|
|
917
|
-
fs.writeFileSync("airdrop/uniswapBalances.json", JSON.stringify(r))
|
|
918
|
-
)
|
|
825
|
+
getUniswapBalances().then(r => fs.writeFileSync("airdrop/uniswapBalances.json", JSON.stringify(r)))
|
|
919
826
|
);
|
|
920
827
|
|
|
921
828
|
ps[2] = _timer(
|
|
922
829
|
"getClaimsPerAddress",
|
|
923
830
|
getClaimsPerAddress()
|
|
924
831
|
.then(r => getClaimsPerAddress(r, ubinew))
|
|
925
|
-
.then(r =>
|
|
926
|
-
fs.writeFileSync("airdrop/claimBalances.json", JSON.stringify(r))
|
|
927
|
-
)
|
|
832
|
+
.then(r => fs.writeFileSync("airdrop/claimBalances.json", JSON.stringify(r)))
|
|
928
833
|
);
|
|
929
834
|
|
|
930
835
|
ps[3] = _timer(
|
|
931
836
|
"getEthPlorerHolders",
|
|
932
|
-
getEthPlorerHolders().then(r =>
|
|
933
|
-
fs.writeFileSync("airdrop/ethBalances.json", JSON.stringify(r))
|
|
934
|
-
)
|
|
837
|
+
getEthPlorerHolders().then(r => fs.writeFileSync("airdrop/ethBalances.json", JSON.stringify(r)))
|
|
935
838
|
);
|
|
936
839
|
|
|
937
840
|
// ps[4] = _timer(
|
|
@@ -945,16 +848,12 @@ export const airdrop = (
|
|
|
945
848
|
// );
|
|
946
849
|
ps[4] = _timer(
|
|
947
850
|
"getFuseHolders",
|
|
948
|
-
getFuseHolders({}).then(r =>
|
|
949
|
-
fs.writeFileSync("airdrop/fuseBalances.json", JSON.stringify(r))
|
|
950
|
-
)
|
|
851
|
+
getFuseHolders({}).then(r => fs.writeFileSync("airdrop/fuseBalances.json", JSON.stringify(r)))
|
|
951
852
|
);
|
|
952
853
|
|
|
953
854
|
ps[5] = _timer(
|
|
954
855
|
"getStakersBalance",
|
|
955
|
-
getStakersBalance().then(r =>
|
|
956
|
-
fs.writeFileSync("airdrop/stakersBalances.json", JSON.stringify(r))
|
|
957
|
-
)
|
|
856
|
+
getStakersBalance().then(r => fs.writeFileSync("airdrop/stakersBalances.json", JSON.stringify(r)))
|
|
958
857
|
);
|
|
959
858
|
|
|
960
859
|
await Promise.all(ps);
|
|
@@ -980,13 +879,8 @@ export const airdrop = (
|
|
|
980
879
|
obj1.claims = get(obj1, "claims", 0) + get(obj2, "claims", 0);
|
|
981
880
|
obj1.balance = get(obj1, "balance", 0) + get(obj2, "balance", 0);
|
|
982
881
|
obj1.stake = get(obj1, "stake", 0) + get(obj2, "stake", 0);
|
|
983
|
-
obj1.stakeRepShare =
|
|
984
|
-
|
|
985
|
-
obj1.isNotContract = get(
|
|
986
|
-
obj1,
|
|
987
|
-
"isNotContract",
|
|
988
|
-
get(obj2, "isNotContract")
|
|
989
|
-
);
|
|
882
|
+
obj1.stakeRepShare = get(obj1, "stakeRepShare") || get(obj2, "stakeRepShare", 0);
|
|
883
|
+
obj1.isNotContract = get(obj1, "isNotContract", get(obj2, "isNotContract"));
|
|
990
884
|
return obj1;
|
|
991
885
|
};
|
|
992
886
|
|
|
@@ -1003,14 +897,9 @@ export const airdrop = (
|
|
|
1003
897
|
const HOLDER_REP_ALLOCATION = 24000000;
|
|
1004
898
|
const STAKER_REP_ALLOCATION = 24000000;
|
|
1005
899
|
|
|
1006
|
-
const ETORO = [
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
];
|
|
1010
|
-
const EtoroOfficial =
|
|
1011
|
-
"0x61ec01ad0937ebc10d448d259a2bbb1556b61e38".toLowerCase();
|
|
1012
|
-
const FoundationOfficial =
|
|
1013
|
-
"0x66582D24FEaD72555adaC681Cc621caCbB208324".toLowerCase();
|
|
900
|
+
const ETORO = ["0xf79b804bae955ae4cd8e8b0331c4bc437104804f", "0x61ec01ad0937ebc10d448d259a2bbb1556b61e38"];
|
|
901
|
+
const EtoroOfficial = "0x61ec01ad0937ebc10d448d259a2bbb1556b61e38".toLowerCase();
|
|
902
|
+
const FoundationOfficial = "0x66582D24FEaD72555adaC681Cc621caCbB208324".toLowerCase();
|
|
1014
903
|
|
|
1015
904
|
const TEAM = [
|
|
1016
905
|
"0x5AeE2397b39B479B72bcfbDA114512BD3329E5aC",
|
|
@@ -1045,24 +934,24 @@ export const airdrop = (
|
|
|
1045
934
|
|
|
1046
935
|
ETORO.forEach(addr => delete balances[addr]);
|
|
1047
936
|
|
|
1048
|
-
let toTree: Array<
|
|
1049
|
-
[
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
937
|
+
let toTree: Array<[string, number, boolean, number, number, number, number]> = Object.entries(balances).map(
|
|
938
|
+
([addr, data]) => {
|
|
939
|
+
let rep =
|
|
940
|
+
data.claimRepShare * CLAIMER_REP_ALLOCATION +
|
|
941
|
+
data.gdRepShare * HOLDER_REP_ALLOCATION +
|
|
942
|
+
data.stakeRepShare * STAKER_REP_ALLOCATION;
|
|
943
|
+
|
|
944
|
+
return [
|
|
945
|
+
addr,
|
|
946
|
+
rep,
|
|
947
|
+
!data.isNotContract,
|
|
948
|
+
data.claimRepShare * CLAIMER_REP_ALLOCATION,
|
|
949
|
+
data.gdRepShare * HOLDER_REP_ALLOCATION,
|
|
950
|
+
data.stakeRepShare * STAKER_REP_ALLOCATION,
|
|
951
|
+
0
|
|
952
|
+
];
|
|
953
|
+
}
|
|
954
|
+
);
|
|
1066
955
|
|
|
1067
956
|
//split etoro's rep between team,etoro and foundation
|
|
1068
957
|
const foundationEtoroRepShare = 8640000;
|
|
@@ -1072,15 +961,7 @@ export const airdrop = (
|
|
|
1072
961
|
foundationRecord[6] = foundationEtoroRepShare;
|
|
1073
962
|
console.log("Foundation updated record:", foundationRecord);
|
|
1074
963
|
|
|
1075
|
-
const etoroRecord: [
|
|
1076
|
-
string,
|
|
1077
|
-
number,
|
|
1078
|
-
boolean,
|
|
1079
|
-
number,
|
|
1080
|
-
number,
|
|
1081
|
-
number,
|
|
1082
|
-
number
|
|
1083
|
-
] = [
|
|
964
|
+
const etoroRecord: [string, number, boolean, number, number, number, number] = [
|
|
1084
965
|
EtoroOfficial,
|
|
1085
966
|
foundationEtoroRepShare,
|
|
1086
967
|
false,
|
|
@@ -1128,11 +1009,7 @@ export const airdrop = (
|
|
|
1128
1009
|
console.log({
|
|
1129
1010
|
precentile: q * 100 + "%",
|
|
1130
1011
|
addresses: (sorted.length * q).toFixed(0),
|
|
1131
|
-
rep:
|
|
1132
|
-
quantile(sorted, q) /
|
|
1133
|
-
(CLAIMER_REP_ALLOCATION +
|
|
1134
|
-
HOLDER_REP_ALLOCATION +
|
|
1135
|
-
STAKER_REP_ALLOCATION)
|
|
1012
|
+
rep: quantile(sorted, q) / (CLAIMER_REP_ALLOCATION + HOLDER_REP_ALLOCATION + STAKER_REP_ALLOCATION)
|
|
1136
1013
|
})
|
|
1137
1014
|
);
|
|
1138
1015
|
|
|
@@ -1145,10 +1022,7 @@ export const airdrop = (
|
|
|
1145
1022
|
})
|
|
1146
1023
|
.split(".")[0];
|
|
1147
1024
|
const hash = ethers.utils.keccak256(
|
|
1148
|
-
ethers.utils.defaultAbiCoder.encode(
|
|
1149
|
-
["address", "uint256"],
|
|
1150
|
-
[e[0], repInWei]
|
|
1151
|
-
)
|
|
1025
|
+
ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [e[0], repInWei])
|
|
1152
1026
|
);
|
|
1153
1027
|
treeData[e[0]] = {
|
|
1154
1028
|
rep: repInWei,
|
|
@@ -1176,9 +1050,7 @@ export const airdrop = (
|
|
|
1176
1050
|
1
|
|
1177
1051
|
);
|
|
1178
1052
|
|
|
1179
|
-
const lastProof = merkleTree
|
|
1180
|
-
.getProof(elements[elements.length - 1])
|
|
1181
|
-
.map(_ => _.toString("hex"));
|
|
1053
|
+
const lastProof = merkleTree.getProof(elements[elements.length - 1]).map(_ => _.toString("hex"));
|
|
1182
1054
|
const lastValidProof = checkProofOrdered(
|
|
1183
1055
|
lastProof.map(_ => Buffer.from(_, "hex")),
|
|
1184
1056
|
merkleTree.getRoot(),
|
|
@@ -1230,10 +1102,7 @@ export const airdrop = (
|
|
|
1230
1102
|
const proof = merkleTree.getProof(proofFor);
|
|
1231
1103
|
const proofIndex = entries.findIndex(_ => _[1].hash === addrData.hash) + 1;
|
|
1232
1104
|
|
|
1233
|
-
console.log(
|
|
1234
|
-
"checkProof:",
|
|
1235
|
-
checkProofOrdered(proof, merkleTree.getRoot(), proofFor, proofIndex)
|
|
1236
|
-
);
|
|
1105
|
+
console.log("checkProof:", checkProofOrdered(proof, merkleTree.getRoot(), proofFor, proofIndex));
|
|
1237
1106
|
const hexProof = proof.map(_ => "0x" + _.toString("hex"));
|
|
1238
1107
|
console.log({ proofIndex, proof: hexProof, [addr]: addrData });
|
|
1239
1108
|
};
|
|
@@ -9,7 +9,6 @@ import { MerkleTree } from "merkletreejs";
|
|
|
9
9
|
import PromisePool from "async-promise-pool";
|
|
10
10
|
import { ethers as Ethers } from "hardhat";
|
|
11
11
|
import { BigNumber } from "ethers";
|
|
12
|
-
import fetch from "node-fetch";
|
|
13
12
|
|
|
14
13
|
const quantile = (sorted, q) => {
|
|
15
14
|
const pos = (sorted.length - 1) * q;
|
|
@@ -22,18 +21,11 @@ const quantile = (sorted, q) => {
|
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
export const airdrop = (ethers: typeof Ethers) => {
|
|
25
|
-
const fuseProvider = new ethers.providers.JsonRpcProvider(
|
|
26
|
-
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
"https://eth-eu.0xfast.com/rpc/free"
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
const cfProvider = new ethers.providers.InfuraProvider(
|
|
34
|
-
1,
|
|
35
|
-
"143f9cf968fe4c3da0db77ff525e0da4"
|
|
36
|
-
);
|
|
24
|
+
const fuseProvider = new ethers.providers.JsonRpcProvider("https://rpc.fuse.io");
|
|
25
|
+
|
|
26
|
+
const zxfastProvider = new ethers.providers.JsonRpcProvider("https://eth-eu.0xfast.com/rpc/free");
|
|
27
|
+
|
|
28
|
+
const cfProvider = new ethers.providers.InfuraProvider(1, "143f9cf968fe4c3da0db77ff525e0da4");
|
|
37
29
|
const goodActiveVotes = async (network = "fuse") => {
|
|
38
30
|
let balances = [];
|
|
39
31
|
|
|
@@ -45,9 +37,7 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
45
37
|
|
|
46
38
|
const graphQuery = async (start, skip, step = EPOCH) => {
|
|
47
39
|
const query = `{
|
|
48
|
-
goodBalances(first: 1000 skip:${skip} where: { memberSince_gte: ${start} memberSince_lt:${
|
|
49
|
-
start + step
|
|
50
|
-
} }) {
|
|
40
|
+
goodBalances(first: 1000 skip:${skip} where: { memberSince_gte: ${start} memberSince_lt:${start + step} }) {
|
|
51
41
|
id
|
|
52
42
|
coreBalance
|
|
53
43
|
totalVotes
|
|
@@ -64,16 +54,11 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
64
54
|
body: JSON.stringify({ query })
|
|
65
55
|
}).then(_ => _.json());
|
|
66
56
|
errors && console.log({ errors });
|
|
67
|
-
if (
|
|
68
|
-
errors?.[0]?.message ===
|
|
69
|
-
"The `skip` argument must be between 0 and 5000, but is 6000"
|
|
70
|
-
) {
|
|
57
|
+
if (errors?.[0]?.message === "The `skip` argument must be between 0 and 5000, but is 6000") {
|
|
71
58
|
throw new Error("skip");
|
|
72
59
|
}
|
|
73
60
|
if (data?.goodBalances?.length === 1000) {
|
|
74
|
-
return data.goodBalances.concat(
|
|
75
|
-
await graphQuery(start, skip + 1000, step)
|
|
76
|
-
);
|
|
61
|
+
return data.goodBalances.concat(await graphQuery(start, skip + 1000, step));
|
|
77
62
|
}
|
|
78
63
|
return data.goodBalances || [];
|
|
79
64
|
} catch (error) {
|
|
@@ -111,11 +96,7 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
111
96
|
await pool.all();
|
|
112
97
|
console.log(`total ${network} GOOD Holders:`, balances.length, {
|
|
113
98
|
uniques: uniq(balances.map(_ => _.id)).length,
|
|
114
|
-
delegatees: uniq(
|
|
115
|
-
balances
|
|
116
|
-
.filter(_ => Number(_.coreBalance) < Number(_.totalVotes))
|
|
117
|
-
.map(_ => _.id)
|
|
118
|
-
).length,
|
|
99
|
+
delegatees: uniq(balances.filter(_ => Number(_.coreBalance) < Number(_.totalVotes)).map(_ => _.id)).length,
|
|
119
100
|
sample: balances.slice(0, 5)
|
|
120
101
|
});
|
|
121
102
|
|
|
@@ -128,10 +109,7 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
128
109
|
rep: record.activeVotes,
|
|
129
110
|
hash: ethers.utils.keccak256(
|
|
130
111
|
ethers.utils.keccak256(
|
|
131
|
-
ethers.utils.defaultAbiCoder.encode(
|
|
132
|
-
["address", "uint256"],
|
|
133
|
-
[record.id, record.activeVotes]
|
|
134
|
-
)
|
|
112
|
+
ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [record.id, record.activeVotes])
|
|
135
113
|
)
|
|
136
114
|
)
|
|
137
115
|
};
|
|
@@ -140,9 +118,7 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
140
118
|
`goodCheckpoints/goodCheckpoint_${network}.json`,
|
|
141
119
|
JSON.stringify({ treeData, balances, until: Date.now() })
|
|
142
120
|
);
|
|
143
|
-
console.log(
|
|
144
|
-
balances.filter(_ => Number(_.coreBalance) < Number(_.totalVotes))
|
|
145
|
-
);
|
|
121
|
+
console.log(balances.filter(_ => Number(_.coreBalance) < Number(_.totalVotes)));
|
|
146
122
|
};
|
|
147
123
|
|
|
148
124
|
const collectAirdropData = async () => {
|
|
@@ -157,33 +133,15 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
157
133
|
for (let blockChunk of chunk(blocks, 10)) {
|
|
158
134
|
// Get the filter (the second null could be omitted)
|
|
159
135
|
const ps = blockChunk.map(async (bc: number) => {
|
|
160
|
-
const logs = await good
|
|
161
|
-
.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
Math.min(bc + step - 1, LAST_BLOCK)
|
|
165
|
-
)
|
|
166
|
-
.catch(e => {
|
|
167
|
-
console.log("block transfer logs failed retrying...", bc);
|
|
168
|
-
return good.queryFilter(
|
|
169
|
-
good.filters.Mint(),
|
|
170
|
-
bc,
|
|
171
|
-
Math.min(bc + step - 1, LAST_BLOCK)
|
|
172
|
-
);
|
|
173
|
-
});
|
|
136
|
+
const logs = await good.queryFilter(good.filters.Mint(), bc, Math.min(bc + step - 1, LAST_BLOCK)).catch(e => {
|
|
137
|
+
console.log("block transfer logs failed retrying...", bc);
|
|
138
|
+
return good.queryFilter(good.filters.Mint(), bc, Math.min(bc + step - 1, LAST_BLOCK));
|
|
139
|
+
});
|
|
174
140
|
const claimedLogs = await good
|
|
175
|
-
.queryFilter(
|
|
176
|
-
good.filters.StateHashProof(),
|
|
177
|
-
bc,
|
|
178
|
-
Math.min(bc + step - 1, LAST_BLOCK)
|
|
179
|
-
)
|
|
141
|
+
.queryFilter(good.filters.StateHashProof(), bc, Math.min(bc + step - 1, LAST_BLOCK))
|
|
180
142
|
.catch(e => {
|
|
181
143
|
console.log("block transfer logs failed retrying...", bc);
|
|
182
|
-
return good.queryFilter(
|
|
183
|
-
good.filters.StateHashProof(),
|
|
184
|
-
bc,
|
|
185
|
-
Math.min(bc + step - 1, LAST_BLOCK)
|
|
186
|
-
);
|
|
144
|
+
return good.queryFilter(good.filters.StateHashProof(), bc, Math.min(bc + step - 1, LAST_BLOCK));
|
|
187
145
|
});
|
|
188
146
|
console.log("found logs:", claimedLogs.length, logs.length, bc);
|
|
189
147
|
return logs.concat(claimedLogs);
|
|
@@ -201,20 +159,14 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
201
159
|
let totalMints = ethers.constants.Zero;
|
|
202
160
|
logs.forEach(l => {
|
|
203
161
|
if (l.event === "Mint") {
|
|
204
|
-
mints[l.args._to.toLowerCase()] = (
|
|
205
|
-
|
|
206
|
-
)
|
|
162
|
+
mints[l.args._to.toLowerCase()] = (mints[l.args._to.toLowerCase()] || BigNumber.from("0")).add(
|
|
163
|
+
l.args._amount
|
|
164
|
+
);
|
|
207
165
|
totalMints = totalMints.add(l.args._amount);
|
|
208
166
|
} else claims[l.args.user.toLowerCase()] = l.args.repBalance.toString();
|
|
209
167
|
});
|
|
210
|
-
Object.entries(mints).forEach(
|
|
211
|
-
|
|
212
|
-
(result[k] = { claim: "0", ...result[k], mint: v.toString() })
|
|
213
|
-
);
|
|
214
|
-
Object.entries(claims).forEach(
|
|
215
|
-
([k, v]) =>
|
|
216
|
-
(result[k] = { mint: "0", ...result[k], claim: v.toString() })
|
|
217
|
-
);
|
|
168
|
+
Object.entries(mints).forEach(([k, v]) => (result[k] = { claim: "0", ...result[k], mint: v.toString() }));
|
|
169
|
+
Object.entries(claims).forEach(([k, v]) => (result[k] = { mint: "0", ...result[k], claim: v.toString() }));
|
|
218
170
|
console.log({ result, totalMints: totalMints.toString() });
|
|
219
171
|
fs.writeFileSync("goodCheckpointMainnet.json", JSON.stringify(result));
|
|
220
172
|
};
|
|
@@ -227,33 +179,21 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
227
179
|
const buildMerkleTree = async () => {
|
|
228
180
|
const buildTree = async (network = "fuse") => {
|
|
229
181
|
const good = await ethers
|
|
230
|
-
.getContractAt(
|
|
231
|
-
"GReputation",
|
|
232
|
-
"0x603B8C0F110E037b51A381CBCacAbb8d6c6E4543"
|
|
233
|
-
)
|
|
182
|
+
.getContractAt("GReputation", "0x603B8C0F110E037b51A381CBCacAbb8d6c6E4543")
|
|
234
183
|
.then(_ => _.connect(network === "fuse" ? fuseProvider : cfProvider));
|
|
235
184
|
|
|
236
|
-
const checkpoint = JSON.parse(
|
|
237
|
-
fs
|
|
238
|
-
.readFileSync(`goodCheckpoints/goodCheckpoint_${network}.json`)
|
|
239
|
-
.toString()
|
|
240
|
-
);
|
|
185
|
+
const checkpoint = JSON.parse(fs.readFileSync(`goodCheckpoints/goodCheckpoint_${network}.json`).toString());
|
|
241
186
|
|
|
242
187
|
const treeData = checkpoint.treeData;
|
|
243
188
|
|
|
244
|
-
let toTree: Array<[string, BigNumber]> = Object.entries(treeData).map(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
);
|
|
189
|
+
let toTree: Array<[string, BigNumber]> = Object.entries(treeData).map(([k, v]) => {
|
|
190
|
+
return [k, BigNumber.from((v as any).rep)];
|
|
191
|
+
});
|
|
249
192
|
|
|
250
193
|
toTree = toTree.sort((a, b) => (a[1].gte(b[1]) ? 1 : -1)).reverse();
|
|
251
194
|
// console.log({ toTree });
|
|
252
195
|
// const topContracts = toTree.filter(_ => _[2] === true);
|
|
253
|
-
const totalReputation = toTree.reduce(
|
|
254
|
-
(c, a) => c.add(a[1]),
|
|
255
|
-
BigNumber.from(0)
|
|
256
|
-
);
|
|
196
|
+
const totalReputation = toTree.reduce((c, a) => c.add(a[1]), BigNumber.from(0));
|
|
257
197
|
const totalSupply = (await good.totalSupply()).toString();
|
|
258
198
|
console.log({
|
|
259
199
|
totalSupply,
|
|
@@ -271,9 +211,7 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
271
211
|
precentile: q * 100 + "%",
|
|
272
212
|
addresses: (sorted.length * q).toFixed(0),
|
|
273
213
|
quantileRep,
|
|
274
|
-
rep:
|
|
275
|
-
Number(quantileRep.div(1e10).toString()) /
|
|
276
|
-
Number(totalReputation.div(1e10).toString())
|
|
214
|
+
rep: Number(quantileRep.div(1e10).toString()) / Number(totalReputation.div(1e10).toString())
|
|
277
215
|
});
|
|
278
216
|
});
|
|
279
217
|
const items = Object.values(treeData);
|
|
@@ -296,16 +234,10 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
296
234
|
const validProof = merkleTree.verify(proof, elements[0], merkleRoot);
|
|
297
235
|
|
|
298
236
|
const lastProof = merkleTree.getHexProof(elements[elements.length - 1]);
|
|
299
|
-
const lastValidProof = merkleTree.verify(
|
|
300
|
-
lastProof,
|
|
301
|
-
elements[elements.length - 1],
|
|
302
|
-
merkleRoot
|
|
303
|
-
);
|
|
237
|
+
const lastValidProof = merkleTree.verify(lastProof, elements[elements.length - 1], merkleRoot);
|
|
304
238
|
|
|
305
239
|
//check for possible address preimage
|
|
306
|
-
const danger = (merkleTree.getHexLayers() as any).map(_ =>
|
|
307
|
-
_.find(_ => _.startsWith("0x000000"))
|
|
308
|
-
);
|
|
240
|
+
const danger = (merkleTree.getHexLayers() as any).map(_ => _.find(_ => _.startsWith("0x000000")));
|
|
309
241
|
|
|
310
242
|
console.log({
|
|
311
243
|
danger,
|
|
@@ -322,10 +254,7 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
322
254
|
|
|
323
255
|
checkpoint.merkleRoot = merkleRoot;
|
|
324
256
|
checkpoint.totalSupply = totalSupply;
|
|
325
|
-
fs.writeFileSync(
|
|
326
|
-
"goodCheckpoints/goodCheckpoint_fuse.json",
|
|
327
|
-
JSON.stringify(checkpoint)
|
|
328
|
-
);
|
|
257
|
+
fs.writeFileSync("goodCheckpoints/goodCheckpoint_fuse.json", JSON.stringify(checkpoint));
|
|
329
258
|
};
|
|
330
259
|
|
|
331
260
|
await buildTree();
|
|
@@ -333,9 +262,7 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
333
262
|
};
|
|
334
263
|
|
|
335
264
|
const getProof = addr => {
|
|
336
|
-
const { treeData, merkleRoot } = JSON.parse(
|
|
337
|
-
fs.readFileSync("airdrop/airdrop.json").toString()
|
|
338
|
-
);
|
|
265
|
+
const { treeData, merkleRoot } = JSON.parse(fs.readFileSync("airdrop/airdrop.json").toString());
|
|
339
266
|
|
|
340
267
|
let entries = Object.entries(treeData as Tree);
|
|
341
268
|
let elements = entries.map(e => Buffer.from(e[1].hash.slice(2), "hex"));
|
|
@@ -355,14 +282,10 @@ export const airdrop = (ethers: typeof Ethers) => {
|
|
|
355
282
|
const proofFor = Buffer.from(addrData.hash.slice(2), "hex");
|
|
356
283
|
|
|
357
284
|
const proof = merkleTree.getHexProof(proofFor);
|
|
358
|
-
const proofIndex =
|
|
359
|
-
elements.findIndex(_ => "0x" + _.toString("hex") === addrData.hash) + 1;
|
|
285
|
+
const proofIndex = elements.findIndex(_ => "0x" + _.toString("hex") === addrData.hash) + 1;
|
|
360
286
|
|
|
361
287
|
console.log({ proofIndex, proof, [addr]: addrData });
|
|
362
|
-
console.log(
|
|
363
|
-
"checkProof:",
|
|
364
|
-
merkleTree.verify(proof, proofFor, calcMerkleRoot)
|
|
365
|
-
);
|
|
288
|
+
console.log("checkProof:", merkleTree.verify(proof, proofFor, calcMerkleRoot));
|
|
366
289
|
};
|
|
367
290
|
|
|
368
291
|
return { buildMerkleTree, collectAirdropData, getProof };
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import { range, chunk } from "lodash";
|
|
2
2
|
import { ethers as Ethers } from "hardhat";
|
|
3
|
-
import fetch from "node-fetch";
|
|
4
3
|
|
|
5
4
|
const ONE_DAY = 24 * 60 * 60;
|
|
6
5
|
|
|
7
6
|
const main = async () => {
|
|
8
7
|
const signer = (await Ethers.getSigners())[0];
|
|
9
8
|
console.log("signer:", signer.address);
|
|
10
|
-
const ubiScheme = new Ethers.Contract(
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
).
|
|
14
|
-
const twoWeeksAgo =
|
|
15
|
-
parseInt((Date.now() / 1000).toFixed(0)) - 24 * 60 * 60 * 14;
|
|
9
|
+
const ubiScheme = new Ethers.Contract("0xD7aC544F8A570C4d8764c3AAbCF6870CBD960D0D", [
|
|
10
|
+
"function fishMulti(address[] tofish)"
|
|
11
|
+
]).connect(signer);
|
|
12
|
+
const twoWeeksAgo = parseInt((Date.now() / 1000).toFixed(0)) - 24 * 60 * 60 * 14;
|
|
16
13
|
|
|
17
14
|
const daysAgo: number[] = range(0, 180, 1);
|
|
18
15
|
let curDay = twoWeeksAgo;
|
|
@@ -27,19 +24,12 @@ const main = async () => {
|
|
|
27
24
|
}
|
|
28
25
|
`;
|
|
29
26
|
|
|
30
|
-
console.log(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
JSON.stringify({ query })
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"https://api.thegraph.com/subgraphs/name/gooddollar/gooddollarfuse",
|
|
37
|
-
{
|
|
38
|
-
method: "post",
|
|
39
|
-
body: JSON.stringify({ query }),
|
|
40
|
-
headers: { "Content-Type": "application/json" }
|
|
41
|
-
}
|
|
42
|
-
).then(_ => _.json());
|
|
27
|
+
console.log("fetching inactive users since:", { curDay, day }, JSON.stringify({ query }));
|
|
28
|
+
const { walletStats } = await fetch("https://api.thegraph.com/subgraphs/name/gooddollar/gooddollarfuse", {
|
|
29
|
+
method: "post",
|
|
30
|
+
body: JSON.stringify({ query }),
|
|
31
|
+
headers: { "Content-Type": "application/json" }
|
|
32
|
+
}).then(_ => _.json());
|
|
43
33
|
|
|
44
34
|
console.log("got inactive wallets:", walletStats.length);
|
|
45
35
|
const accounts = walletStats.map(_ => _.id);
|