@snapshot-labs/snapshot.js 0.10.1 → 0.11.1
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/dist/index.d.ts +8 -0
- package/dist/schemas/index.d.ts +8 -0
- package/dist/snapshot.cjs.js +119 -65
- package/dist/snapshot.esm.js +118 -65
- package/dist/snapshot.min.js +3 -3
- package/dist/utils/delegation.d.ts +18 -0
- package/dist/utils.d.ts +2 -11
- package/package.json +2 -1
- package/src/schemas/space.json +10 -2
- package/src/utils/delegation.ts +117 -0
- package/src/utils.ts +5 -51
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const SNAPSHOT_SUBGRAPH_URL: {
|
|
2
|
+
1: string;
|
|
3
|
+
5: string;
|
|
4
|
+
10: string;
|
|
5
|
+
56: string;
|
|
6
|
+
100: string;
|
|
7
|
+
137: string;
|
|
8
|
+
250: string;
|
|
9
|
+
42161: string;
|
|
10
|
+
};
|
|
11
|
+
declare type Delegation = {
|
|
12
|
+
delegator: string;
|
|
13
|
+
delegate: string;
|
|
14
|
+
space: string;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
};
|
|
17
|
+
export default function getDelegatesBySpace(network: string, space: string, snapshot?: string | number, options?: any): Promise<Delegation[]>;
|
|
18
|
+
export {};
|
package/dist/utils.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { getSnapshots } from './utils/blockfinder';
|
|
|
3
3
|
import getProvider from './utils/provider';
|
|
4
4
|
import { signMessage, getBlockNumber } from './utils/web3';
|
|
5
5
|
import { getHash, verify } from './sign/utils';
|
|
6
|
+
import getDelegatesBySpace, { SNAPSHOT_SUBGRAPH_URL } from './utils/delegation';
|
|
6
7
|
interface Options {
|
|
7
8
|
url?: string;
|
|
8
9
|
}
|
|
@@ -11,16 +12,6 @@ interface Strategy {
|
|
|
11
12
|
network?: string;
|
|
12
13
|
params: any;
|
|
13
14
|
}
|
|
14
|
-
export declare const SNAPSHOT_SUBGRAPH_URL: {
|
|
15
|
-
1: string;
|
|
16
|
-
5: string;
|
|
17
|
-
10: string;
|
|
18
|
-
56: string;
|
|
19
|
-
100: string;
|
|
20
|
-
137: string;
|
|
21
|
-
250: string;
|
|
22
|
-
42161: string;
|
|
23
|
-
};
|
|
24
15
|
export declare function call(provider: any, abi: any[], call: any[], options?: any): Promise<any>;
|
|
25
16
|
export declare function multicall(network: string, provider: any, abi: any[], calls: any[], options?: any): Promise<any>;
|
|
26
17
|
export declare function subgraphRequest(url: string, query: any, options?: any): Promise<any>;
|
|
@@ -40,10 +31,10 @@ export declare function getEnsTextRecord(ens: string, record: string, network?:
|
|
|
40
31
|
export declare function getSpaceUri(id: string, network?: string, options?: any): Promise<string | null>;
|
|
41
32
|
export declare function getEnsOwner(ens: string, network?: string, options?: any): Promise<string | null>;
|
|
42
33
|
export declare function getSpaceController(id: string, network?: string, options?: any): Promise<string | null>;
|
|
43
|
-
export declare function getDelegatesBySpace(network: string, space: string, snapshot?: string, options?: any): Promise<never[]>;
|
|
44
34
|
export declare function clone(item: any): any;
|
|
45
35
|
export declare function sleep(time: any): Promise<unknown>;
|
|
46
36
|
export declare function getNumberWithOrdinal(n: any): string;
|
|
37
|
+
export { getDelegatesBySpace, SNAPSHOT_SUBGRAPH_URL };
|
|
47
38
|
declare const _default: {
|
|
48
39
|
call: typeof call;
|
|
49
40
|
multicall: typeof multicall;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snapshot-labs/snapshot.js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"repository": "snapshot-labs/snapshot.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/snapshot.cjs.js",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"@ethersproject/units": "^5.7.0",
|
|
19
19
|
"@ethersproject/wallet": "^5.6.2",
|
|
20
20
|
"ajv": "^8.11.0",
|
|
21
|
+
"ajv-errors": "^3.0.0",
|
|
21
22
|
"ajv-formats": "^2.1.1",
|
|
22
23
|
"cross-fetch": "^3.1.6",
|
|
23
24
|
"json-to-graphql-query": "^2.2.4",
|
package/src/schemas/space.json
CHANGED
|
@@ -282,11 +282,19 @@
|
|
|
282
282
|
"properties": {
|
|
283
283
|
"delay": {
|
|
284
284
|
"type": "integer",
|
|
285
|
-
"minimum": 0
|
|
285
|
+
"minimum": 0,
|
|
286
|
+
"maximum": 2592000,
|
|
287
|
+
"errorMessage": {
|
|
288
|
+
"maximum": "Delay must be less than 30 days"
|
|
289
|
+
}
|
|
286
290
|
},
|
|
287
291
|
"period": {
|
|
288
292
|
"type": "integer",
|
|
289
|
-
"minimum": 0
|
|
293
|
+
"minimum": 0,
|
|
294
|
+
"maximum": 15552000,
|
|
295
|
+
"errorMessage": {
|
|
296
|
+
"maximum": "Delay must be less than 180 days"
|
|
297
|
+
}
|
|
290
298
|
},
|
|
291
299
|
"type": {
|
|
292
300
|
"type": "string",
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { subgraphRequest } from '../utils';
|
|
2
|
+
import delegationSubgraphs from '../delegationSubgraphs.json';
|
|
3
|
+
|
|
4
|
+
export const SNAPSHOT_SUBGRAPH_URL = delegationSubgraphs;
|
|
5
|
+
const PAGE_SIZE = 1000;
|
|
6
|
+
|
|
7
|
+
type Delegation = {
|
|
8
|
+
delegator: string;
|
|
9
|
+
delegate: string;
|
|
10
|
+
space: string;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default async function getDelegatesBySpace(
|
|
15
|
+
network: string,
|
|
16
|
+
space: string,
|
|
17
|
+
snapshot: string | number = 'latest',
|
|
18
|
+
options: any = {}
|
|
19
|
+
) {
|
|
20
|
+
const subgraphUrl = options.subgraphUrl || SNAPSHOT_SUBGRAPH_URL[network];
|
|
21
|
+
if (!subgraphUrl) {
|
|
22
|
+
return Promise.reject(
|
|
23
|
+
`Delegation subgraph not available for network ${network}`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let pivot = 0;
|
|
28
|
+
const result = new Map<string, Delegation>();
|
|
29
|
+
const spaceIn = buildSpaceIn(space);
|
|
30
|
+
|
|
31
|
+
while (true) {
|
|
32
|
+
const newResults = await fetchData({
|
|
33
|
+
url: subgraphUrl,
|
|
34
|
+
spaces: spaceIn,
|
|
35
|
+
pivot,
|
|
36
|
+
snapshot
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (checkAllDuplicates(newResults)) {
|
|
40
|
+
throw new Error('Unable to paginate delegation');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
newResults.forEach((delegation) => {
|
|
44
|
+
concatUniqueDelegation(result, delegation);
|
|
45
|
+
pivot = delegation.timestamp;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (newResults.length < PAGE_SIZE) break;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return [...result.values()];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function checkAllDuplicates(delegations: Delegation[]) {
|
|
55
|
+
return (
|
|
56
|
+
delegations.length === PAGE_SIZE &&
|
|
57
|
+
delegations[0].timestamp === delegations[delegations.length - 1].timestamp
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function delegationKey(delegation: Delegation) {
|
|
62
|
+
return `${delegation.delegator}-${delegation.delegate}-${delegation.space}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function concatUniqueDelegation(
|
|
66
|
+
result: Map<string, Delegation>,
|
|
67
|
+
delegation: Delegation
|
|
68
|
+
): void {
|
|
69
|
+
const key = delegationKey(delegation);
|
|
70
|
+
if (!result.has(key)) {
|
|
71
|
+
result.set(key, delegation);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function buildSpaceIn(space: string) {
|
|
76
|
+
const spaces = ['', space];
|
|
77
|
+
if (space.includes('.eth')) spaces.push(space.replace('.eth', ''));
|
|
78
|
+
|
|
79
|
+
return spaces;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function fetchData({
|
|
83
|
+
url,
|
|
84
|
+
spaces,
|
|
85
|
+
pivot,
|
|
86
|
+
snapshot
|
|
87
|
+
}: {
|
|
88
|
+
url: string;
|
|
89
|
+
spaces: string[];
|
|
90
|
+
pivot: number;
|
|
91
|
+
snapshot: string | number;
|
|
92
|
+
}): Promise<Delegation[]> {
|
|
93
|
+
const params: any = {
|
|
94
|
+
delegations: {
|
|
95
|
+
__args: {
|
|
96
|
+
where: {
|
|
97
|
+
space_in: spaces,
|
|
98
|
+
timestamp_gte: pivot
|
|
99
|
+
},
|
|
100
|
+
first: PAGE_SIZE,
|
|
101
|
+
skip: 0,
|
|
102
|
+
orderBy: 'timestamp',
|
|
103
|
+
orderDirection: 'asc'
|
|
104
|
+
},
|
|
105
|
+
delegator: true,
|
|
106
|
+
space: true,
|
|
107
|
+
delegate: true,
|
|
108
|
+
timestamp: true
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
if (snapshot !== 'latest') {
|
|
113
|
+
params.delegations.__args.block = { number: snapshot };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return (await subgraphRequest(url, params)).delegations || [];
|
|
117
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { namehash, ensNormalize } from '@ethersproject/hash';
|
|
|
7
7
|
import { jsonToGraphQLQuery } from 'json-to-graphql-query';
|
|
8
8
|
import Ajv from 'ajv';
|
|
9
9
|
import addFormats from 'ajv-formats';
|
|
10
|
+
import addErrors from 'ajv-errors';
|
|
10
11
|
import Multicaller from './utils/multicaller';
|
|
11
12
|
import { getSnapshots } from './utils/blockfinder';
|
|
12
13
|
import getProvider from './utils/provider';
|
|
@@ -14,8 +15,8 @@ import { signMessage, getBlockNumber } from './utils/web3';
|
|
|
14
15
|
import { getHash, verify } from './sign/utils';
|
|
15
16
|
import gateways from './gateways.json';
|
|
16
17
|
import networks from './networks.json';
|
|
17
|
-
import delegationSubgraphs from './delegationSubgraphs.json';
|
|
18
18
|
import voting from './voting';
|
|
19
|
+
import getDelegatesBySpace, { SNAPSHOT_SUBGRAPH_URL } from './utils/delegation';
|
|
19
20
|
|
|
20
21
|
interface Options {
|
|
21
22
|
url?: string;
|
|
@@ -27,7 +28,6 @@ interface Strategy {
|
|
|
27
28
|
params: any;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
export const SNAPSHOT_SUBGRAPH_URL = delegationSubgraphs;
|
|
31
31
|
const ENS_RESOLVER_ABI = [
|
|
32
32
|
'function text(bytes32 node, string calldata key) external view returns (string memory)'
|
|
33
33
|
];
|
|
@@ -46,6 +46,7 @@ const ajv = new Ajv({
|
|
|
46
46
|
});
|
|
47
47
|
// @ts-ignore
|
|
48
48
|
addFormats(ajv);
|
|
49
|
+
addErrors(ajv);
|
|
49
50
|
|
|
50
51
|
ajv.addFormat('address', {
|
|
51
52
|
validate: (value: string) => {
|
|
@@ -572,55 +573,6 @@ export async function getSpaceController(
|
|
|
572
573
|
return await getEnsOwner(id, network, options);
|
|
573
574
|
}
|
|
574
575
|
|
|
575
|
-
export async function getDelegatesBySpace(
|
|
576
|
-
network: string,
|
|
577
|
-
space: string,
|
|
578
|
-
snapshot = 'latest',
|
|
579
|
-
options: any = {}
|
|
580
|
-
) {
|
|
581
|
-
const subgraphUrl = options.subgraphUrl || SNAPSHOT_SUBGRAPH_URL[network];
|
|
582
|
-
if (!subgraphUrl) {
|
|
583
|
-
return Promise.reject(
|
|
584
|
-
`Delegation subgraph not available for network ${network}`
|
|
585
|
-
);
|
|
586
|
-
}
|
|
587
|
-
const spaceIn = ['', space];
|
|
588
|
-
if (space.includes('.eth')) spaceIn.push(space.replace('.eth', ''));
|
|
589
|
-
|
|
590
|
-
const PAGE_SIZE = 1000;
|
|
591
|
-
let result = [];
|
|
592
|
-
let page = 0;
|
|
593
|
-
const params: any = {
|
|
594
|
-
delegations: {
|
|
595
|
-
__args: {
|
|
596
|
-
where: {
|
|
597
|
-
space_in: spaceIn
|
|
598
|
-
},
|
|
599
|
-
first: PAGE_SIZE,
|
|
600
|
-
skip: 0
|
|
601
|
-
},
|
|
602
|
-
delegator: true,
|
|
603
|
-
space: true,
|
|
604
|
-
delegate: true
|
|
605
|
-
}
|
|
606
|
-
};
|
|
607
|
-
if (snapshot !== 'latest') {
|
|
608
|
-
params.delegations.__args.block = { number: snapshot };
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
while (true) {
|
|
612
|
-
params.delegations.__args.skip = page * PAGE_SIZE;
|
|
613
|
-
|
|
614
|
-
const pageResult = await subgraphRequest(subgraphUrl, params);
|
|
615
|
-
const pageDelegations = pageResult.delegations || [];
|
|
616
|
-
result = result.concat(pageDelegations);
|
|
617
|
-
page++;
|
|
618
|
-
if (pageDelegations.length < PAGE_SIZE) break;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
return result;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
576
|
export function clone(item) {
|
|
625
577
|
return JSON.parse(JSON.stringify(item));
|
|
626
578
|
}
|
|
@@ -656,6 +608,8 @@ function inputError(message: string) {
|
|
|
656
608
|
return Promise.reject(new Error(message));
|
|
657
609
|
}
|
|
658
610
|
|
|
611
|
+
export { getDelegatesBySpace, SNAPSHOT_SUBGRAPH_URL };
|
|
612
|
+
|
|
659
613
|
export default {
|
|
660
614
|
call,
|
|
661
615
|
multicall,
|