@snapshot-labs/snapshot.js 0.13.0 → 0.14.0

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.
@@ -1,5 +1,4 @@
1
1
  import fetch from 'cross-fetch';
2
- import { AbiCoder, Interface } from '@ethersproject/abi';
3
2
  import { Contract as Contract$1 } from '@ethersproject/contracts';
4
3
  import { isAddress, getAddress } from '@ethersproject/address';
5
4
  import { parseUnits } from '@ethersproject/units';
@@ -8,12 +7,13 @@ import { jsonToGraphQLQuery } from 'json-to-graphql-query';
8
7
  import Ajv from 'ajv';
9
8
  import addFormats from 'ajv-formats';
10
9
  import addErrors from 'ajv-errors';
11
- import set from 'lodash.set';
12
10
  import { StaticJsonRpcProvider } from '@ethersproject/providers';
11
+ import { RpcProvider, Contract, typedData, transaction, uint256, shortString, num, constants as constants$1, validateAndParseAddress } from 'starknet';
13
12
  import { hexlify, concat, arrayify } from '@ethersproject/bytes';
14
- import { Contract, RpcProvider, typedData, validateAndParseAddress } from 'starknet';
15
13
  import { BigNumber } from '@ethersproject/bignumber';
16
14
  import { verifyTypedData } from '@ethersproject/wallet';
15
+ import { AbiCoder, Interface } from '@ethersproject/abi';
16
+ import set from 'lodash.set';
17
17
 
18
18
  /*! *****************************************************************************
19
19
  Copyright (c) Microsoft Corporation. All rights reserved.
@@ -273,33 +273,6 @@ var constants = {
273
273
  local: local
274
274
  };
275
275
 
276
- class Multicaller {
277
- constructor(network, provider, abi, options) {
278
- this.options = {};
279
- this.calls = [];
280
- this.paths = [];
281
- this.network = network;
282
- this.provider = provider;
283
- this.abi = abi;
284
- this.options = options || {};
285
- }
286
- call(path, address, fn, params) {
287
- this.calls.push([address, fn, params]);
288
- this.paths.push(path);
289
- return this;
290
- }
291
- execute(from) {
292
- return __awaiter(this, void 0, void 0, function* () {
293
- const obj = from || {};
294
- const result = yield multicall(this.network, this.provider, this.abi, this.calls, this.options);
295
- result.forEach((r, i) => set(obj, this.paths[i], r.length > 1 ? r : r[0]));
296
- this.calls = [];
297
- this.paths = [];
298
- return obj;
299
- });
300
- }
301
- }
302
-
303
276
  let cache = {};
304
277
  let expirationTime = 0;
305
278
  function getSnapshots(network_1, snapshot_1, provider_1, networks_1) {
@@ -347,213 +320,6 @@ function getSnapshots(network_1, snapshot_1, provider_1, networks_1) {
347
320
  });
348
321
  }
349
322
 
350
- const providers = {};
351
- const DEFAULT_BROVIDER_URL = 'https://rpc.snapshot.org';
352
- const DEFAULT_TIMEOUT = 25000;
353
- function getProvider(network, { broviderUrl = DEFAULT_BROVIDER_URL, timeout = DEFAULT_TIMEOUT } = {}) {
354
- const url = `${broviderUrl}/${network}`;
355
- if (!providers[network])
356
- providers[network] = new StaticJsonRpcProvider({
357
- url,
358
- timeout,
359
- allowGzip: true
360
- }, Number(network));
361
- return providers[network];
362
- }
363
-
364
- function signMessage(web3, msg, address) {
365
- return __awaiter(this, void 0, void 0, function* () {
366
- msg = hexlify(new Buffer(msg, 'utf8'));
367
- return yield web3.send('personal_sign', [msg, address]);
368
- });
369
- }
370
- function getBlockNumber(provider) {
371
- return __awaiter(this, void 0, void 0, function* () {
372
- try {
373
- const blockNumber = yield provider.getBlockNumber();
374
- return parseInt(blockNumber);
375
- }
376
- catch (e) {
377
- return Promise.reject();
378
- }
379
- });
380
- }
381
-
382
- const RPC_URLS = {
383
- SN_MAIN: 'https://starknet-mainnet.public.blastapi.io',
384
- SN_SEPOLIA: 'https://starknet-sepolia.public.blastapi.io'
385
- };
386
- const ABI = [
387
- {
388
- name: 'argent::common::account::IAccount',
389
- type: 'interface',
390
- items: [
391
- {
392
- name: 'is_valid_signature',
393
- type: 'function',
394
- inputs: [
395
- {
396
- name: 'hash',
397
- type: 'core::felt252'
398
- },
399
- {
400
- name: 'signature',
401
- type: 'core::array::Array::<core::felt252>'
402
- }
403
- ],
404
- outputs: [
405
- {
406
- type: 'core::felt252'
407
- }
408
- ],
409
- state_mutability: 'view'
410
- }
411
- ]
412
- }
413
- ];
414
- function getProvider$1(network, options) {
415
- var _a;
416
- if (!RPC_URLS[network])
417
- throw new Error('Invalid network');
418
- return new RpcProvider({
419
- nodeUrl: (_a = options === null || options === void 0 ? void 0 : options.broviderUrl) !== null && _a !== void 0 ? _a : RPC_URLS[network]
420
- });
421
- }
422
- function isStarknetMessage(data) {
423
- return !!data.primaryType && !!data.types.StarkNetDomain;
424
- }
425
- function getHash(data, address) {
426
- const { domain, types, primaryType, message } = data;
427
- return typedData.getMessageHash({ types, primaryType, domain, message }, address);
428
- }
429
- function verify(address_1, sig_1, data_1) {
430
- return __awaiter(this, arguments, void 0, function* (address, sig, data, network = 'SN_MAIN', options = {}) {
431
- try {
432
- const contractAccount = new Contract(ABI, address, getProvider$1(network, options));
433
- if (sig.length < 2) {
434
- throw new Error('Invalid signature format');
435
- }
436
- const result = yield contractAccount.is_valid_signature(getHash(data, address), sig.slice(-2));
437
- return BigNumber.from(result).eq(BigNumber.from('370462705988'));
438
- }
439
- catch (e) {
440
- if (e.message.includes('Contract not found')) {
441
- throw new Error('Contract not deployed');
442
- }
443
- throw e;
444
- }
445
- });
446
- }
447
-
448
- var starknet = /*#__PURE__*/Object.freeze({
449
- __proto__: null,
450
- isStarknetMessage: isStarknetMessage,
451
- getHash: getHash,
452
- 'default': verify
453
- });
454
-
455
- const ERC6492_DETECTION_SUFFIX = '6492649264926492649264926492649264926492649264926492649264926492';
456
- function isEqual(a, b) {
457
- return a.toLowerCase() === b.toLowerCase();
458
- }
459
- function getHash$1(data) {
460
- const { domain, types, message } = data;
461
- return _TypedDataEncoder.hash(domain, types, message);
462
- }
463
- function verify$1(address_1, sig_1, data_1) {
464
- return __awaiter(this, arguments, void 0, function* (address, sig, data, network = '1', options = {}) {
465
- const { domain, types, message } = data;
466
- try {
467
- const recoverAddress = verifyTypedData(domain, types, message, sig);
468
- if (isEqual(address, recoverAddress))
469
- return true;
470
- }
471
- catch (e) { }
472
- const provider = getProvider(network, options);
473
- const hash = getHash$1(data);
474
- // Handle EIP-6492
475
- // https://eips.ethereum.org/EIPS/eip-6492
476
- //
477
- // We can actually replace verifyTypedData and verifyDefault with the following code,
478
- // but https://github.com/AmbireTech/signature-validator/blob/main/contracts/DeploylessUniversalSigValidator.sol
479
- // also can send an extra network request to the provider. (with verifyTypedData we don't send any extra request)
480
- //
481
- if (sig.endsWith(ERC6492_DETECTION_SUFFIX)) {
482
- try {
483
- return ('0x01' ===
484
- (yield provider.call({
485
- data: concat([
486
- '0x60806040523480156200001157600080fd5b50604051620007003803806200070083398101604081905262000034916200056f565b6000620000438484846200004f565b9050806000526001601ff35b600080846001600160a01b0316803b806020016040519081016040528181526000908060200190933c90507f6492649264926492649264926492649264926492649264926492649264926492620000a68462000451565b036200021f57600060608085806020019051810190620000c79190620005ce565b8651929550909350915060000362000192576000836001600160a01b031683604051620000f5919062000643565b6000604051808303816000865af19150503d806000811462000134576040519150601f19603f3d011682016040523d82523d6000602084013e62000139565b606091505b5050905080620001905760405162461bcd60e51b815260206004820152601e60248201527f5369676e617475726556616c696461746f723a206465706c6f796d656e74000060448201526064015b60405180910390fd5b505b604051630b135d3f60e11b808252906001600160a01b038a1690631626ba7e90620001c4908b90869060040162000661565b602060405180830381865afa158015620001e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020891906200069d565b6001600160e01b031916149450505050506200044a565b805115620002b157604051630b135d3f60e11b808252906001600160a01b03871690631626ba7e9062000259908890889060040162000661565b602060405180830381865afa15801562000277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029d91906200069d565b6001600160e01b031916149150506200044a565b8251604114620003195760405162461bcd60e51b815260206004820152603a6024820152600080516020620006e083398151915260448201527f3a20696e76616c6964207369676e6174757265206c656e677468000000000000606482015260840162000187565b620003236200046b565b506020830151604080850151855186939260009185919081106200034b576200034b620006c9565b016020015160f81c9050601b81148015906200036b57508060ff16601c14155b15620003cf5760405162461bcd60e51b815260206004820152603b6024820152600080516020620006e083398151915260448201527f3a20696e76616c6964207369676e617475726520762076616c75650000000000606482015260840162000187565b6040805160008152602081018083528a905260ff83169181019190915260608101849052608081018390526001600160a01b038a169060019060a0016020604051602081039080840390855afa1580156200042e573d6000803e3d6000fd5b505050602060405103516001600160a01b031614955050505050505b9392505050565b60006020825110156200046357600080fd5b508051015190565b60405180606001604052806003906020820280368337509192915050565b6001600160a01b03811681146200049f57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620004d5578181015183820152602001620004bb565b50506000910152565b600082601f830112620004f057600080fd5b81516001600160401b03808211156200050d576200050d620004a2565b604051601f8301601f19908116603f01168101908282118183101715620005385762000538620004a2565b816040528381528660208588010111156200055257600080fd5b62000565846020830160208901620004b8565b9695505050505050565b6000806000606084860312156200058557600080fd5b8351620005928162000489565b6020850151604086015191945092506001600160401b03811115620005b657600080fd5b620005c486828701620004de565b9150509250925092565b600080600060608486031215620005e457600080fd5b8351620005f18162000489565b60208501519093506001600160401b03808211156200060f57600080fd5b6200061d87838801620004de565b935060408601519150808211156200063457600080fd5b50620005c486828701620004de565b6000825162000657818460208701620004b8565b9190910192915050565b828152604060208201526000825180604084015262000688816060850160208701620004b8565b601f01601f1916919091016060019392505050565b600060208284031215620006b057600080fd5b81516001600160e01b0319811681146200044a57600080fd5b634e487b7160e01b600052603260045260246000fdfe5369676e617475726556616c696461746f72237265636f7665725369676e6572',
487
- new AbiCoder().encode(['address', 'bytes32', 'bytes'], [address, arrayify(hash), sig])
488
- ])
489
- })));
490
- }
491
- catch (error) {
492
- return false;
493
- }
494
- }
495
- // Handle EIP-1271
496
- if (yield verifyDefault(address, sig, hash, provider))
497
- return true;
498
- return yield verifyOldVersion(address, sig, hash, provider);
499
- });
500
- }
501
- function verifyDefault(address, sig, hash, provider) {
502
- return __awaiter(this, void 0, void 0, function* () {
503
- let returnValue;
504
- const magicValue = '0x1626ba7e';
505
- const abi = 'function isValidSignature(bytes32 _hash, bytes memory _signature) public view returns (bytes4 magicValue)';
506
- try {
507
- returnValue = yield call(provider, [abi], [address, 'isValidSignature', [arrayify(hash), sig]]);
508
- }
509
- catch (e) {
510
- if (e.message.startsWith('missing revert data in call exception')) {
511
- return false;
512
- }
513
- throw e;
514
- }
515
- return isEqual(returnValue, magicValue);
516
- });
517
- }
518
- function verifyOldVersion(address, sig, hash, provider) {
519
- return __awaiter(this, void 0, void 0, function* () {
520
- const magicValue = '0x20c13b0b';
521
- const abi = 'function isValidSignature(bytes _hash, bytes memory _signature) public view returns (bytes4 magicValue)';
522
- const returnValue = yield call(provider, [abi], [address, 'isValidSignature', [arrayify(hash), sig]]);
523
- return isEqual(returnValue, magicValue);
524
- });
525
- }
526
-
527
- var evm = /*#__PURE__*/Object.freeze({
528
- __proto__: null,
529
- getHash: getHash$1,
530
- 'default': verify$1
531
- });
532
-
533
- function getHash$2(data, address) {
534
- const networkType = isStarknetMessage(data) ? starknet : evm;
535
- return networkType.getHash(data, address);
536
- }
537
- function verify$2(address_1, sig_1, data_1) {
538
- return __awaiter(this, arguments, void 0, function* (address, sig, data, network = '1', options = {}) {
539
- if (!isStarknetAddress(address) && !isEvmAddress(address)) {
540
- throw new Error('Invalid address');
541
- }
542
- const networkType = isStarknetMessage(data) ? starknet : evm;
543
- return yield networkType.default(address, sig, data, network, options);
544
- });
545
- }
546
-
547
- var gateways = [
548
- "ipfs.snapshot.box",
549
- "snapshot.4everland.link",
550
- "ipfs.io",
551
- "ipfs.fleek.co",
552
- "gateway.pinata.cloud",
553
- "dweb.link",
554
- "ipfs.infura.io"
555
- ];
556
-
557
323
  var networks = {
558
324
  "1": {
559
325
  key: "1",
@@ -2583,19 +2349,299 @@ var networks = {
2583
2349
  },
2584
2350
  start: 7521509,
2585
2351
  logo: "ipfs://QmNnGPr1CNvj12SSGzKARtUHv9FyEfE5nES73U4vBWQSJL"
2352
+ },
2353
+ "0x534e5f4d41494e": {
2354
+ key: "sn",
2355
+ name: "Starknet",
2356
+ shortName: "Starknet",
2357
+ chainId: "0x534e5f4d41494e",
2358
+ network: "mainnet",
2359
+ multicall: "0x05754af3760f3356da99aea5c3ec39ccac7783d925a19666ebbeca58ff0087f4",
2360
+ explorer: {
2361
+ url: "https://starkscan.co"
2362
+ },
2363
+ rpc: [
2364
+ ],
2365
+ start: 8446,
2366
+ logo: "ipfs://bafkreihbjafyh7eud7r6e5743esaamifcttsvbspfwcrfoc5ykodjdi67m"
2367
+ },
2368
+ "0x534e5f5345504f4c4941": {
2369
+ key: "sn-sep",
2370
+ name: "Starknet Testnet",
2371
+ shortName: "testnet",
2372
+ chainId: "0x534e5f5345504f4c4941",
2373
+ network: "testnet",
2374
+ testnet: true,
2375
+ multicall: "0x05754af3760f3356da99aea5c3ec39ccac7783d925a19666ebbeca58ff0087f4",
2376
+ explorer: {
2377
+ url: "https://sepolia.starkscan.co"
2378
+ },
2379
+ rpc: [
2380
+ ],
2381
+ start: 7,
2382
+ logo: "ipfs://bafkreihbjafyh7eud7r6e5743esaamifcttsvbspfwcrfoc5ykodjdi67m"
2586
2383
  }
2587
2384
  };
2588
2385
 
2589
- class SingleChoiceVoting {
2590
- constructor(proposal, votes, strategies, selected) {
2591
- this.proposal = proposal;
2592
- this.votes = votes;
2593
- this.strategies = strategies;
2594
- this.selected = selected;
2595
- }
2596
- static isValidChoice(voteChoice, proposalChoices) {
2597
- return (typeof voteChoice === 'number' &&
2598
- (proposalChoices === null || proposalChoices === void 0 ? void 0 : proposalChoices[voteChoice - 1]) !== undefined);
2386
+ const DEFAULT_BROVIDER_URL = 'https://rpc.snapshot.org';
2387
+ const DEFAULT_TIMEOUT = 25000;
2388
+ const STARKNET_BROVIDER_KEYS = ['sn', 'sn-sep'];
2389
+ const providerMemo = new Map();
2390
+ const providerFnMap = {
2391
+ evm: getEvmProvider,
2392
+ starknet: getStarknetProvider
2393
+ };
2394
+ function normalizeOptions(options = {}) {
2395
+ var _a;
2396
+ return {
2397
+ broviderUrl: options.broviderUrl || DEFAULT_BROVIDER_URL,
2398
+ timeout: (_a = options.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT
2399
+ };
2400
+ }
2401
+ function getBroviderNetworkId(network) {
2402
+ const config = networks[network];
2403
+ if (!config) {
2404
+ throw new Error(`Network '${network}' is not supported`);
2405
+ }
2406
+ return String(config.key);
2407
+ }
2408
+ function getProviderType(networkId) {
2409
+ const isStarknet = STARKNET_BROVIDER_KEYS.includes(networkId);
2410
+ return isStarknet ? 'starknet' : 'evm';
2411
+ }
2412
+ function createMemoKey(networkId, options) {
2413
+ return `${networkId}:${options.broviderUrl}:${options.timeout}`;
2414
+ }
2415
+ // return loose `any` type to avoid typecheck issues on package consumers
2416
+ function getProvider(network, options = {}) {
2417
+ const networkId = getBroviderNetworkId(network);
2418
+ const normalizedOptions = normalizeOptions(options);
2419
+ const memoKey = createMemoKey(networkId, normalizedOptions);
2420
+ const memoized = providerMemo.get(memoKey);
2421
+ if (memoized) {
2422
+ return memoized;
2423
+ }
2424
+ const providerType = getProviderType(networkId);
2425
+ const provider = providerFnMap[providerType](networkId, normalizedOptions);
2426
+ providerMemo.set(memoKey, provider);
2427
+ return provider;
2428
+ }
2429
+ function getEvmProvider(networkId, options) {
2430
+ return new StaticJsonRpcProvider({
2431
+ url: `${options.broviderUrl}/${networkId}`,
2432
+ timeout: options.timeout,
2433
+ allowGzip: true
2434
+ }, Number(networkId));
2435
+ }
2436
+ function getStarknetProvider(networkKey, options) {
2437
+ return new RpcProvider({
2438
+ nodeUrl: `${options.broviderUrl}/${networkKey}`
2439
+ });
2440
+ }
2441
+
2442
+ function signMessage(web3, msg, address) {
2443
+ return __awaiter(this, void 0, void 0, function* () {
2444
+ msg = hexlify(new Buffer(msg, 'utf8'));
2445
+ return yield web3.send('personal_sign', [msg, address]);
2446
+ });
2447
+ }
2448
+ function getBlockNumber(provider) {
2449
+ return __awaiter(this, void 0, void 0, function* () {
2450
+ try {
2451
+ const blockNumber = yield provider.getBlockNumber();
2452
+ return parseInt(blockNumber);
2453
+ }
2454
+ catch (e) {
2455
+ return Promise.reject();
2456
+ }
2457
+ });
2458
+ }
2459
+
2460
+ const RPC_URLS = {
2461
+ SN_MAIN: 'https://starknet-mainnet.public.blastapi.io',
2462
+ SN_SEPOLIA: 'https://starknet-sepolia.public.blastapi.io'
2463
+ };
2464
+ const ABI = [
2465
+ {
2466
+ name: 'argent::common::account::IAccount',
2467
+ type: 'interface',
2468
+ items: [
2469
+ {
2470
+ name: 'is_valid_signature',
2471
+ type: 'function',
2472
+ inputs: [
2473
+ {
2474
+ name: 'hash',
2475
+ type: 'core::felt252'
2476
+ },
2477
+ {
2478
+ name: 'signature',
2479
+ type: 'core::array::Array::<core::felt252>'
2480
+ }
2481
+ ],
2482
+ outputs: [
2483
+ {
2484
+ type: 'core::felt252'
2485
+ }
2486
+ ],
2487
+ state_mutability: 'view'
2488
+ }
2489
+ ]
2490
+ }
2491
+ ];
2492
+ function getProvider$1(network, options) {
2493
+ var _a;
2494
+ if (!RPC_URLS[network])
2495
+ throw new Error('Invalid network');
2496
+ return new RpcProvider({
2497
+ nodeUrl: (_a = options === null || options === void 0 ? void 0 : options.broviderUrl) !== null && _a !== void 0 ? _a : RPC_URLS[network]
2498
+ });
2499
+ }
2500
+ function isStarknetMessage(data) {
2501
+ return !!data.primaryType && !!data.types.StarkNetDomain;
2502
+ }
2503
+ function getHash(data, address) {
2504
+ const { domain, types, primaryType, message } = data;
2505
+ return typedData.getMessageHash({ types, primaryType, domain, message }, address);
2506
+ }
2507
+ function verify(address_1, sig_1, data_1) {
2508
+ return __awaiter(this, arguments, void 0, function* (address, sig, data, network = 'SN_MAIN', options = {}) {
2509
+ try {
2510
+ const contractAccount = new Contract(ABI, address, getProvider$1(network, options));
2511
+ if (sig.length < 2) {
2512
+ throw new Error('Invalid signature format');
2513
+ }
2514
+ const result = yield contractAccount.is_valid_signature(getHash(data, address), sig.slice(-2));
2515
+ return BigNumber.from(result).eq(BigNumber.from('370462705988'));
2516
+ }
2517
+ catch (e) {
2518
+ if (e.message.includes('Contract not found')) {
2519
+ throw new Error('Contract not deployed');
2520
+ }
2521
+ throw e;
2522
+ }
2523
+ });
2524
+ }
2525
+
2526
+ var starknet = /*#__PURE__*/Object.freeze({
2527
+ __proto__: null,
2528
+ isStarknetMessage: isStarknetMessage,
2529
+ getHash: getHash,
2530
+ 'default': verify
2531
+ });
2532
+
2533
+ const ERC6492_DETECTION_SUFFIX = '6492649264926492649264926492649264926492649264926492649264926492';
2534
+ function isEqual(a, b) {
2535
+ return a.toLowerCase() === b.toLowerCase();
2536
+ }
2537
+ function getHash$1(data) {
2538
+ const { domain, types, message } = data;
2539
+ return _TypedDataEncoder.hash(domain, types, message);
2540
+ }
2541
+ function verify$1(address_1, sig_1, data_1) {
2542
+ return __awaiter(this, arguments, void 0, function* (address, sig, data, network = '1', options = {}) {
2543
+ const { domain, types, message } = data;
2544
+ try {
2545
+ const recoverAddress = verifyTypedData(domain, types, message, sig);
2546
+ if (isEqual(address, recoverAddress))
2547
+ return true;
2548
+ }
2549
+ catch (e) { }
2550
+ const provider = getProvider(network, options);
2551
+ const hash = getHash$1(data);
2552
+ // Handle EIP-6492
2553
+ // https://eips.ethereum.org/EIPS/eip-6492
2554
+ //
2555
+ // We can actually replace verifyTypedData and verifyDefault with the following code,
2556
+ // but https://github.com/AmbireTech/signature-validator/blob/main/contracts/DeploylessUniversalSigValidator.sol
2557
+ // also can send an extra network request to the provider. (with verifyTypedData we don't send any extra request)
2558
+ //
2559
+ if (sig.endsWith(ERC6492_DETECTION_SUFFIX)) {
2560
+ try {
2561
+ return ('0x01' ===
2562
+ (yield provider.call({
2563
+ data: concat([
2564
+ '0x60806040523480156200001157600080fd5b50604051620007003803806200070083398101604081905262000034916200056f565b6000620000438484846200004f565b9050806000526001601ff35b600080846001600160a01b0316803b806020016040519081016040528181526000908060200190933c90507f6492649264926492649264926492649264926492649264926492649264926492620000a68462000451565b036200021f57600060608085806020019051810190620000c79190620005ce565b8651929550909350915060000362000192576000836001600160a01b031683604051620000f5919062000643565b6000604051808303816000865af19150503d806000811462000134576040519150601f19603f3d011682016040523d82523d6000602084013e62000139565b606091505b5050905080620001905760405162461bcd60e51b815260206004820152601e60248201527f5369676e617475726556616c696461746f723a206465706c6f796d656e74000060448201526064015b60405180910390fd5b505b604051630b135d3f60e11b808252906001600160a01b038a1690631626ba7e90620001c4908b90869060040162000661565b602060405180830381865afa158015620001e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020891906200069d565b6001600160e01b031916149450505050506200044a565b805115620002b157604051630b135d3f60e11b808252906001600160a01b03871690631626ba7e9062000259908890889060040162000661565b602060405180830381865afa15801562000277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029d91906200069d565b6001600160e01b031916149150506200044a565b8251604114620003195760405162461bcd60e51b815260206004820152603a6024820152600080516020620006e083398151915260448201527f3a20696e76616c6964207369676e6174757265206c656e677468000000000000606482015260840162000187565b620003236200046b565b506020830151604080850151855186939260009185919081106200034b576200034b620006c9565b016020015160f81c9050601b81148015906200036b57508060ff16601c14155b15620003cf5760405162461bcd60e51b815260206004820152603b6024820152600080516020620006e083398151915260448201527f3a20696e76616c6964207369676e617475726520762076616c75650000000000606482015260840162000187565b6040805160008152602081018083528a905260ff83169181019190915260608101849052608081018390526001600160a01b038a169060019060a0016020604051602081039080840390855afa1580156200042e573d6000803e3d6000fd5b505050602060405103516001600160a01b031614955050505050505b9392505050565b60006020825110156200046357600080fd5b508051015190565b60405180606001604052806003906020820280368337509192915050565b6001600160a01b03811681146200049f57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620004d5578181015183820152602001620004bb565b50506000910152565b600082601f830112620004f057600080fd5b81516001600160401b03808211156200050d576200050d620004a2565b604051601f8301601f19908116603f01168101908282118183101715620005385762000538620004a2565b816040528381528660208588010111156200055257600080fd5b62000565846020830160208901620004b8565b9695505050505050565b6000806000606084860312156200058557600080fd5b8351620005928162000489565b6020850151604086015191945092506001600160401b03811115620005b657600080fd5b620005c486828701620004de565b9150509250925092565b600080600060608486031215620005e457600080fd5b8351620005f18162000489565b60208501519093506001600160401b03808211156200060f57600080fd5b6200061d87838801620004de565b935060408601519150808211156200063457600080fd5b50620005c486828701620004de565b6000825162000657818460208701620004b8565b9190910192915050565b828152604060208201526000825180604084015262000688816060850160208701620004b8565b601f01601f1916919091016060019392505050565b600060208284031215620006b057600080fd5b81516001600160e01b0319811681146200044a57600080fd5b634e487b7160e01b600052603260045260246000fdfe5369676e617475726556616c696461746f72237265636f7665725369676e6572',
2565
+ new AbiCoder().encode(['address', 'bytes32', 'bytes'], [address, arrayify(hash), sig])
2566
+ ])
2567
+ })));
2568
+ }
2569
+ catch (error) {
2570
+ return false;
2571
+ }
2572
+ }
2573
+ // Handle EIP-1271
2574
+ if (yield verifyDefault(address, sig, hash, provider))
2575
+ return true;
2576
+ return yield verifyOldVersion(address, sig, hash, provider);
2577
+ });
2578
+ }
2579
+ function verifyDefault(address, sig, hash, provider) {
2580
+ return __awaiter(this, void 0, void 0, function* () {
2581
+ let returnValue;
2582
+ const magicValue = '0x1626ba7e';
2583
+ const abi = 'function isValidSignature(bytes32 _hash, bytes memory _signature) public view returns (bytes4 magicValue)';
2584
+ try {
2585
+ returnValue = yield call(provider, [abi], [address, 'isValidSignature', [arrayify(hash), sig]]);
2586
+ }
2587
+ catch (e) {
2588
+ if (e.message.startsWith('missing revert data in call exception')) {
2589
+ return false;
2590
+ }
2591
+ throw e;
2592
+ }
2593
+ return isEqual(returnValue, magicValue);
2594
+ });
2595
+ }
2596
+ function verifyOldVersion(address, sig, hash, provider) {
2597
+ return __awaiter(this, void 0, void 0, function* () {
2598
+ const magicValue = '0x20c13b0b';
2599
+ const abi = 'function isValidSignature(bytes _hash, bytes memory _signature) public view returns (bytes4 magicValue)';
2600
+ const returnValue = yield call(provider, [abi], [address, 'isValidSignature', [arrayify(hash), sig]]);
2601
+ return isEqual(returnValue, magicValue);
2602
+ });
2603
+ }
2604
+
2605
+ var evm = /*#__PURE__*/Object.freeze({
2606
+ __proto__: null,
2607
+ getHash: getHash$1,
2608
+ 'default': verify$1
2609
+ });
2610
+
2611
+ function getHash$2(data, address) {
2612
+ const networkType = isStarknetMessage(data) ? starknet : evm;
2613
+ return networkType.getHash(data, address);
2614
+ }
2615
+ function verify$2(address_1, sig_1, data_1) {
2616
+ return __awaiter(this, arguments, void 0, function* (address, sig, data, network = '1', options = {}) {
2617
+ if (!isStarknetAddress(address) && !isEvmAddress(address)) {
2618
+ throw new Error('Invalid address');
2619
+ }
2620
+ const networkType = isStarknetMessage(data) ? starknet : evm;
2621
+ return yield networkType.default(address, sig, data, network, options);
2622
+ });
2623
+ }
2624
+
2625
+ var gateways = [
2626
+ "ipfs.snapshot.box",
2627
+ "snapshot.4everland.link",
2628
+ "ipfs.io",
2629
+ "ipfs.fleek.co",
2630
+ "gateway.pinata.cloud",
2631
+ "dweb.link",
2632
+ "ipfs.infura.io"
2633
+ ];
2634
+
2635
+ class SingleChoiceVoting {
2636
+ constructor(proposal, votes, strategies, selected) {
2637
+ this.proposal = proposal;
2638
+ this.votes = votes;
2639
+ this.strategies = strategies;
2640
+ this.selected = selected;
2641
+ }
2642
+ static isValidChoice(voteChoice, proposalChoices) {
2643
+ return (typeof voteChoice === 'number' &&
2644
+ (proposalChoices === null || proposalChoices === void 0 ? void 0 : proposalChoices[voteChoice - 1]) !== undefined);
2599
2645
  }
2600
2646
  getValidVotes() {
2601
2647
  return this.votes.filter((vote) => SingleChoiceVoting.isValidChoice(vote.choice, this.proposal.choices));
@@ -3183,6 +3229,209 @@ function fetchData(_a) {
3183
3229
  });
3184
3230
  }
3185
3231
 
3232
+ const multicallAbi = [
3233
+ 'function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)'
3234
+ ];
3235
+ function multicall(address_1, provider_1, abi_1, calls_1, limit_1) {
3236
+ return __awaiter(this, arguments, void 0, function* (address, provider, abi, calls, limit, options = {}) {
3237
+ const multi = new Contract$1(address, multicallAbi, provider);
3238
+ const itf = new Interface(abi);
3239
+ try {
3240
+ const pages = Math.ceil(calls.length / limit);
3241
+ const promises = [];
3242
+ Array.from(Array(pages)).forEach((x, i) => {
3243
+ const callsInPage = calls.slice(limit * i, limit * (i + 1));
3244
+ promises.push(multi.aggregate(callsInPage.map((call) => [
3245
+ call[0].toLowerCase(),
3246
+ itf.encodeFunctionData(call[1], call[2])
3247
+ ]), options));
3248
+ });
3249
+ let results = yield Promise.all(promises);
3250
+ results = results.reduce((prev, [, res]) => prev.concat(res), []);
3251
+ return results.map((call, i) => itf.decodeFunctionResult(calls[i][1], call));
3252
+ }
3253
+ catch (e) {
3254
+ return Promise.reject(e);
3255
+ }
3256
+ });
3257
+ }
3258
+
3259
+ /**
3260
+ * Parses the raw result from a Starknet function call based on its ABI.
3261
+ * It handles different types like felt252, u8, u256, etc., and decodes them accordingly.
3262
+ * @param rawResult - The raw result from the Starknet function call.
3263
+ * @param functionAbi - The ABI of the function that was called.
3264
+ * @returns The parsed result in a more usable format.
3265
+ */
3266
+ function parseStarknetResult(rawResult, functionAbi) {
3267
+ if (!functionAbi ||
3268
+ !functionAbi.outputs ||
3269
+ !Array.isArray(rawResult) ||
3270
+ rawResult.length === 0) {
3271
+ return rawResult;
3272
+ }
3273
+ const output = functionAbi.outputs[0];
3274
+ const rawValue = rawResult[0];
3275
+ try {
3276
+ switch (output.type) {
3277
+ case 'core::felt252':
3278
+ // Try to decode as shortString (for name, symbol)
3279
+ try {
3280
+ return shortString.decodeShortString(rawValue);
3281
+ }
3282
+ catch (_a) {
3283
+ // If shortString decode fails, return as hex
3284
+ return rawValue;
3285
+ }
3286
+ // Unsigned integers
3287
+ case 'core::integer::u8':
3288
+ case 'core::integer::u16':
3289
+ case 'core::integer::u32':
3290
+ case 'core::integer::u64':
3291
+ return parseInt(rawValue, 16);
3292
+ case 'core::integer::u128':
3293
+ case 'core::integer::usize':
3294
+ return BigInt(rawValue).toString();
3295
+ case 'core::integer::u256':
3296
+ return uint256.uint256ToBN({
3297
+ low: rawValue,
3298
+ high: rawResult[1] || '0x0'
3299
+ });
3300
+ // Signed integers
3301
+ case 'core::integer::i8':
3302
+ case 'core::integer::i16':
3303
+ case 'core::integer::i32':
3304
+ case 'core::integer::i64':
3305
+ return parseInt(rawValue, 16);
3306
+ case 'core::integer::i128':
3307
+ return BigInt(rawValue).toString();
3308
+ // Boolean type
3309
+ case 'core::bool':
3310
+ return rawValue === '0x1' || rawValue === '0x01';
3311
+ // Address types
3312
+ case 'core::starknet::contract_address::ContractAddress':
3313
+ case 'core::starknet::class_hash::ClassHash':
3314
+ case 'core::starknet::storage_access::StorageAddress':
3315
+ return rawValue;
3316
+ // Byte array
3317
+ case 'core::bytes_31::bytes31':
3318
+ return rawValue;
3319
+ default:
3320
+ // Return raw value for unknown types
3321
+ return rawValue;
3322
+ }
3323
+ }
3324
+ catch (_b) {
3325
+ // Fallback to raw result if parsing fails
3326
+ return rawResult;
3327
+ }
3328
+ }
3329
+ /**
3330
+ * Partitions the responses from a Starknet multicall into individual call results.
3331
+ * Each response starts with its length, followed by the actual response data.
3332
+ * @param responses - The array of responses from the Starknet multicall.
3333
+ * @returns An array of arrays, where each inner array contains the response data for a single call.
3334
+ */
3335
+ const partitionResponses = (responses) => {
3336
+ if (responses.length === 0) {
3337
+ return [];
3338
+ }
3339
+ const [responseLength, ...restResponses] = responses;
3340
+ const responseLengthInt = Number(num.toBigInt(responseLength));
3341
+ const response = restResponses.slice(0, responseLengthInt);
3342
+ const remainingResponses = restResponses.slice(responseLengthInt);
3343
+ return [response, ...partitionResponses(remainingResponses)];
3344
+ };
3345
+ function multicall$1(address_1, provider_1, abi_1, calls_1, limit_1) {
3346
+ return __awaiter(this, arguments, void 0, function* (address, provider, abi, calls, limit, options = {}) {
3347
+ const callData = calls.map((call) => {
3348
+ return {
3349
+ contractAddress: call[0],
3350
+ entrypoint: call[1],
3351
+ calldata: call[2] || []
3352
+ };
3353
+ });
3354
+ // Chunk calls into batches based on limit
3355
+ const chunks = [];
3356
+ for (let i = 0; i < callData.length; i += limit) {
3357
+ chunks.push(callData.slice(i, i + limit));
3358
+ }
3359
+ // Process each chunk
3360
+ const paginatedResults = yield Promise.all(chunks.map((chunk) => {
3361
+ var _a;
3362
+ return provider.callContract({
3363
+ contractAddress: address,
3364
+ entrypoint: 'aggregate',
3365
+ calldata: transaction.fromCallsToExecuteCalldata(chunk)
3366
+ }, (_a = options.blockTag) !== null && _a !== void 0 ? _a : 'latest');
3367
+ }));
3368
+ const callResults = paginatedResults
3369
+ .map((callContractResult) => {
3370
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3371
+ const [_blockNumber, _totalLength, ...results] = callContractResult;
3372
+ return partitionResponses(results);
3373
+ })
3374
+ .flat();
3375
+ return callResults.map((result, index) => {
3376
+ const [, functionName] = calls[index];
3377
+ const functionAbi = abi.find((item) => item.name === functionName);
3378
+ return [parseStarknetResult(result, functionAbi)];
3379
+ });
3380
+ });
3381
+ }
3382
+
3383
+ class Multicaller {
3384
+ constructor(network, provider, abi, options = {}) {
3385
+ this.options = {};
3386
+ this.calls = [];
3387
+ this.paths = [];
3388
+ this.network = network;
3389
+ this.provider = provider;
3390
+ this.abi = abi;
3391
+ this.options = options;
3392
+ }
3393
+ call(path, address, fn, params) {
3394
+ this.calls.push([address, fn, params]);
3395
+ this.paths.push(path);
3396
+ return this;
3397
+ }
3398
+ execute(from) {
3399
+ return __awaiter(this, void 0, void 0, function* () {
3400
+ const obj = from || {};
3401
+ const result = yield multicall$2(this.network, this.provider, this.abi, this.calls, this.options);
3402
+ result.forEach((r, i) => set(obj, this.paths[i], r.length > 1 ? r : r[0]));
3403
+ this.calls = [];
3404
+ this.paths = [];
3405
+ return obj;
3406
+ });
3407
+ }
3408
+ }
3409
+
3410
+ const STARKNET_CHAIN_IDS = [
3411
+ constants$1.StarknetChainId.SN_MAIN,
3412
+ constants$1.StarknetChainId.SN_SEPOLIA
3413
+ ];
3414
+ const MULTICALLS_FN = {
3415
+ evm: multicall,
3416
+ starknet: multicall$1
3417
+ };
3418
+ function multicall$2(network_1, provider_1, abi_1, calls_1) {
3419
+ return __awaiter(this, arguments, void 0, function* (network, provider, abi, calls, options = {}) {
3420
+ const address = (options === null || options === void 0 ? void 0 : options.multicallAddress) || networks[network].multicall;
3421
+ if (!address) {
3422
+ throw new Error('missing multicall address');
3423
+ }
3424
+ const multicallOptions = Object.assign({}, options);
3425
+ const limit = (multicallOptions === null || multicallOptions === void 0 ? void 0 : multicallOptions.limit) || 500;
3426
+ delete multicallOptions.limit;
3427
+ delete multicallOptions.multicallAddress;
3428
+ const protocol = STARKNET_CHAIN_IDS.includes(network)
3429
+ ? 'starknet'
3430
+ : 'evm';
3431
+ return MULTICALLS_FN[protocol](address, provider, abi, calls, limit, multicallOptions);
3432
+ });
3433
+ }
3434
+
3186
3435
  const MUTED_ERRORS = [
3187
3436
  // mute error from coinbase, when the subdomain is not found
3188
3437
  // most other resolvers just return an empty address
@@ -3196,16 +3445,6 @@ const ENS_ABI = [
3196
3445
  'function resolver(bytes32 node) view returns (address)' // ENS registry ABI
3197
3446
  ];
3198
3447
  const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000';
3199
- const STARKNET_NETWORKS = {
3200
- '0x534e5f4d41494e': {
3201
- name: 'Starknet',
3202
- testnet: false
3203
- },
3204
- '0x534e5f5345504f4c4941': {
3205
- name: 'Starknet Sepolia',
3206
- testnet: true
3207
- }
3208
- };
3209
3448
  const scoreApiHeaders = {
3210
3449
  Accept: 'application/json',
3211
3450
  'Content-Type': 'application/json'
@@ -3329,22 +3568,6 @@ ajv.addKeyword({
3329
3568
  message: 'network not allowed'
3330
3569
  }
3331
3570
  });
3332
- ajv.addKeyword({
3333
- keyword: 'starknetNetwork',
3334
- validate: function (schema, data) {
3335
- // @ts-ignore
3336
- const snapshotEnv = this.snapshotEnv || 'default';
3337
- if (snapshotEnv === 'mainnet') {
3338
- return Object.keys(STARKNET_NETWORKS)
3339
- .filter((id) => !STARKNET_NETWORKS[id].testnet)
3340
- .includes(data);
3341
- }
3342
- return Object.keys(STARKNET_NETWORKS).includes(data);
3343
- },
3344
- error: {
3345
- message: 'network not allowed'
3346
- }
3347
- });
3348
3571
  // Custom URL format to allow empty string values
3349
3572
  // https://github.com/snapshot-labs/snapshot.js/pull/541/files
3350
3573
  ajv.addFormat('customUrl', {
@@ -3413,36 +3636,6 @@ function call(provider, abi, call, options) {
3413
3636
  }
3414
3637
  });
3415
3638
  }
3416
- function multicall(network, provider, abi, calls, options) {
3417
- return __awaiter(this, void 0, void 0, function* () {
3418
- const multicallAbi = [
3419
- 'function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)'
3420
- ];
3421
- const multicallAddress = (options === null || options === void 0 ? void 0 : options.multicallAddress) || networks[network].multicall;
3422
- const multi = new Contract$1(multicallAddress, multicallAbi, provider);
3423
- const itf = new Interface(abi);
3424
- try {
3425
- const max = (options === null || options === void 0 ? void 0 : options.limit) || 500;
3426
- if (options === null || options === void 0 ? void 0 : options.limit)
3427
- delete options.limit;
3428
- const pages = Math.ceil(calls.length / max);
3429
- const promises = [];
3430
- Array.from(Array(pages)).forEach((x, i) => {
3431
- const callsInPage = calls.slice(max * i, max * (i + 1));
3432
- promises.push(multi.aggregate(callsInPage.map((call) => [
3433
- call[0].toLowerCase(),
3434
- itf.encodeFunctionData(call[1], call[2])
3435
- ]), options || {}));
3436
- });
3437
- let results = yield Promise.all(promises);
3438
- results = results.reduce((prev, [, res]) => prev.concat(res), []);
3439
- return results.map((call, i) => itf.decodeFunctionResult(calls[i][1], call));
3440
- }
3441
- catch (e) {
3442
- return Promise.reject(e);
3443
- }
3444
- });
3445
- }
3446
3639
  function subgraphRequest(url_1, query_1) {
3447
3640
  return __awaiter(this, arguments, void 0, function* (url, query, options = {}) {
3448
3641
  const body = { query: jsonToGraphQLQuery({ query }) };
@@ -3674,7 +3867,7 @@ function getEnsTextRecord(ens_1, record_1) {
3674
3867
  [ensHash, record]
3675
3868
  ]) // Query for text record from each resolver
3676
3869
  ];
3677
- const [[resolverAddress], ...textRecords] = yield multicall(network, provider, ENS_ABI, calls, multicallOptions);
3870
+ const [[resolverAddress], ...textRecords] = (yield multicall$2(network, provider, ENS_ABI, calls, multicallOptions));
3678
3871
  const resolverIndex = ensResolvers.indexOf(resolverAddress);
3679
3872
  return resolverIndex !== -1 ? (_b = textRecords[resolverIndex]) === null || _b === void 0 ? void 0 : _b[0] : null;
3680
3873
  });
@@ -3822,21 +4015,22 @@ function isEvmAddress(address) {
3822
4015
  return isAddress(address);
3823
4016
  }
3824
4017
  function getFormattedAddress(address, format) {
3825
- // Consider non-evm addresses as Starknet by default
3826
- // as there's no other way to differentiate them
3827
- const addressType = format !== null && format !== void 0 ? format : (isEvmAddress(address) ? 'evm' : 'starknet');
4018
+ if (typeof address !== 'string' || !/^0[xX]/.test(address)) {
4019
+ throw new Error(`Invalid address: ${address}`);
4020
+ }
4021
+ const addressType = format !== null && format !== void 0 ? format : (address.length === 42 ? 'evm' : 'starknet');
3828
4022
  if (addressType === 'evm' && isEvmAddress(address))
3829
4023
  return getAddress(address);
3830
4024
  if (addressType === 'starknet' && isStarknetAddress(address))
3831
4025
  return validateAndParseAddress(address);
3832
- throw new Error(`Invalid address: ${address}`);
4026
+ throw new Error(`Invalid ${addressType} address: ${address}`);
3833
4027
  }
3834
4028
  function inputError(message) {
3835
4029
  return Promise.reject(new Error(message));
3836
4030
  }
3837
4031
  var utils = {
3838
4032
  call,
3839
- multicall,
4033
+ multicall: multicall$2,
3840
4034
  subgraphRequest,
3841
4035
  ipfsGet,
3842
4036
  getUrl,
@@ -4126,8 +4320,7 @@ var definitions = {
4126
4320
  type: "string",
4127
4321
  snapshotNetwork: true,
4128
4322
  title: "network",
4129
- minLength: 1,
4130
- maxLength: 32
4323
+ minLength: 1
4131
4324
  },
4132
4325
  symbol: {
4133
4326
  type: "string",
@@ -4170,7 +4363,6 @@ var definitions = {
4170
4363
  },
4171
4364
  network: {
4172
4365
  type: "string",
4173
- maxLength: 12,
4174
4366
  title: "network",
4175
4367
  snapshotNetwork: true
4176
4368
  },
@@ -4369,15 +4561,7 @@ var definitions = {
4369
4561
  type: "string",
4370
4562
  title: "Delegation network",
4371
4563
  description: "The network of your delegation contract",
4372
- anyOf: [
4373
- {
4374
- snapshotNetwork: true
4375
- },
4376
- {
4377
- starknetNetwork: true
4378
- }
4379
- ],
4380
- errorMessage: "Must be a valid network"
4564
+ snapshotNetwork: true
4381
4565
  },
4382
4566
  delegationApi: {
4383
4567
  type: "string",
@@ -4519,15 +4703,7 @@ var definitions = {
4519
4703
  network: {
4520
4704
  type: "string",
4521
4705
  title: "Network",
4522
- anyOf: [
4523
- {
4524
- snapshotNetwork: true
4525
- },
4526
- {
4527
- starknetNetwork: true
4528
- }
4529
- ],
4530
- errorMessage: "Must be a valid network"
4706
+ snapshotNetwork: true
4531
4707
  }
4532
4708
  },
4533
4709
  required: [