@snapshot-labs/snapshot.js 0.12.1 → 0.12.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapshot-labs/snapshot.js",
3
- "version": "0.12.1",
3
+ "version": "0.12.2",
4
4
  "repository": "snapshot-labs/snapshot.js",
5
5
  "license": "MIT",
6
6
  "main": "dist/snapshot.cjs.js",
@@ -11,6 +11,7 @@
11
11
  "@ensdomains/eth-ens-namehash": "^2.0.15",
12
12
  "@ethersproject/abi": "^5.6.4",
13
13
  "@ethersproject/address": "^5.6.1",
14
+ "@ethersproject/bignumber": "^5.7.0",
14
15
  "@ethersproject/bytes": "^5.6.1",
15
16
  "@ethersproject/contracts": "^5.6.2",
16
17
  "@ethersproject/hash": "^5.7.0",
@@ -1,7 +1,9 @@
1
1
  import { test, expect, describe } from 'vitest';
2
2
  import starknetMessage from '../../test/fixtures/starknet/message-alias.json';
3
+ import starknetMessageRsv from '../../test/fixtures/starknet/message-alias-rsv.json';
3
4
  import verify, { getHash } from './starknet';
4
5
  import { validateAndParseAddress } from 'starknet';
6
+ import { clone } from '../utils';
5
7
 
6
8
  describe('verify/starknet', () => {
7
9
  describe('getHash()', () => {
@@ -21,47 +23,79 @@ describe('verify/starknet', () => {
21
23
  });
22
24
 
23
25
  describe('verify()', () => {
24
- test('should return true if the signature is valid', () => {
25
- expect(
26
- verify(
27
- starknetMessage.address,
28
- starknetMessage.sig,
29
- starknetMessage.data,
30
- 'SN_SEPOLIA'
31
- )
32
- ).resolves.toBe(true);
26
+ describe.each([
27
+ ['2', starknetMessage],
28
+ ['3', starknetMessageRsv]
29
+ ])('with a %s items signature', (title, message) => {
30
+ test('should return true if the signature is valid', () => {
31
+ expect(
32
+ verify(message.address, message.sig, message.data, 'SN_MAIN')
33
+ ).resolves.toBe(true);
34
+ });
35
+
36
+ test('should return true if the signature is valid with a padded address', () => {
37
+ expect(
38
+ verify(
39
+ validateAndParseAddress(message.address),
40
+ message.sig,
41
+ message.data,
42
+ 'SN_MAIN'
43
+ )
44
+ ).resolves.toBe(true);
45
+ });
46
+
47
+ test('should return true when verifying on a different network', () => {
48
+ expect(
49
+ verify(message.address, message.sig, message.data, 'SN_SEPOLIA')
50
+ ).resolves.toBe(true);
51
+ });
52
+
53
+ test('should throw an error if the signature is invalid', () => {
54
+ expect(
55
+ verify(
56
+ '0x7667469b8e93faa642573078b6bf8c790d3a6184b2a1bb39c5c923a732862e1',
57
+ message.sig,
58
+ message.data
59
+ )
60
+ ).rejects.toThrow();
61
+ });
33
62
  });
34
63
 
35
- test('should return true if the signature is valid with a padded address', () => {
64
+ test('should throw an error when the contract is not deployed', () => {
36
65
  expect(
37
66
  verify(
38
- validateAndParseAddress(starknetMessage.address),
67
+ '0x07f71118e351c02f6EC7099C8CDf93AED66CEd8406E94631cC91637f7D7F203A',
39
68
  starknetMessage.sig,
40
69
  starknetMessage.data,
41
- 'SN_SEPOLIA'
70
+ 'SN_MAIN'
42
71
  )
43
- ).resolves.toBe(true);
72
+ ).rejects.toThrowError('Contract not deployed');
44
73
  });
45
74
 
46
- test('should throw an error if message is on wrong network', () => {
75
+ test('should return false when the signature is not valid', () => {
47
76
  expect(
48
77
  verify(
49
78
  starknetMessage.address,
50
- starknetMessage.sig,
79
+ ['1', '2'],
51
80
  starknetMessage.data,
52
81
  'SN_MAIN'
53
82
  )
54
- ).rejects.toThrowError();
83
+ ).resolves.toBe(false);
55
84
  });
56
85
 
57
- test('should throw an error if the signature is invalid', () => {
86
+ test('should return false when the signature is not valid', () => {
87
+ const data = clone(starknetMessage.data);
88
+ data.message.timestamp = 1234;
89
+
58
90
  expect(
59
- verify(
60
- '0x7667469b8e93faa642573078b6bf8c790d3a6184b2a1bb39c5c923a732862e1',
61
- starknetMessage.sig,
62
- starknetMessage.data
63
- )
64
- ).rejects.toThrow();
91
+ verify(starknetMessage.address, starknetMessage.sig, data, 'SN_MAIN')
92
+ ).resolves.toBe(false);
93
+ });
94
+
95
+ test('should throw an error on wrong signature length', () => {
96
+ expect(
97
+ verify(starknetMessage.address, ['1'], starknetMessage.data, 'SN_MAIN')
98
+ ).rejects.toThrowError('Invalid signature format');
65
99
  });
66
100
  });
67
101
  });
@@ -1,4 +1,5 @@
1
1
  import { Contract, RpcProvider, typedData } from 'starknet';
2
+ import { BigNumber } from '@ethersproject/bignumber';
2
3
  import type { SignaturePayload } from '.';
3
4
  import type { ProviderOptions } from '../utils/provider';
4
5
 
@@ -11,11 +12,11 @@ const RPC_URLS: Record<NetworkType, string> = {
11
12
 
12
13
  const ABI = [
13
14
  {
14
- name: 'argent::account::interface::IDeprecatedArgentAccount',
15
+ name: 'argent::common::account::IAccount',
15
16
  type: 'interface',
16
17
  items: [
17
18
  {
18
- name: 'isValidSignature',
19
+ name: 'is_valid_signature',
19
20
  type: 'function',
20
21
  inputs: [
21
22
  {
@@ -23,7 +24,7 @@ const ABI = [
23
24
  type: 'core::felt252'
24
25
  },
25
26
  {
26
- name: 'signatures',
27
+ name: 'signature',
27
28
  type: 'core::array::Array::<core::felt252>'
28
29
  }
29
30
  ],
@@ -67,16 +68,28 @@ export default async function verify(
67
68
  network: NetworkType = 'SN_MAIN',
68
69
  options: ProviderOptions = {}
69
70
  ): Promise<boolean> {
70
- const contractAccount = new Contract(
71
- ABI,
72
- address,
73
- getProvider(network, options)
74
- );
71
+ try {
72
+ const contractAccount = new Contract(
73
+ ABI,
74
+ address,
75
+ getProvider(network, options)
76
+ );
77
+
78
+ if (sig.length < 2) {
79
+ throw new Error('Invalid signature format');
80
+ }
75
81
 
76
- await contractAccount.isValidSignature(getHash(data, address), [
77
- sig[0],
78
- sig[1]
79
- ]);
82
+ const result = await contractAccount.is_valid_signature(
83
+ getHash(data, address),
84
+ sig.slice(-2)
85
+ );
80
86
 
81
- return true;
87
+ return BigNumber.from(result).eq(BigNumber.from('370462705988'));
88
+ } catch (e: any) {
89
+ if (e.message.includes('Contract not found')) {
90
+ throw new Error('Contract not deployed');
91
+ }
92
+
93
+ throw e;
94
+ }
82
95
  }