@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.
@@ -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.10.1",
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",
@@ -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,