@gooddollar/goodprotocol 2.0.5-beta.9 → 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 +7 -3
- 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/upgradeToV2/upgradeToV2.ts +54 -208
- package/scripts/voltageswaps.ts +0 -1
- package/yarn.lock +2 -1
|
@@ -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);
|