starknet 4.3.1 → 4.4.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ # [4.4.0](https://github.com/0xs34n/starknet.js/compare/v4.3.1...v4.4.0) (2022-09-01)
2
+
3
+ ### Bug Fixes
4
+
5
+ - delete premature session account file ([ca3e70b](https://github.com/0xs34n/starknet.js/commit/ca3e70b06d21dba8b2074512251cf232ed8be46b))
6
+ - session ([00269bf](https://github.com/0xs34n/starknet.js/commit/00269bfd23ed647270a1efd699af7c36978965c7))
7
+ - session account prooving ([0b56833](https://github.com/0xs34n/starknet.js/commit/0b56833f6eb7557d55725a505a01185bbc9756db))
8
+ - tests ([4586e93](https://github.com/0xs34n/starknet.js/commit/4586e93f10a2a43c375a23d851a9778bab412fcc))
9
+ - typo ([1c60a4d](https://github.com/0xs34n/starknet.js/commit/1c60a4d4b306879422769a6c2afc4fd6c39c4c07))
10
+
11
+ ### Features
12
+
13
+ - add merkle trees ([e9b8674](https://github.com/0xs34n/starknet.js/commit/e9b8674f51c6d6fe57772a4c88b162c5132cfbdd))
14
+ - add visibility modifiers ([cd1a23d](https://github.com/0xs34n/starknet.js/commit/cd1a23d74b49407c27314a12d5bc149ed40209f3))
15
+ - allow merkle trees as native type in eip712 like messages ([65b7766](https://github.com/0xs34n/starknet.js/commit/65b7766c29eca4f4d0e89f6ad1368fedd5e0e18e))
16
+ - session ([9ac48cc](https://github.com/0xs34n/starknet.js/commit/9ac48cc15c1c7b0e504adfc79a7f382f5d0b55d0))
17
+ - session needs to be aware of the whole tree ([11e10bd](https://github.com/0xs34n/starknet.js/commit/11e10bda0f020a670854d941a54142d55936fc18))
18
+
1
19
  ## [4.3.1](https://github.com/0xs34n/starknet.js/compare/v4.3.0...v4.3.1) (2022-08-31)
2
20
 
3
21
  ### Bug Fixes
@@ -0,0 +1,42 @@
1
+ {
2
+ "primaryType": "Session",
3
+ "types": {
4
+ "Policy": [
5
+ { "name": "contractAddress", "type": "felt" },
6
+ { "name": "selector", "type": "selector" }
7
+ ],
8
+ "Session": [
9
+ { "name": "key", "type": "felt" },
10
+ { "name": "expires", "type": "felt" },
11
+ { "name": "root", "type": "merkletree", "contains": "Policy" }
12
+ ],
13
+ "StarkNetDomain": [
14
+ { "name": "name", "type": "felt" },
15
+ { "name": "version", "type": "felt" },
16
+ { "name": "chain_id", "type": "felt" }
17
+ ]
18
+ },
19
+ "domain": {
20
+ "name": "StarkNet Mail",
21
+ "version": "1",
22
+ "chain_id": 1
23
+ },
24
+ "message": {
25
+ "key": "0x0000000000000000000000000000000000000000000000000000000000000000",
26
+ "expires": "0x0000000000000000000000000000000000000000000000000000000000000000",
27
+ "root": [
28
+ {
29
+ "contractAddress": "0x1",
30
+ "selector": "transfer"
31
+ },
32
+ {
33
+ "contractAddress": "0x2",
34
+ "selector": "transfer"
35
+ },
36
+ {
37
+ "contractAddress": "0x3",
38
+ "selector": "transfer"
39
+ }
40
+ ]
41
+ }
42
+ }
@@ -1,3 +1,5 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`pedersen() 1`] = `"0x5ed2703dfdb505c587700ce2ebfcab5b3515cd7e6114817e6026ec9d4b364ca"`;
4
+
5
+ exports[`pedersen() with 0 1`] = `"0x1a5c561f97b52c17a19f34c4499a745cd4e8412e29e4ed5e91e4481c7d53935"`;
@@ -25,6 +25,11 @@ test('pedersen()', () => {
25
25
  expect(own).toMatchSnapshot();
26
26
  });
27
27
 
28
+ test('pedersen() with 0', () => {
29
+ const own = pedersen(['0x12773', '0x0']);
30
+ expect(own).toMatchSnapshot();
31
+ });
32
+
28
33
  test('computeHashOnElements()', () => {
29
34
  const array = ['1', '2', '3', '4'];
30
35
  expect(computeHashOnElements(array)).toBe(
@@ -0,0 +1,146 @@
1
+ import { MerkleTree, proofMerklePath } from '../../src/utils/merkle';
2
+
3
+ describe('MerkleTree class', () => {
4
+ describe('generate roots', () => {
5
+ test('should generate valid root for 1 elements', async () => {
6
+ const leaves = ['0x1'];
7
+ const tree = new MerkleTree(leaves);
8
+
9
+ const manualMerkle = leaves[0];
10
+
11
+ expect(tree.root).toBe(manualMerkle);
12
+ });
13
+ test('should generate valid root for 2 elements', async () => {
14
+ const leaves = ['0x1', '0x2'];
15
+ const tree = new MerkleTree(leaves);
16
+
17
+ const manualMerkle = MerkleTree.hash(leaves[0], leaves[1]);
18
+
19
+ expect(tree.root).toBe(manualMerkle);
20
+ });
21
+ test('should generate valid root for 4 elements', async () => {
22
+ const leaves = ['0x1', '0x2', '0x3', '0x4'];
23
+ const tree = new MerkleTree(leaves);
24
+
25
+ const manualMerkle = MerkleTree.hash(
26
+ MerkleTree.hash(leaves[0], leaves[1]),
27
+ MerkleTree.hash(leaves[2], leaves[3])
28
+ );
29
+
30
+ expect(tree.root).toBe(manualMerkle);
31
+ });
32
+ test('should generate valid root for 6 elements', async () => {
33
+ const leaves = ['0x1', '0x2', '0x3', '0x4', '0x5', '0x6'];
34
+ const tree = new MerkleTree(leaves);
35
+
36
+ const manualMerkle = MerkleTree.hash(
37
+ MerkleTree.hash(
38
+ MerkleTree.hash(leaves[0], leaves[1]),
39
+ MerkleTree.hash(leaves[2], leaves[3])
40
+ ),
41
+ MerkleTree.hash(leaves[4], leaves[5])
42
+ );
43
+
44
+ expect(tree.root).toBe(manualMerkle);
45
+ });
46
+ test('should generate valid root for 7 elements', async () => {
47
+ const leaves = ['0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7'];
48
+ const tree = new MerkleTree(leaves);
49
+
50
+ const manualMerkle = MerkleTree.hash(
51
+ MerkleTree.hash(
52
+ MerkleTree.hash(leaves[0], leaves[1]),
53
+ MerkleTree.hash(leaves[2], leaves[3])
54
+ ),
55
+ MerkleTree.hash(MerkleTree.hash(leaves[4], leaves[5]), leaves[6])
56
+ );
57
+
58
+ expect(tree.root).toBe(manualMerkle);
59
+ });
60
+ });
61
+ describe('generate proofs', () => {
62
+ let tree: MerkleTree;
63
+ beforeAll(() => {
64
+ const leaves = ['0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7'];
65
+ tree = new MerkleTree(leaves);
66
+ });
67
+ test('should return proof path for valid child', async () => {
68
+ const proof = tree.getProof('0x3');
69
+
70
+ const manualProof = [
71
+ '0x4',
72
+ MerkleTree.hash('0x1', '0x2'),
73
+ MerkleTree.hash(MerkleTree.hash('0x5', '0x6'), '0x7'),
74
+ ];
75
+
76
+ expect(proof).toEqual(manualProof);
77
+ });
78
+ test('should return proof path for valid child', async () => {
79
+ const proof = tree.getProof('0x7');
80
+
81
+ const manualProof = [
82
+ '0x0', // proofs should always be as long as the tree is deep
83
+ MerkleTree.hash('0x5', '0x6'),
84
+ MerkleTree.hash(MerkleTree.hash('0x1', '0x2'), MerkleTree.hash('0x3', '0x4')),
85
+ ];
86
+
87
+ expect(proof).toEqual(manualProof);
88
+ });
89
+ test('should throw for invalid child', () => {
90
+ expect(() => tree.getProof('0x8')).toThrow('leaf not found');
91
+ });
92
+ });
93
+ describe('verify proofs', () => {
94
+ let tree: MerkleTree;
95
+ beforeAll(() => {
96
+ const leaves = ['0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7'];
97
+ tree = new MerkleTree(leaves);
98
+ });
99
+
100
+ test('should return true for valid manual proof', async () => {
101
+ const manualProof = [
102
+ MerkleTree.hash('0x5', '0x6'),
103
+ MerkleTree.hash(MerkleTree.hash('0x1', '0x2'), MerkleTree.hash('0x3', '0x4')),
104
+ ];
105
+ const leaf = '0x7';
106
+ const { root } = tree;
107
+
108
+ expect(proofMerklePath(root, leaf, manualProof)).toBe(true);
109
+ });
110
+ test('should return true for valid proof', async () => {
111
+ const proof = tree.getProof('0x3');
112
+ const leaf = '0x3';
113
+ const { root } = tree;
114
+
115
+ expect(proofMerklePath(root, leaf, proof)).toBe(true);
116
+ });
117
+ test('should return false for invalid proof (root)', async () => {
118
+ const proof = tree.getProof('0x3');
119
+ const leaf = '0x3';
120
+ const root = '0x4';
121
+
122
+ expect(proofMerklePath(root, leaf, proof)).toBe(false);
123
+ });
124
+ test('should return false for invalid proof (proof[0])', async () => {
125
+ const proof = tree.getProof('0x3');
126
+ const leaf = '0x3';
127
+ const { root } = tree;
128
+ proof[0] = '0x7';
129
+ expect(proofMerklePath(root, leaf, proof)).toBe(false);
130
+ });
131
+ test('should return false for invalid proof (proof[1])', async () => {
132
+ const proof = tree.getProof('0x3');
133
+ const leaf = '0x3';
134
+ const { root } = tree;
135
+ proof[1] = '0x4';
136
+ expect(proofMerklePath(root, leaf, proof)).toBe(false);
137
+ });
138
+ test('should return false for invalid proof (proof[2])', async () => {
139
+ const proof = tree.getProof('0x3');
140
+ const leaf = '0x3';
141
+ const { root } = tree;
142
+ proof[2] = '0x4';
143
+ expect(proofMerklePath(root, leaf, proof)).toBe(false);
144
+ });
145
+ });
146
+ });
@@ -1,46 +1,134 @@
1
1
  import typedDataExample from '../../__mocks__/typedDataExample.json';
2
+ import typedDataSessionExample from '../../__mocks__/typedDataSessionExample.json';
2
3
  import typedDataStructArrayExample from '../../__mocks__/typedDataStructArrayExample.json';
3
4
  import { number } from '../../src';
5
+ import { getSelectorFromName } from '../../src/utils/hash';
6
+ import { MerkleTree } from '../../src/utils/merkle';
4
7
  import { BigNumberish } from '../../src/utils/number';
5
- import { encodeType, getMessageHash, getStructHash, getTypeHash } from '../../src/utils/typedData';
8
+ import {
9
+ StarkNetDomain,
10
+ encodeType,
11
+ encodeValue,
12
+ getMessageHash,
13
+ getStructHash,
14
+ getTypeHash,
15
+ } from '../../src/utils/typedData';
6
16
 
7
17
  describe('typedData', () => {
8
18
  test('should get right type encoding', () => {
9
- const typeEncoding = encodeType(typedDataExample, 'Mail');
19
+ const typeEncoding = encodeType(typedDataExample.types, 'Mail');
10
20
  expect(typeEncoding).toMatchInlineSnapshot(
11
21
  `"Mail(from:Person,to:Person,contents:felt)Person(name:felt,wallet:felt)"`
12
22
  );
13
- const typeEncodingStructArr = encodeType(typedDataStructArrayExample, 'Mail');
23
+ const typeEncodingStructArr = encodeType(typedDataStructArrayExample.types, 'Mail');
14
24
  expect(typeEncodingStructArr).toMatchInlineSnapshot(
15
25
  `"Mail(from:Person,to:Person,posts_len:felt,posts:Post*)Person(name:felt,wallet:felt)Post(title:felt,content:felt)"`
16
26
  );
17
27
  });
18
28
 
19
29
  test('should get right type hash', () => {
20
- const typeHashDomain = getTypeHash(typedDataExample, 'StarkNetDomain');
30
+ const typeHashDomain = getTypeHash(typedDataExample.types, 'StarkNetDomain');
21
31
  expect(typeHashDomain).toMatchInlineSnapshot(
22
32
  `"0x1bfc207425a47a5dfa1a50a4f5241203f50624ca5fdf5e18755765416b8e288"`
23
33
  );
24
- const typeHashPerson = getTypeHash(typedDataExample, 'Person');
34
+ const typeHashPerson = getTypeHash(typedDataExample.types, 'Person');
25
35
  expect(typeHashPerson).toMatchInlineSnapshot(
26
36
  `"0x2896dbe4b96a67110f454c01e5336edc5bbc3635537efd690f122f4809cc855"`
27
37
  );
28
- const typeHashMail = getTypeHash(typedDataExample, 'Mail');
38
+ const typeHashMail = getTypeHash(typedDataExample.types, 'Mail');
29
39
  expect(typeHashMail).toMatchInlineSnapshot(
30
40
  `"0x13d89452df9512bf750f539ba3001b945576243288137ddb6c788457d4b2f79"`
31
41
  );
32
- const typeHashPost = getTypeHash(typedDataStructArrayExample, 'Post');
42
+ const typeHashPost = getTypeHash(typedDataStructArrayExample.types, 'Post');
33
43
  expect(typeHashPost).toMatchInlineSnapshot(
34
44
  `"0x1d71e69bf476486b43cdcfaf5a85c00bb2d954c042b281040e513080388356d"`
35
45
  );
36
- const typeHashMailWithStructArray = getTypeHash(typedDataStructArrayExample, 'Mail');
46
+ const typeHashMailWithStructArray = getTypeHash(typedDataStructArrayExample.types, 'Mail');
37
47
  expect(typeHashMailWithStructArray).toMatchInlineSnapshot(
38
48
  `"0x873b878e35e258fc99e3085d5aaad3a81a0c821f189c08b30def2cde55ff27"`
39
49
  );
50
+ const selectorTypeHash = getTypeHash({}, 'selector');
51
+ expect(selectorTypeHash).toMatchInlineSnapshot(
52
+ `"0x1d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"`
53
+ );
54
+ });
55
+
56
+ test('should transform type selector', () => {
57
+ const selector = 'transfer';
58
+ const selectorHash = getSelectorFromName(selector);
59
+ const rawSelectorValueHash = encodeValue({}, 'felt', selectorHash);
60
+ const selectorValueHash = encodeValue({}, 'selector', selector);
61
+ expect(selectorValueHash).toEqual(rawSelectorValueHash);
62
+ expect(selectorValueHash).toMatchInlineSnapshot(`
63
+ Array [
64
+ "felt",
65
+ "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e",
66
+ ]
67
+ `);
68
+ });
69
+
70
+ test('should transform merkle tree', () => {
71
+ const tree = new MerkleTree(['0x1', '0x2', '0x3']);
72
+ const [, merkleTreeHash] = encodeValue({}, 'merkletree', tree.leaves);
73
+ expect(merkleTreeHash).toBe(tree.root);
74
+ expect(merkleTreeHash).toMatchInlineSnapshot(
75
+ `"0x551b4adb6c35d49c686a00b9192da9332b18c9b262507cad0ece37f3b6918d2"`
76
+ );
77
+ });
78
+
79
+ test('should transform merkle tree with custom types', () => {
80
+ const leaves = [
81
+ {
82
+ contractAddress: '0x1',
83
+ selector: 'transfer',
84
+ },
85
+ {
86
+ contractAddress: '0x2',
87
+ selector: 'transfer',
88
+ },
89
+ {
90
+ contractAddress: '0x3',
91
+ selector: 'transfer',
92
+ },
93
+ ];
94
+ const hashedLeaves = leaves.map(
95
+ (leaf) =>
96
+ encodeValue(
97
+ {
98
+ Policy: [
99
+ { name: 'contractAddress', type: 'felt' },
100
+ { name: 'selector', type: 'selector' },
101
+ ],
102
+ },
103
+ 'Policy',
104
+ leaf
105
+ )[1]
106
+ );
107
+ const tree = new MerkleTree(hashedLeaves);
108
+ const [, merkleTreeHash] = encodeValue(
109
+ {
110
+ Parent: [{ name: 'root', type: 'merkletree', contains: 'Policy' }],
111
+ Policy: [
112
+ { name: 'contractAddress', type: 'felt' },
113
+ { name: 'selector', type: 'selector' },
114
+ ],
115
+ },
116
+ 'merkletree',
117
+ leaves,
118
+ { key: 'root', parent: 'Parent' }
119
+ );
120
+ expect(merkleTreeHash).toBe(tree.root);
121
+ expect(merkleTreeHash).toMatchInlineSnapshot(
122
+ `"0x75c4f467f4527a5348f3e302007228a6b0057fc4c015f981ffb5b3ace475727"`
123
+ );
40
124
  });
41
125
 
42
126
  test('should get right hash for StarkNetDomain', () => {
43
- const hash = getStructHash(typedDataExample, 'StarkNetDomain', typedDataExample.domain as any);
127
+ const hash = getStructHash(
128
+ typedDataExample.types,
129
+ 'StarkNetDomain',
130
+ typedDataExample.domain as StarkNetDomain
131
+ );
44
132
  expect(hash).toMatchInlineSnapshot(
45
133
  `"0x54833b121883a3e3aebff48ec08a962f5742e5f7b973469c1f8f4f55d470b07"`
46
134
  );
@@ -122,4 +210,14 @@ describe('typedData', () => {
122
210
  `"0x70338fb11b8f70b68b261de8a322bcb004bd85e88ac47d9147982c7f5ac66fd"`
123
211
  );
124
212
  });
213
+
214
+ test('should transform session message correctly', () => {
215
+ const hash = getMessageHash(
216
+ typedDataSessionExample,
217
+ '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
218
+ );
219
+ expect(hash).toMatchInlineSnapshot(
220
+ `"0x1ad0330a62a4a94eae5ea1a7ad96388179d2e4d33e6f909d17421d315110653"`
221
+ );
222
+ });
125
223
  });
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export * as json from './utils/json';
16
16
  export * as number from './utils/number';
17
17
  export * as transaction from './utils/transaction';
18
18
  export * as stark from './utils/stark';
19
+ export * as merkle from './utils/merkle';
19
20
  export * as ec from './utils/ellipticCurve';
20
21
  export * as uint256 from './utils/uint256';
21
22
  export * as shortString from './utils/shortString';
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
26
26
  return result;
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.typedData = exports.shortString = exports.uint256 = exports.ec = exports.stark = exports.transaction = exports.number = exports.json = exports.hash = exports.encode = exports.constants = void 0;
29
+ exports.typedData = exports.shortString = exports.uint256 = exports.ec = exports.merkle = exports.stark = exports.transaction = exports.number = exports.json = exports.hash = exports.encode = exports.constants = void 0;
30
30
  /**
31
31
  * Main
32
32
  */
@@ -45,6 +45,7 @@ exports.json = __importStar(require("./utils/json"));
45
45
  exports.number = __importStar(require("./utils/number"));
46
46
  exports.transaction = __importStar(require("./utils/transaction"));
47
47
  exports.stark = __importStar(require("./utils/stark"));
48
+ exports.merkle = __importStar(require("./utils/merkle"));
48
49
  exports.ec = __importStar(require("./utils/ellipticCurve"));
49
50
  exports.uint256 = __importStar(require("./utils/uint256"));
50
51
  exports.shortString = __importStar(require("./utils/shortString"));
@@ -3,7 +3,7 @@ import { TypedData } from '../utils/typedData';
3
3
  import { SignerInterface } from './interface';
4
4
  export declare class Signer implements SignerInterface {
5
5
  protected keyPair: KeyPair;
6
- constructor(keyPair: KeyPair);
6
+ constructor(keyPair?: KeyPair);
7
7
  getPubKey(): Promise<string>;
8
8
  signTransaction(transactions: Invocation[], transactionsDetail: InvocationsSignerDetails, abis?: Abi[]): Promise<Signature>;
9
9
  signMessage(typedData: TypedData, accountAddress: string): Promise<Signature>;
@@ -43,6 +43,7 @@ var transaction_1 = require("../utils/transaction");
43
43
  var typedData_1 = require("../utils/typedData");
44
44
  var Signer = /** @class */ (function () {
45
45
  function Signer(keyPair) {
46
+ if (keyPair === void 0) { keyPair = (0, ellipticCurve_1.genKeyPair)(); }
46
47
  this.keyPair = keyPair;
47
48
  }
48
49
  Signer.prototype.getPubKey = function () {
@@ -78,13 +78,15 @@ function pedersen(input) {
78
78
  for (var i = 0; i < input.length; i += 1) {
79
79
  var x = (0, number_1.toBN)(input[i]);
80
80
  (0, minimalistic_assert_1.default)(x.gte(constants_1.ZERO) && x.lt((0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.FIELD_PRIME))), "Invalid input: ".concat(input[i]));
81
- for (var j = 0; j < 252; j += 1) {
82
- var pt = constantPoints[2 + i * 252 + j];
83
- (0, minimalistic_assert_1.default)(!point.getX().eq(pt.getX()));
84
- if (x.and(constants_1.ONE).toNumber() !== 0) {
85
- point = point.add(pt);
81
+ if (!x.isZero()) {
82
+ for (var j = 0; j < 252; j += 1) {
83
+ var pt = constantPoints[2 + i * 252 + j];
84
+ (0, minimalistic_assert_1.default)(!point.getX().eq(pt.getX()));
85
+ if (x.and(constants_1.ONE).toNumber() !== 0) {
86
+ point = point.add(pt);
87
+ }
88
+ x = x.shrn(1);
86
89
  }
87
- x = x.shrn(1);
88
90
  }
89
91
  }
90
92
  return (0, encode_1.addHexPrefix)(point.getX().toString(16));
@@ -0,0 +1,10 @@
1
+ export declare class MerkleTree {
2
+ leaves: string[];
3
+ branches: string[][];
4
+ root: string;
5
+ constructor(leafHashes: string[]);
6
+ private build;
7
+ static hash(a: string, b: string): string;
8
+ getProof(leaf: string, branch?: string[], hashPath?: string[]): string[];
9
+ }
10
+ export declare function proofMerklePath(root: string, leaf: string, path: string[]): boolean;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __read = (this && this.__read) || function (o, n) {
3
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
4
+ if (!m) return o;
5
+ var i = m.call(o), r, ar = [], e;
6
+ try {
7
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
8
+ }
9
+ catch (error) { e = { error: error }; }
10
+ finally {
11
+ try {
12
+ if (r && !r.done && (m = i["return"])) m.call(i);
13
+ }
14
+ finally { if (e) throw e.error; }
15
+ }
16
+ return ar;
17
+ };
18
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
20
+ if (ar || !(i in from)) {
21
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
22
+ ar[i] = from[i];
23
+ }
24
+ }
25
+ return to.concat(ar || Array.prototype.slice.call(from));
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.proofMerklePath = exports.MerkleTree = void 0;
29
+ var hash_1 = require("./hash");
30
+ var MerkleTree = /** @class */ (function () {
31
+ function MerkleTree(leafHashes) {
32
+ this.branches = [];
33
+ this.leaves = leafHashes;
34
+ this.root = this.build(leafHashes);
35
+ }
36
+ MerkleTree.prototype.build = function (leaves) {
37
+ if (leaves.length === 1) {
38
+ return leaves[0];
39
+ }
40
+ if (leaves.length !== this.leaves.length) {
41
+ this.branches.push(leaves);
42
+ }
43
+ var newLeaves = [];
44
+ for (var i = 0; i < leaves.length; i += 2) {
45
+ if (i + 1 === leaves.length) {
46
+ newLeaves.push(leaves[i]);
47
+ }
48
+ else {
49
+ newLeaves.push(MerkleTree.hash(leaves[i], leaves[i + 1]));
50
+ }
51
+ }
52
+ return this.build(newLeaves);
53
+ };
54
+ MerkleTree.hash = function (a, b) {
55
+ var _a = __read([a, b].sort(), 2), aSorted = _a[0], bSorted = _a[1];
56
+ return (0, hash_1.pedersen)([aSorted, bSorted]);
57
+ };
58
+ MerkleTree.prototype.getProof = function (leaf, branch, hashPath) {
59
+ var _a, _b;
60
+ if (branch === void 0) { branch = this.leaves; }
61
+ if (hashPath === void 0) { hashPath = []; }
62
+ var index = branch.indexOf(leaf);
63
+ if (index === -1) {
64
+ throw new Error('leaf not found');
65
+ }
66
+ if (branch.length === 1) {
67
+ return hashPath;
68
+ }
69
+ var isLeft = index % 2 === 0;
70
+ var neededBranch = (_a = (isLeft ? branch[index + 1] : branch[index - 1])) !== null && _a !== void 0 ? _a : '0x0';
71
+ var newHashPath = __spreadArray(__spreadArray([], __read(hashPath), false), [neededBranch], false);
72
+ var currentBranchLevelIndex = this.leaves.length === branch.length
73
+ ? -1
74
+ : this.branches.findIndex(function (b) { return b.length === branch.length; });
75
+ var nextBranch = (_b = this.branches[currentBranchLevelIndex + 1]) !== null && _b !== void 0 ? _b : [this.root];
76
+ return this.getProof(neededBranch === '0x0'
77
+ ? leaf
78
+ : MerkleTree.hash(isLeft ? leaf : neededBranch, isLeft ? neededBranch : leaf), nextBranch, newHashPath);
79
+ };
80
+ return MerkleTree;
81
+ }());
82
+ exports.MerkleTree = MerkleTree;
83
+ function proofMerklePath(root, leaf, path) {
84
+ if (path.length === 0) {
85
+ return root === leaf;
86
+ }
87
+ var _a = __read(path), next = _a[0], rest = _a.slice(1);
88
+ return proofMerklePath(root, MerkleTree.hash(leaf, next), rest);
89
+ }
90
+ exports.proofMerklePath = proofMerklePath;
@@ -31,7 +31,7 @@ var bn_js_1 = __importStar(require("bn.js"));
31
31
  var minimalistic_assert_1 = __importDefault(require("minimalistic-assert"));
32
32
  var encode_1 = require("./encode");
33
33
  function isHex(hex) {
34
- return hex.startsWith('0x');
34
+ return /^0x[0-9a-f]*$/i.test(hex);
35
35
  }
36
36
  exports.isHex = isHex;
37
37
  function toBN(number, base) {
@@ -1,6 +1,12 @@
1
1
  import { BigNumberish } from '../number';
2
- import { TypedData } from './types';
2
+ import { StarkNetMerkleType, StarkNetType, TypedData } from './types';
3
3
  export * from './types';
4
+ export declare function prepareSelector(selector: string): string;
5
+ export declare function isMerkleTreeType(type: StarkNetType): type is StarkNetMerkleType;
6
+ interface Context {
7
+ parent?: string;
8
+ key?: string;
9
+ }
4
10
  /**
5
11
  * Get the dependencies of a struct type. If a struct has the same dependency multiple times, it's only included once
6
12
  * in the resulting array.
@@ -10,7 +16,7 @@ export * from './types';
10
16
  * @param {string[]} [dependencies]
11
17
  * @return {string[]}
12
18
  */
13
- export declare const getDependencies: (typedData: TypedData, type: string, dependencies?: string[]) => string[];
19
+ export declare const getDependencies: (types: TypedData['types'], type: string, dependencies?: string[]) => string[];
14
20
  /**
15
21
  * Encode a type to a string. All dependant types are alphabetically sorted.
16
22
  *
@@ -18,7 +24,7 @@ export declare const getDependencies: (typedData: TypedData, type: string, depen
18
24
  * @param {string} type
19
25
  * @return {string}
20
26
  */
21
- export declare const encodeType: (typedData: TypedData, type: string) => string;
27
+ export declare const encodeType: (types: TypedData['types'], type: string) => string;
22
28
  /**
23
29
  * Get a type string as hash.
24
30
  *
@@ -26,7 +32,17 @@ export declare const encodeType: (typedData: TypedData, type: string) => string;
26
32
  * @param {string} type
27
33
  * @return {string}
28
34
  */
29
- export declare const getTypeHash: (typedData: TypedData, type: string) => string;
35
+ export declare const getTypeHash: (types: TypedData['types'], type: string) => string;
36
+ /**
37
+ * Encodes a single value to an ABI serialisable string, number or Buffer. Returns the data as tuple, which consists of
38
+ * an array of ABI compatible types, and an array of corresponding values.
39
+ *
40
+ * @param {TypedData} typedData
41
+ * @param {string} type
42
+ * @param {any} data
43
+ * @returns {[string, string]}
44
+ */
45
+ export declare const encodeValue: (types: TypedData['types'], type: string, data: unknown, ctx?: Context) => [string, string];
30
46
  /**
31
47
  * Encode the data to an ABI encoded Buffer. The data should be a key -> value object with all the required values. All
32
48
  * dependant types are automatically encoded.
@@ -35,7 +51,7 @@ export declare const getTypeHash: (typedData: TypedData, type: string) => string
35
51
  * @param {string} type
36
52
  * @param {Record<string, any>} data
37
53
  */
38
- export declare const encodeData: <T extends TypedData>(typedData: T, type: string, data: T["message"]) => string[][];
54
+ export declare const encodeData: <T extends TypedData>(types: T["types"], type: string, data: T["message"]) => string[][];
39
55
  /**
40
56
  * Get encoded data as a hash. The data should be a key -> value object with all the required values. All dependant
41
57
  * types are automatically encoded.
@@ -45,10 +61,9 @@ export declare const encodeData: <T extends TypedData>(typedData: T, type: strin
45
61
  * @param {Record<string, any>} data
46
62
  * @return {Buffer}
47
63
  */
48
- export declare const getStructHash: <T extends TypedData>(typedData: T, type: string, data: T["message"]) => string;
64
+ export declare const getStructHash: <T extends TypedData>(types: T["types"], type: string, data: T["message"]) => string;
49
65
  /**
50
- * Get the EIP-191 encoded message to sign, from the typedData object. If `hash` is enabled, the message will be hashed
51
- * with Keccak256.
66
+ * Get the EIP-191 encoded message to sign, from the typedData object.
52
67
  *
53
68
  * @param {TypedData} typedData
54
69
  * @param {BigNumberish} account