@snapshot-labs/snapshot.js 0.11.22 → 0.11.23
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/snapshot.cjs.js +90 -56
- package/dist/snapshot.esm.js +90 -56
- package/dist/snapshot.min.js +3 -3
- package/dist/utils.d.ts +2 -1
- package/package.json +1 -1
- package/src/utils.spec.js +50 -30
- package/src/utils.ts +61 -28
package/dist/utils.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { getHash, verify } from './sign/utils';
|
|
|
6
6
|
import getDelegatesBySpace, { SNAPSHOT_SUBGRAPH_URL } from './utils/delegation';
|
|
7
7
|
interface Options {
|
|
8
8
|
url?: string;
|
|
9
|
+
headers?: any;
|
|
9
10
|
}
|
|
10
11
|
interface Strategy {
|
|
11
12
|
name: string;
|
|
@@ -21,7 +22,7 @@ export declare function ipfsGet(gateway: string, ipfsHash: string, protocolType?
|
|
|
21
22
|
export declare function sendTransaction(web3: any, contractAddress: string, abi: any[], action: string, params: any[], overrides?: {}): Promise<any>;
|
|
22
23
|
export declare function getScores(space: string, strategies: Strategy[], network: string, addresses: string[], snapshot?: number | string, scoreApiUrl?: string, options?: any): Promise<any>;
|
|
23
24
|
export declare function getVp(address: string, network: string, strategies: Strategy[], snapshot: number | 'latest', space: string, delegation: boolean, options?: Options): Promise<any>;
|
|
24
|
-
export declare function validate(validation: string, author: string, space: string, network: string, snapshot: number | 'latest', params: any, options
|
|
25
|
+
export declare function validate(validation: string, author: string, space: string, network: string, snapshot: number | 'latest', params: any, options?: Options): Promise<any>;
|
|
25
26
|
interface validateSchemaOptions {
|
|
26
27
|
snapshotEnv?: string;
|
|
27
28
|
spaceType?: string;
|
package/package.json
CHANGED
package/src/utils.spec.js
CHANGED
|
@@ -78,13 +78,14 @@ describe('utils', () => {
|
|
|
78
78
|
|
|
79
79
|
describe('when passing valid args', () => {
|
|
80
80
|
test('send a JSON-RPC payload to score-api', async () => {
|
|
81
|
+
const result = { result: 'OK' };
|
|
81
82
|
fetch.mockReturnValue({
|
|
82
|
-
|
|
83
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
83
84
|
});
|
|
84
85
|
|
|
85
86
|
expect(_validate({})).resolves;
|
|
86
87
|
expect(fetch).toHaveBeenCalledWith(
|
|
87
|
-
'https://score.snapshot.org',
|
|
88
|
+
'https://score.snapshot.org/',
|
|
88
89
|
expect.objectContaining({
|
|
89
90
|
body: JSON.stringify({
|
|
90
91
|
jsonrpc: '2.0',
|
|
@@ -96,13 +97,14 @@ describe('utils', () => {
|
|
|
96
97
|
});
|
|
97
98
|
|
|
98
99
|
test('send a POST request with JSON content-type', async () => {
|
|
100
|
+
const result = { result: 'OK' };
|
|
99
101
|
fetch.mockReturnValue({
|
|
100
|
-
|
|
102
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
101
103
|
});
|
|
102
104
|
|
|
103
105
|
expect(_validate({})).resolves;
|
|
104
106
|
expect(fetch).toHaveBeenCalledWith(
|
|
105
|
-
'https://score.snapshot.org',
|
|
107
|
+
'https://score.snapshot.org/',
|
|
106
108
|
expect.objectContaining({
|
|
107
109
|
method: 'POST',
|
|
108
110
|
headers: {
|
|
@@ -114,23 +116,28 @@ describe('utils', () => {
|
|
|
114
116
|
});
|
|
115
117
|
|
|
116
118
|
test('can customize the score-api url', () => {
|
|
119
|
+
const result = { result: 'OK' };
|
|
117
120
|
fetch.mockReturnValue({
|
|
118
|
-
|
|
121
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
119
122
|
});
|
|
120
123
|
|
|
121
124
|
expect(
|
|
122
125
|
_validate({ options: { url: 'https://snapshot.org/?apiKey=xxx' } })
|
|
123
126
|
).resolves;
|
|
124
127
|
expect(fetch).toHaveBeenCalledWith(
|
|
125
|
-
'https://snapshot.org
|
|
126
|
-
expect.
|
|
128
|
+
'https://snapshot.org/',
|
|
129
|
+
expect.objectContaining({
|
|
130
|
+
headers: expect.objectContaining({
|
|
131
|
+
'X-API-KEY': 'xxx'
|
|
132
|
+
})
|
|
133
|
+
})
|
|
127
134
|
);
|
|
128
135
|
});
|
|
129
136
|
|
|
130
137
|
test('returns the JSON-RPC result property', () => {
|
|
131
138
|
const result = { result: 'OK' };
|
|
132
139
|
fetch.mockReturnValue({
|
|
133
|
-
|
|
140
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
134
141
|
});
|
|
135
142
|
|
|
136
143
|
expect(_validate({})).resolves.toEqual('OK');
|
|
@@ -141,7 +148,7 @@ describe('utils', () => {
|
|
|
141
148
|
test('rejects with the JSON-RPC error object', () => {
|
|
142
149
|
const result = { error: { message: 'Oh no' } };
|
|
143
150
|
fetch.mockReturnValue({
|
|
144
|
-
|
|
151
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
145
152
|
});
|
|
146
153
|
|
|
147
154
|
expect(_validate({})).rejects.toEqual(result.error);
|
|
@@ -152,7 +159,7 @@ describe('utils', () => {
|
|
|
152
159
|
test('rejects with the error', () => {
|
|
153
160
|
const result = new Error('Oh no');
|
|
154
161
|
fetch.mockReturnValue({
|
|
155
|
-
|
|
162
|
+
text: () => {
|
|
156
163
|
throw result;
|
|
157
164
|
}
|
|
158
165
|
});
|
|
@@ -196,7 +203,7 @@ describe('utils', () => {
|
|
|
196
203
|
network ?? payload.network,
|
|
197
204
|
addresses ?? payload.addresses,
|
|
198
205
|
snapshot ?? payload.snapshot,
|
|
199
|
-
scoreApiUrl ?? 'https://score.snapshot.org',
|
|
206
|
+
scoreApiUrl ?? 'https://score.snapshot.org/',
|
|
200
207
|
options ?? {}
|
|
201
208
|
);
|
|
202
209
|
}
|
|
@@ -239,8 +246,9 @@ describe('utils', () => {
|
|
|
239
246
|
|
|
240
247
|
describe('when passing valid args', () => {
|
|
241
248
|
test('send a JSON-RPC payload to score-api', async () => {
|
|
249
|
+
const result = { result: 'OK' };
|
|
242
250
|
fetch.mockReturnValue({
|
|
243
|
-
|
|
251
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
244
252
|
});
|
|
245
253
|
|
|
246
254
|
expect(_getScores({})).resolves;
|
|
@@ -253,8 +261,9 @@ describe('utils', () => {
|
|
|
253
261
|
});
|
|
254
262
|
|
|
255
263
|
test('send a POST request with JSON content-type', async () => {
|
|
264
|
+
const result = { result: 'OK' };
|
|
256
265
|
fetch.mockReturnValue({
|
|
257
|
-
|
|
266
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
258
267
|
});
|
|
259
268
|
|
|
260
269
|
expect(_getScores({})).resolves;
|
|
@@ -270,23 +279,29 @@ describe('utils', () => {
|
|
|
270
279
|
);
|
|
271
280
|
});
|
|
272
281
|
|
|
273
|
-
test('can customize the score-api url', () => {
|
|
282
|
+
test('can customize the score-api url and if apiKey should be passed in headers', () => {
|
|
283
|
+
const result = { result: 'OK' };
|
|
274
284
|
fetch.mockReturnValue({
|
|
275
|
-
|
|
285
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
276
286
|
});
|
|
277
287
|
|
|
278
288
|
expect(_getScores({ scoreApiUrl: 'https://snapshot.org/?apiKey=xxx' }))
|
|
279
289
|
.resolves;
|
|
280
290
|
expect(fetch).toHaveBeenCalledWith(
|
|
281
|
-
'https://snapshot.org/api/scores
|
|
282
|
-
expect.
|
|
291
|
+
'https://snapshot.org/api/scores',
|
|
292
|
+
expect.objectContaining({
|
|
293
|
+
headers: expect.objectContaining({
|
|
294
|
+
'X-API-KEY': 'xxx'
|
|
295
|
+
})
|
|
296
|
+
})
|
|
283
297
|
);
|
|
284
298
|
});
|
|
285
299
|
|
|
286
300
|
test('returns the JSON-RPC result scores property', () => {
|
|
287
301
|
const result = { scores: 'SCORES', other: 'Other' };
|
|
288
302
|
fetch.mockReturnValue({
|
|
289
|
-
|
|
303
|
+
text: () =>
|
|
304
|
+
new Promise((resolve) => resolve(JSON.stringify({ result })))
|
|
290
305
|
});
|
|
291
306
|
|
|
292
307
|
expect(_getScores({})).resolves.toEqual('SCORES');
|
|
@@ -295,7 +310,8 @@ describe('utils', () => {
|
|
|
295
310
|
test('returns the JSON-RPC all properties', () => {
|
|
296
311
|
const result = { scores: 'SCORES', other: 'Other' };
|
|
297
312
|
fetch.mockReturnValue({
|
|
298
|
-
|
|
313
|
+
text: () =>
|
|
314
|
+
new Promise((resolve) => resolve(JSON.stringify({ result })))
|
|
299
315
|
});
|
|
300
316
|
|
|
301
317
|
expect(
|
|
@@ -308,7 +324,7 @@ describe('utils', () => {
|
|
|
308
324
|
test('rejects with the JSON-RPC error object', () => {
|
|
309
325
|
const result = { error: { message: 'Oh no' } };
|
|
310
326
|
fetch.mockReturnValue({
|
|
311
|
-
|
|
327
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
312
328
|
});
|
|
313
329
|
|
|
314
330
|
expect(_getScores({})).rejects.toEqual(result.error);
|
|
@@ -319,7 +335,7 @@ describe('utils', () => {
|
|
|
319
335
|
test('rejects with the error', () => {
|
|
320
336
|
const result = new Error('Oh no');
|
|
321
337
|
fetch.mockReturnValue({
|
|
322
|
-
|
|
338
|
+
text: () => {
|
|
323
339
|
throw result;
|
|
324
340
|
}
|
|
325
341
|
});
|
|
@@ -391,13 +407,14 @@ describe('utils', () => {
|
|
|
391
407
|
|
|
392
408
|
describe('when passing valid args', () => {
|
|
393
409
|
test('send a JSON-RPC payload to score-api', async () => {
|
|
410
|
+
const result = { result: 'OK' };
|
|
394
411
|
fetch.mockReturnValue({
|
|
395
|
-
|
|
412
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
396
413
|
});
|
|
397
414
|
|
|
398
415
|
expect(_getVp({})).resolves;
|
|
399
416
|
expect(fetch).toHaveBeenCalledWith(
|
|
400
|
-
'https://score.snapshot.org',
|
|
417
|
+
'https://score.snapshot.org/',
|
|
401
418
|
expect.objectContaining({
|
|
402
419
|
body: JSON.stringify({
|
|
403
420
|
jsonrpc: '2.0',
|
|
@@ -409,13 +426,14 @@ describe('utils', () => {
|
|
|
409
426
|
});
|
|
410
427
|
|
|
411
428
|
test('send a POST request with JSON content-type', async () => {
|
|
429
|
+
const result = { result: 'OK' };
|
|
412
430
|
fetch.mockReturnValue({
|
|
413
|
-
|
|
431
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
414
432
|
});
|
|
415
433
|
|
|
416
434
|
expect(_getVp({})).resolves;
|
|
417
435
|
expect(fetch).toHaveBeenCalledWith(
|
|
418
|
-
'https://score.snapshot.org',
|
|
436
|
+
'https://score.snapshot.org/',
|
|
419
437
|
expect.objectContaining({
|
|
420
438
|
method: 'POST',
|
|
421
439
|
headers: {
|
|
@@ -427,13 +445,14 @@ describe('utils', () => {
|
|
|
427
445
|
});
|
|
428
446
|
|
|
429
447
|
test('can customize the score-api url', () => {
|
|
448
|
+
const result = { result: 'OK' };
|
|
430
449
|
fetch.mockReturnValue({
|
|
431
|
-
|
|
450
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
432
451
|
});
|
|
433
452
|
|
|
434
453
|
expect(_getVp({ options: { url: 'https://snapshot.org' } })).resolves;
|
|
435
454
|
expect(fetch).toHaveBeenCalledWith(
|
|
436
|
-
'https://snapshot.org',
|
|
455
|
+
'https://snapshot.org/',
|
|
437
456
|
expect.anything()
|
|
438
457
|
);
|
|
439
458
|
});
|
|
@@ -441,7 +460,8 @@ describe('utils', () => {
|
|
|
441
460
|
test('returns the JSON-RPC result property', () => {
|
|
442
461
|
const result = { data: 'OK' };
|
|
443
462
|
fetch.mockReturnValue({
|
|
444
|
-
|
|
463
|
+
text: () =>
|
|
464
|
+
new Promise((resolve) => resolve(JSON.stringify({ result })))
|
|
445
465
|
});
|
|
446
466
|
|
|
447
467
|
expect(_getVp({})).resolves.toEqual(result);
|
|
@@ -452,7 +472,7 @@ describe('utils', () => {
|
|
|
452
472
|
test('rejects with the JSON-RPC error object', () => {
|
|
453
473
|
const result = { error: { message: 'Oh no' } };
|
|
454
474
|
fetch.mockReturnValue({
|
|
455
|
-
|
|
475
|
+
text: () => new Promise((resolve) => resolve(JSON.stringify(result)))
|
|
456
476
|
});
|
|
457
477
|
|
|
458
478
|
expect(_getVp({})).rejects.toEqual(result.error);
|
|
@@ -463,7 +483,7 @@ describe('utils', () => {
|
|
|
463
483
|
test('rejects with the error', () => {
|
|
464
484
|
const result = new Error('Oh no');
|
|
465
485
|
fetch.mockReturnValue({
|
|
466
|
-
|
|
486
|
+
text: () => {
|
|
467
487
|
throw result;
|
|
468
488
|
}
|
|
469
489
|
});
|
package/src/utils.ts
CHANGED
|
@@ -20,6 +20,7 @@ import getDelegatesBySpace, { SNAPSHOT_SUBGRAPH_URL } from './utils/delegation';
|
|
|
20
20
|
|
|
21
21
|
interface Options {
|
|
22
22
|
url?: string;
|
|
23
|
+
headers?: any;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
interface Strategy {
|
|
@@ -38,6 +39,43 @@ const scoreApiHeaders = {
|
|
|
38
39
|
'Content-Type': 'application/json'
|
|
39
40
|
};
|
|
40
41
|
|
|
42
|
+
const DEFAULT_SCORE_API_URL = 'https://score.snapshot.org';
|
|
43
|
+
|
|
44
|
+
function formatScoreAPIUrl(
|
|
45
|
+
url = DEFAULT_SCORE_API_URL,
|
|
46
|
+
options = {
|
|
47
|
+
path: ''
|
|
48
|
+
}
|
|
49
|
+
) {
|
|
50
|
+
const scoreURL = new URL(url);
|
|
51
|
+
if (options.path) scoreURL.pathname = options.path;
|
|
52
|
+
const apiKey = scoreURL.searchParams.get('apiKey');
|
|
53
|
+
let headers: any = { ...scoreApiHeaders };
|
|
54
|
+
if (apiKey) {
|
|
55
|
+
scoreURL.searchParams.delete('apiKey');
|
|
56
|
+
headers = { ...scoreApiHeaders, 'X-API-KEY': apiKey };
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
url: scoreURL.toString(),
|
|
60
|
+
headers
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function parseScoreAPIResponse(res: any) {
|
|
65
|
+
let data: any = await res.text();
|
|
66
|
+
try {
|
|
67
|
+
data = JSON.parse(data);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
return Promise.reject({
|
|
70
|
+
code: res.status || 500,
|
|
71
|
+
message: 'Failed to parse response from score API',
|
|
72
|
+
data
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (data.error) return Promise.reject(data.error);
|
|
76
|
+
return data;
|
|
77
|
+
}
|
|
78
|
+
|
|
41
79
|
const ajv = new Ajv({
|
|
42
80
|
allErrors: true,
|
|
43
81
|
allowUnionTypes: true,
|
|
@@ -135,7 +173,6 @@ ajv.addKeyword({
|
|
|
135
173
|
errors: true
|
|
136
174
|
});
|
|
137
175
|
|
|
138
|
-
|
|
139
176
|
// Custom URL format to allow empty string values
|
|
140
177
|
// https://github.com/snapshot-labs/snapshot.js/pull/541/files
|
|
141
178
|
ajv.addFormat('customUrl', {
|
|
@@ -287,7 +324,7 @@ export async function getScores(
|
|
|
287
324
|
network: string,
|
|
288
325
|
addresses: string[],
|
|
289
326
|
snapshot: number | string = 'latest',
|
|
290
|
-
scoreApiUrl =
|
|
327
|
+
scoreApiUrl = DEFAULT_SCORE_API_URL,
|
|
291
328
|
options: any = {}
|
|
292
329
|
) {
|
|
293
330
|
if (!Array.isArray(addresses)) {
|
|
@@ -317,9 +354,11 @@ export async function getScores(
|
|
|
317
354
|
);
|
|
318
355
|
}
|
|
319
356
|
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
357
|
+
const urlObject = new URL(scoreApiUrl);
|
|
358
|
+
urlObject.pathname = '/api/scores';
|
|
359
|
+
const { url, headers } = formatScoreAPIUrl(scoreApiUrl, {
|
|
360
|
+
path: '/api/scores'
|
|
361
|
+
});
|
|
323
362
|
|
|
324
363
|
try {
|
|
325
364
|
const params = {
|
|
@@ -329,20 +368,16 @@ export async function getScores(
|
|
|
329
368
|
strategies,
|
|
330
369
|
addresses
|
|
331
370
|
};
|
|
332
|
-
const res = await fetch(
|
|
371
|
+
const res = await fetch(url, {
|
|
333
372
|
method: 'POST',
|
|
334
|
-
headers
|
|
373
|
+
headers,
|
|
335
374
|
body: JSON.stringify({ params })
|
|
336
375
|
});
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
if (obj.error) {
|
|
340
|
-
return Promise.reject(obj.error);
|
|
341
|
-
}
|
|
376
|
+
const response = await parseScoreAPIResponse(res);
|
|
342
377
|
|
|
343
378
|
return options.returnValue === 'all'
|
|
344
|
-
?
|
|
345
|
-
:
|
|
379
|
+
? response.result
|
|
380
|
+
: response.result[options.returnValue || 'scores'];
|
|
346
381
|
} catch (e) {
|
|
347
382
|
if (e.errno) {
|
|
348
383
|
return Promise.reject({ code: e.errno, message: e.toString(), data: '' });
|
|
@@ -360,8 +395,7 @@ export async function getVp(
|
|
|
360
395
|
delegation: boolean,
|
|
361
396
|
options?: Options
|
|
362
397
|
) {
|
|
363
|
-
|
|
364
|
-
if (!options.url) options.url = 'https://score.snapshot.org';
|
|
398
|
+
const { url, headers } = formatScoreAPIUrl(options?.url);
|
|
365
399
|
if (!isValidAddress(address)) {
|
|
366
400
|
return inputError(`Invalid voter address: ${address}`);
|
|
367
401
|
}
|
|
@@ -385,7 +419,7 @@ export async function getVp(
|
|
|
385
419
|
|
|
386
420
|
const init = {
|
|
387
421
|
method: 'POST',
|
|
388
|
-
headers
|
|
422
|
+
headers,
|
|
389
423
|
body: JSON.stringify({
|
|
390
424
|
jsonrpc: '2.0',
|
|
391
425
|
method: 'get_vp',
|
|
@@ -401,10 +435,9 @@ export async function getVp(
|
|
|
401
435
|
};
|
|
402
436
|
|
|
403
437
|
try {
|
|
404
|
-
const res = await fetch(
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
if (json.result) return json.result;
|
|
438
|
+
const res = await fetch(url, init);
|
|
439
|
+
const response = await parseScoreAPIResponse(res);
|
|
440
|
+
return response.result;
|
|
408
441
|
} catch (e) {
|
|
409
442
|
if (e.errno) {
|
|
410
443
|
return Promise.reject({ code: e.errno, message: e.toString(), data: '' });
|
|
@@ -420,7 +453,7 @@ export async function validate(
|
|
|
420
453
|
network: string,
|
|
421
454
|
snapshot: number | 'latest',
|
|
422
455
|
params: any,
|
|
423
|
-
options
|
|
456
|
+
options?: Options
|
|
424
457
|
) {
|
|
425
458
|
if (!isValidAddress(author)) {
|
|
426
459
|
return inputError(`Invalid author: ${author}`);
|
|
@@ -436,10 +469,11 @@ export async function validate(
|
|
|
436
469
|
}
|
|
437
470
|
|
|
438
471
|
if (!options) options = {};
|
|
439
|
-
|
|
472
|
+
const { url, headers } = formatScoreAPIUrl(options.url);
|
|
473
|
+
|
|
440
474
|
const init = {
|
|
441
475
|
method: 'POST',
|
|
442
|
-
headers
|
|
476
|
+
headers,
|
|
443
477
|
body: JSON.stringify({
|
|
444
478
|
jsonrpc: '2.0',
|
|
445
479
|
method: 'validate',
|
|
@@ -455,10 +489,9 @@ export async function validate(
|
|
|
455
489
|
};
|
|
456
490
|
|
|
457
491
|
try {
|
|
458
|
-
const res = await fetch(
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
return json.result;
|
|
492
|
+
const res = await fetch(url, init);
|
|
493
|
+
const response = await parseScoreAPIResponse(res);
|
|
494
|
+
return response.result;
|
|
462
495
|
} catch (e) {
|
|
463
496
|
if (e.errno) {
|
|
464
497
|
return Promise.reject({ code: e.errno, message: e.toString(), data: '' });
|