starknet 4.3.1 → 4.4.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/CHANGELOG.md +32 -0
- package/__mocks__/typedDataSessionExample.json +42 -0
- package/__tests__/rpcProvider.test.ts +29 -2
- package/__tests__/utils/__snapshots__/ellipticalCurve.test.ts.snap +2 -0
- package/__tests__/utils/ellipticalCurve.test.ts +5 -0
- package/__tests__/utils/merkle.test.ts +146 -0
- package/__tests__/utils/typedData.test.ts +107 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/provider/rpc.js +3 -3
- package/dist/signer/default.d.ts +1 -1
- package/dist/signer/default.js +1 -0
- package/dist/utils/hash.js +8 -6
- package/dist/utils/merkle.d.ts +10 -0
- package/dist/utils/merkle.js +90 -0
- package/dist/utils/number.d.ts +1 -0
- package/dist/utils/number.js +6 -2
- package/dist/utils/typedData/index.d.ts +23 -8
- package/dist/utils/typedData/index.js +70 -31
- package/dist/utils/typedData/types.d.ts +8 -3
- package/index.d.ts +1 -0
- package/index.js +2 -1
- package/package.json +1 -1
- package/provider/rpc.js +3 -3
- package/signer/default.d.ts +1 -1
- package/signer/default.js +1 -0
- package/src/index.ts +1 -0
- package/src/provider/rpc.ts +9 -4
- package/src/signer/default.ts +2 -2
- package/src/utils/hash.ts +8 -6
- package/src/utils/merkle.ts +70 -0
- package/src/utils/number.ts +5 -1
- package/src/utils/typedData/index.ts +88 -34
- package/src/utils/typedData/types.ts +12 -4
- package/utils/hash.js +8 -6
- package/utils/merkle.d.ts +10 -0
- package/utils/merkle.js +90 -0
- package/utils/number.d.ts +1 -0
- package/utils/number.js +6 -2
- package/utils/typedData/index.d.ts +23 -8
- package/utils/typedData/index.js +70 -31
- package/utils/typedData/types.d.ts +8 -3
- package/www/docs/API/utils.md +6 -0
- package/www/guides/account.md +8 -8
- package/www/guides/erc20.md +4 -5
- package/www/package-lock.json +4731 -6611
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
## [4.4.2](https://github.com/0xs34n/starknet.js/compare/v4.4.1...v4.4.2) (2022-09-07)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- dont import fetch from crosshatch ([a3ef41c](https://github.com/0xs34n/starknet.js/commit/a3ef41cac0e818f7429e6dd7654722ede1dc3796))
|
|
6
|
+
- use custom fetch ponyfill ([78f904a](https://github.com/0xs34n/starknet.js/commit/78f904a1d5aeb5efaba7fbdd853802529c80594b))
|
|
7
|
+
- use isomorphic-unfetch ([c63b6a1](https://github.com/0xs34n/starknet.js/commit/c63b6a138616936cf7a70f9098af5df290983c74))
|
|
8
|
+
|
|
9
|
+
## [4.4.1](https://github.com/0xs34n/starknet.js/compare/v4.4.0...v4.4.1) (2022-09-01)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- supply calldata as hexadecimal string array ([44cb4c5](https://github.com/0xs34n/starknet.js/commit/44cb4c5f108a2ea8fcd77147f053e068189d4f33))
|
|
14
|
+
|
|
15
|
+
# [4.4.0](https://github.com/0xs34n/starknet.js/compare/v4.3.1...v4.4.0) (2022-09-01)
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- delete premature session account file ([ca3e70b](https://github.com/0xs34n/starknet.js/commit/ca3e70b06d21dba8b2074512251cf232ed8be46b))
|
|
20
|
+
- session ([00269bf](https://github.com/0xs34n/starknet.js/commit/00269bfd23ed647270a1efd699af7c36978965c7))
|
|
21
|
+
- session account prooving ([0b56833](https://github.com/0xs34n/starknet.js/commit/0b56833f6eb7557d55725a505a01185bbc9756db))
|
|
22
|
+
- tests ([4586e93](https://github.com/0xs34n/starknet.js/commit/4586e93f10a2a43c375a23d851a9778bab412fcc))
|
|
23
|
+
- typo ([1c60a4d](https://github.com/0xs34n/starknet.js/commit/1c60a4d4b306879422769a6c2afc4fd6c39c4c07))
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
- add merkle trees ([e9b8674](https://github.com/0xs34n/starknet.js/commit/e9b8674f51c6d6fe57772a4c88b162c5132cfbdd))
|
|
28
|
+
- add visibility modifiers ([cd1a23d](https://github.com/0xs34n/starknet.js/commit/cd1a23d74b49407c27314a12d5bc149ed40209f3))
|
|
29
|
+
- allow merkle trees as native type in eip712 like messages ([65b7766](https://github.com/0xs34n/starknet.js/commit/65b7766c29eca4f4d0e89f6ad1368fedd5e0e18e))
|
|
30
|
+
- session ([9ac48cc](https://github.com/0xs34n/starknet.js/commit/9ac48cc15c1c7b0e504adfc79a7f382f5d0b55d0))
|
|
31
|
+
- session needs to be aware of the whole tree ([11e10bd](https://github.com/0xs34n/starknet.js/commit/11e10bda0f020a670854d941a54142d55936fc18))
|
|
32
|
+
|
|
1
33
|
## [4.3.1](https://github.com/0xs34n/starknet.js/compare/v4.3.0...v4.3.1) (2022-08-31)
|
|
2
34
|
|
|
3
35
|
### 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,11 +1,23 @@
|
|
|
1
|
-
import { RpcProvider } from '../src';
|
|
2
|
-
import {
|
|
1
|
+
import { Account, RpcProvider, ec } from '../src';
|
|
2
|
+
import {
|
|
3
|
+
compiledOpenZeppelinAccount,
|
|
4
|
+
describeIfRpc,
|
|
5
|
+
getTestAccount,
|
|
6
|
+
getTestProvider,
|
|
7
|
+
} from './fixtures';
|
|
3
8
|
|
|
4
9
|
describeIfRpc('RPCProvider', () => {
|
|
5
10
|
let rpcProvider: RpcProvider;
|
|
11
|
+
let accountPublicKey: string;
|
|
6
12
|
|
|
7
13
|
beforeAll(async () => {
|
|
8
14
|
rpcProvider = getTestProvider() as RpcProvider;
|
|
15
|
+
const account = getTestAccount(rpcProvider);
|
|
16
|
+
|
|
17
|
+
expect(account).toBeInstanceOf(Account);
|
|
18
|
+
|
|
19
|
+
const accountKeyPair = ec.genKeyPair();
|
|
20
|
+
accountPublicKey = ec.getStarkKey(accountKeyPair);
|
|
9
21
|
});
|
|
10
22
|
|
|
11
23
|
describe('RPC methods', () => {
|
|
@@ -13,5 +25,20 @@ describeIfRpc('RPCProvider', () => {
|
|
|
13
25
|
const chainId = await rpcProvider.getChainId();
|
|
14
26
|
expect(chainId).toBe('0x534e5f474f45524c49');
|
|
15
27
|
});
|
|
28
|
+
|
|
29
|
+
test('deployContract', async () => {
|
|
30
|
+
const { contract_address, transaction_hash } = await rpcProvider.deployContract({
|
|
31
|
+
contract: compiledOpenZeppelinAccount,
|
|
32
|
+
constructorCalldata: [accountPublicKey],
|
|
33
|
+
addressSalt: accountPublicKey,
|
|
34
|
+
});
|
|
35
|
+
await rpcProvider.waitForTransaction(transaction_hash);
|
|
36
|
+
expect(contract_address).toBeTruthy();
|
|
37
|
+
expect(transaction_hash).toBeTruthy();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test.todo('getEstimateFee');
|
|
41
|
+
|
|
42
|
+
test.todo('invokeFunction');
|
|
16
43
|
});
|
|
17
44
|
});
|
|
@@ -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 {
|
|
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(
|
|
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"));
|
package/dist/provider/rpc.js
CHANGED
|
@@ -217,7 +217,7 @@ var RpcProvider = /** @class */ (function () {
|
|
|
217
217
|
contract_address: invocation.contractAddress,
|
|
218
218
|
entry_point_selector: (0, hash_1.getSelectorFromName)(invocation.entrypoint),
|
|
219
219
|
calldata: (0, provider_1.parseCalldata)(invocation.calldata),
|
|
220
|
-
signature: (0, number_1.
|
|
220
|
+
signature: (0, number_1.bigNumberishArrayToHexadecimalStringArray)(invocation.signature || []),
|
|
221
221
|
version: (0, number_1.toHex)((0, number_1.toBN)((invocationDetails === null || invocationDetails === void 0 ? void 0 : invocationDetails.version) || 0)),
|
|
222
222
|
},
|
|
223
223
|
blockIdentifier,
|
|
@@ -249,7 +249,7 @@ var RpcProvider = /** @class */ (function () {
|
|
|
249
249
|
contractDefinition = (0, provider_1.parseContract)(contract);
|
|
250
250
|
return [2 /*return*/, this.fetchEndpoint('starknet_addDeployTransaction', [
|
|
251
251
|
addressSalt !== null && addressSalt !== void 0 ? addressSalt : (0, stark_1.randomAddress)(),
|
|
252
|
-
(0, number_1.
|
|
252
|
+
(0, number_1.bigNumberishArrayToHexadecimalStringArray)(constructorCalldata !== null && constructorCalldata !== void 0 ? constructorCalldata : []),
|
|
253
253
|
{
|
|
254
254
|
program: contractDefinition.program,
|
|
255
255
|
entry_points_by_type: contractDefinition.entry_points_by_type,
|
|
@@ -267,7 +267,7 @@ var RpcProvider = /** @class */ (function () {
|
|
|
267
267
|
entry_point_selector: (0, hash_1.getSelectorFromName)(functionInvocation.entrypoint),
|
|
268
268
|
calldata: (0, provider_1.parseCalldata)(functionInvocation.calldata),
|
|
269
269
|
},
|
|
270
|
-
(0, number_1.
|
|
270
|
+
(0, number_1.bigNumberishArrayToHexadecimalStringArray)(functionInvocation.signature || []),
|
|
271
271
|
(0, number_1.toHex)((0, number_1.toBN)(details.maxFee || 0)),
|
|
272
272
|
(0, number_1.toHex)((0, number_1.toBN)(details.version || 0)),
|
|
273
273
|
]).then(this.responseParser.parseInvokeFunctionResponse)];
|
package/dist/signer/default.d.ts
CHANGED
|
@@ -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
|
|
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>;
|
package/dist/signer/default.js
CHANGED
|
@@ -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 () {
|
package/dist/utils/hash.js
CHANGED
|
@@ -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
|
-
|
|
82
|
-
var
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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;
|
package/dist/utils/number.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export declare function hexToDecimalString(hex: string): string;
|
|
|
7
7
|
export declare function toFelt(num: BigNumberish): string;
|
|
8
8
|
export declare function assertInRange(input: BigNumberish, lowerBound: BigNumberish, upperBound: BigNumberish, inputName?: string): void;
|
|
9
9
|
export declare function bigNumberishArrayToDecimalStringArray(rawCalldata: BigNumberish[]): string[];
|
|
10
|
+
export declare function bigNumberishArrayToHexadecimalStringArray(rawCalldata: BigNumberish[]): string[];
|