starknet 2.4.0 → 2.7.1
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 +43 -0
- package/__tests__/account.test.ts +3 -3
- package/__tests__/provider.test.ts +28 -13
- package/__tests__/utils/ellipticalCurve.test.ts +1 -1
- package/__tests__/utils/typedData.test.ts +72 -0
- package/contract.d.ts +2 -2
- package/dist/contract.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/provider/default.d.ts +23 -19
- package/dist/provider/default.js +58 -41
- package/dist/provider/interface.d.ts +22 -18
- package/dist/provider/utils.d.ts +27 -0
- package/dist/provider/utils.js +37 -0
- package/dist/signer/default.d.ts +18 -1
- package/dist/signer/default.js +43 -7
- package/dist/signer/interface.d.ts +20 -1
- package/dist/types.d.ts +7 -6
- package/dist/utils/ellipticCurve.d.ts +8 -1
- package/dist/utils/ellipticCurve.js +48 -9
- package/dist/utils/stark.d.ts +2 -3
- package/dist/utils/typedData/index.d.ts +91 -0
- package/dist/utils/typedData/index.js +183 -0
- package/dist/utils/typedData/types.d.ts +82 -0
- package/dist/utils/typedData/types.js +47 -0
- package/dist/utils/typedData/utils.d.ts +24 -0
- package/dist/utils/typedData/utils.js +15 -0
- package/index.d.ts +1 -0
- package/index.js +3 -1
- package/package.json +2 -1
- package/provider/default.d.ts +34 -18
- package/provider/default.js +75 -45
- package/provider/interface.d.ts +33 -17
- package/provider/utils.d.ts +30 -0
- package/provider/utils.js +39 -0
- package/signer/default.d.ts +18 -1
- package/signer/default.js +44 -7
- package/signer/interface.d.ts +20 -1
- package/src/contract.ts +2 -2
- package/src/index.ts +1 -0
- package/src/provider/default.ts +55 -32
- package/src/provider/interface.ts +32 -17
- package/src/provider/utils.ts +38 -0
- package/src/signer/default.ts +26 -3
- package/src/signer/interface.ts +22 -1
- package/src/types.ts +13 -6
- package/src/utils/ellipticCurve.ts +31 -9
- package/src/utils/stark.ts +4 -4
- package/src/utils/typedData/index.ts +176 -0
- package/src/utils/typedData/types.ts +82 -0
- package/src/utils/typedData/utils.ts +13 -0
- package/types.d.ts +9 -7
- package/utils/ellipticCurve.d.ts +12 -1
- package/utils/ellipticCurve.js +72 -23
- package/utils/stark.d.ts +2 -3
- package/utils/typedData/index.d.ts +113 -0
- package/utils/typedData/index.js +247 -0
- package/utils/typedData/types.d.ts +103 -0
- package/utils/typedData/types.js +57 -0
- package/utils/typedData/utils.d.ts +27 -0
- package/utils/typedData/utils.js +15 -0
package/src/provider/default.ts
CHANGED
|
@@ -3,6 +3,7 @@ import urljoin from 'url-join';
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
AddTransactionResponse,
|
|
6
|
+
BlockNumber,
|
|
6
7
|
CallContractResponse,
|
|
7
8
|
CallContractTransaction,
|
|
8
9
|
CompiledContract,
|
|
@@ -11,14 +12,16 @@ import {
|
|
|
11
12
|
GetContractAddressesResponse,
|
|
12
13
|
GetTransactionResponse,
|
|
13
14
|
GetTransactionStatusResponse,
|
|
15
|
+
Signature,
|
|
14
16
|
Transaction,
|
|
15
17
|
} from '../types';
|
|
16
18
|
import { parse, stringify } from '../utils/json';
|
|
17
19
|
import { BigNumberish, toBN, toHex } from '../utils/number';
|
|
18
20
|
import { compressProgram, formatSignature, randomAddress } from '../utils/stark';
|
|
19
21
|
import { ProviderInterface } from './interface';
|
|
22
|
+
import { getFormattedBlockIdentifier } from './utils';
|
|
20
23
|
|
|
21
|
-
type NetworkName = 'mainnet-alpha' | '
|
|
24
|
+
type NetworkName = 'mainnet-alpha' | 'goerli-alpha';
|
|
22
25
|
|
|
23
26
|
type ProviderOptions =
|
|
24
27
|
| {
|
|
@@ -39,7 +42,7 @@ export class Provider implements ProviderInterface {
|
|
|
39
42
|
|
|
40
43
|
public gatewayUrl: string;
|
|
41
44
|
|
|
42
|
-
constructor(optionsOrProvider: ProviderOptions | Provider = { network: '
|
|
45
|
+
constructor(optionsOrProvider: ProviderOptions | Provider = { network: 'goerli-alpha' }) {
|
|
43
46
|
if (optionsOrProvider instanceof Provider) {
|
|
44
47
|
this.baseUrl = optionsOrProvider.baseUrl;
|
|
45
48
|
this.feederGatewayUrl = optionsOrProvider.feederGatewayUrl;
|
|
@@ -59,7 +62,7 @@ export class Provider implements ProviderInterface {
|
|
|
59
62
|
switch (name) {
|
|
60
63
|
case 'mainnet-alpha':
|
|
61
64
|
return 'https://alpha-mainnet.starknet.io';
|
|
62
|
-
case '
|
|
65
|
+
case 'goerli-alpha':
|
|
63
66
|
default:
|
|
64
67
|
return 'https://alpha4.starknet.io';
|
|
65
68
|
}
|
|
@@ -81,18 +84,22 @@ export class Provider implements ProviderInterface {
|
|
|
81
84
|
/**
|
|
82
85
|
* Calls a function on the StarkNet contract.
|
|
83
86
|
*
|
|
84
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
87
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L25-L39)
|
|
85
88
|
*
|
|
86
89
|
* @param invokeTransaction - transaction to be invoked
|
|
87
|
-
* @param
|
|
90
|
+
* @param blockHash
|
|
91
|
+
* @param blockNumber
|
|
88
92
|
* @returns the result of the function on the smart contract.
|
|
89
93
|
*/
|
|
90
94
|
public async callContract(
|
|
91
95
|
invokeTransaction: CallContractTransaction,
|
|
92
|
-
|
|
96
|
+
blockHash?: BigNumberish,
|
|
97
|
+
blockNumber: BlockNumber = null
|
|
93
98
|
): Promise<CallContractResponse> {
|
|
99
|
+
const formattedBlockIdentifier = getFormattedBlockIdentifier(blockHash, blockNumber);
|
|
100
|
+
|
|
94
101
|
const { data } = await axios.post<CallContractResponse>(
|
|
95
|
-
urljoin(this.feederGatewayUrl, 'call_contract',
|
|
102
|
+
urljoin(this.feederGatewayUrl, 'call_contract', formattedBlockIdentifier),
|
|
96
103
|
{
|
|
97
104
|
signature: [],
|
|
98
105
|
calldata: [],
|
|
@@ -103,16 +110,22 @@ export class Provider implements ProviderInterface {
|
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
/**
|
|
106
|
-
* Gets the block information
|
|
113
|
+
* Gets the block information
|
|
107
114
|
*
|
|
108
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
115
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L41-L53)
|
|
109
116
|
*
|
|
110
|
-
* @param
|
|
111
|
-
* @
|
|
117
|
+
* @param blockHash
|
|
118
|
+
* @param blockNumber
|
|
119
|
+
* @returns the block object { block_number, previous_block_number, state_root, status, timestamp, transaction_receipts, transactions }
|
|
112
120
|
*/
|
|
113
|
-
public async getBlock(
|
|
121
|
+
public async getBlock(
|
|
122
|
+
blockHash?: BigNumberish,
|
|
123
|
+
blockNumber: BlockNumber = null
|
|
124
|
+
): Promise<GetBlockResponse> {
|
|
125
|
+
const formattedBlockIdentifier = getFormattedBlockIdentifier(blockHash, blockNumber);
|
|
126
|
+
|
|
114
127
|
const { data } = await axios.get<GetBlockResponse>(
|
|
115
|
-
urljoin(this.feederGatewayUrl, 'get_block',
|
|
128
|
+
urljoin(this.feederGatewayUrl, 'get_block', formattedBlockIdentifier)
|
|
116
129
|
);
|
|
117
130
|
return data;
|
|
118
131
|
}
|
|
@@ -120,18 +133,25 @@ export class Provider implements ProviderInterface {
|
|
|
120
133
|
/**
|
|
121
134
|
* Gets the code of the deployed contract.
|
|
122
135
|
*
|
|
123
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
136
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L55-L68)
|
|
124
137
|
*
|
|
125
138
|
* @param contractAddress
|
|
126
|
-
* @param
|
|
139
|
+
* @param blockHash
|
|
140
|
+
* @param blockNumber
|
|
127
141
|
* @returns Bytecode and ABI of compiled contract
|
|
128
142
|
*/
|
|
129
|
-
public async getCode(
|
|
143
|
+
public async getCode(
|
|
144
|
+
contractAddress: string,
|
|
145
|
+
blockHash?: BigNumberish,
|
|
146
|
+
blockNumber: BlockNumber = null
|
|
147
|
+
): Promise<GetCodeResponse> {
|
|
148
|
+
const formattedBlockIdentifier = getFormattedBlockIdentifier(blockHash, blockNumber);
|
|
149
|
+
|
|
130
150
|
const { data } = await axios.get<GetCodeResponse>(
|
|
131
151
|
urljoin(
|
|
132
152
|
this.feederGatewayUrl,
|
|
133
153
|
'get_code',
|
|
134
|
-
`?contractAddress=${contractAddress}
|
|
154
|
+
`?contractAddress=${contractAddress}&${formattedBlockIdentifier}`
|
|
135
155
|
)
|
|
136
156
|
);
|
|
137
157
|
return data;
|
|
@@ -141,23 +161,27 @@ export class Provider implements ProviderInterface {
|
|
|
141
161
|
/**
|
|
142
162
|
* Gets the contract's storage variable at a specific key.
|
|
143
163
|
*
|
|
144
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
164
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L70-L85)
|
|
145
165
|
*
|
|
146
166
|
* @param contractAddress
|
|
147
167
|
* @param key - from getStorageVarAddress('<STORAGE_VARIABLE_NAME>') (WIP)
|
|
148
|
-
* @param
|
|
168
|
+
* @param blockHash
|
|
169
|
+
* @param blockNumber
|
|
149
170
|
* @returns the value of the storage variable
|
|
150
171
|
*/
|
|
151
172
|
public async getStorageAt(
|
|
152
173
|
contractAddress: string,
|
|
153
174
|
key: number,
|
|
154
|
-
|
|
175
|
+
blockHash?: BigNumberish,
|
|
176
|
+
blockNumber: BlockNumber = null
|
|
155
177
|
): Promise<object> {
|
|
178
|
+
const formattedBlockIdentifier = getFormattedBlockIdentifier(blockHash, blockNumber);
|
|
179
|
+
|
|
156
180
|
const { data } = await axios.get<object>(
|
|
157
181
|
urljoin(
|
|
158
182
|
this.feederGatewayUrl,
|
|
159
183
|
'get_storage_at',
|
|
160
|
-
`?contractAddress=${contractAddress}&key=${key}
|
|
184
|
+
`?contractAddress=${contractAddress}&key=${key}&${formattedBlockIdentifier}`
|
|
161
185
|
)
|
|
162
186
|
);
|
|
163
187
|
return data;
|
|
@@ -169,7 +193,7 @@ export class Provider implements ProviderInterface {
|
|
|
169
193
|
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L48-L52)
|
|
170
194
|
*
|
|
171
195
|
* @param txHash
|
|
172
|
-
* @returns the transaction status object {
|
|
196
|
+
* @returns the transaction status object { block_number, tx_status: NOT_RECEIVED | RECEIVED | PENDING | REJECTED | ACCEPTED_ONCHAIN }
|
|
173
197
|
*/
|
|
174
198
|
public async getTransactionStatus(txHash: BigNumberish): Promise<GetTransactionStatusResponse> {
|
|
175
199
|
const txHashBn = toBN(txHash);
|
|
@@ -189,7 +213,7 @@ export class Provider implements ProviderInterface {
|
|
|
189
213
|
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L54-L58)
|
|
190
214
|
*
|
|
191
215
|
* @param txHash
|
|
192
|
-
* @returns the transacton object { transaction_id, status, transaction,
|
|
216
|
+
* @returns the transacton object { transaction_id, status, transaction, block_number?, block_number?, transaction_index?, transaction_failure_reason? }
|
|
193
217
|
*/
|
|
194
218
|
public async getTransaction(txHash: BigNumberish): Promise<GetTransactionResponse> {
|
|
195
219
|
const txHashBn = toBN(txHash);
|
|
@@ -265,7 +289,7 @@ export class Provider implements ProviderInterface {
|
|
|
265
289
|
contractAddress: string,
|
|
266
290
|
entrypointSelector: string,
|
|
267
291
|
calldata?: string[],
|
|
268
|
-
signature?:
|
|
292
|
+
signature?: Signature
|
|
269
293
|
): Promise<AddTransactionResponse> {
|
|
270
294
|
return this.addTransaction({
|
|
271
295
|
type: 'INVOKE_FUNCTION',
|
|
@@ -278,21 +302,20 @@ export class Provider implements ProviderInterface {
|
|
|
278
302
|
|
|
279
303
|
public async waitForTx(txHash: BigNumberish, retryInterval: number = 8000) {
|
|
280
304
|
let onchain = false;
|
|
305
|
+
await wait(retryInterval);
|
|
306
|
+
|
|
281
307
|
while (!onchain) {
|
|
282
308
|
// eslint-disable-next-line no-await-in-loop
|
|
283
309
|
await wait(retryInterval);
|
|
284
310
|
// eslint-disable-next-line no-await-in-loop
|
|
285
311
|
const res = await this.getTransactionStatus(txHash);
|
|
286
312
|
|
|
287
|
-
if (
|
|
288
|
-
res.tx_status === 'ACCEPTED_ONCHAIN' ||
|
|
289
|
-
(res.tx_status === 'PENDING' && res.block_hash !== 'pending') // This is needed as of today. In the future there will be a different status for pending transactions.
|
|
290
|
-
) {
|
|
313
|
+
if (res.tx_status === 'ACCEPTED_ON_L1' || res.tx_status === 'ACCEPTED_ON_L2') {
|
|
291
314
|
onchain = true;
|
|
292
|
-
} else if (res.tx_status === 'REJECTED') {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
throw
|
|
315
|
+
} else if (res.tx_status === 'REJECTED' || res.tx_status === 'NOT_RECEIVED') {
|
|
316
|
+
const error = Error(res.tx_status) as Error & { response: GetTransactionStatusResponse };
|
|
317
|
+
error.response = res;
|
|
318
|
+
throw error;
|
|
296
319
|
}
|
|
297
320
|
}
|
|
298
321
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AddTransactionResponse,
|
|
3
|
+
BlockNumber,
|
|
3
4
|
CallContractResponse,
|
|
4
5
|
CallContractTransaction,
|
|
5
6
|
CompiledContract,
|
|
@@ -8,6 +9,7 @@ import type {
|
|
|
8
9
|
GetContractAddressesResponse,
|
|
9
10
|
GetTransactionResponse,
|
|
10
11
|
GetTransactionStatusResponse,
|
|
12
|
+
Signature,
|
|
11
13
|
Transaction,
|
|
12
14
|
} from '../types';
|
|
13
15
|
import type { BigNumberish } from '../utils/number';
|
|
@@ -30,53 +32,66 @@ export abstract class ProviderInterface {
|
|
|
30
32
|
/**
|
|
31
33
|
* Calls a function on the StarkNet contract.
|
|
32
34
|
*
|
|
33
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
35
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L25-L39)
|
|
34
36
|
*
|
|
35
37
|
* @param invokeTransaction - transaction to be invoked
|
|
36
|
-
* @param
|
|
38
|
+
* @param blockHash
|
|
39
|
+
* @param blockNumber
|
|
37
40
|
* @returns the result of the function on the smart contract.
|
|
38
41
|
*/
|
|
39
42
|
public abstract callContract(
|
|
40
43
|
invokeTransaction: CallContractTransaction,
|
|
41
|
-
|
|
44
|
+
blockHash?: BigNumberish,
|
|
45
|
+
blockNumber?: BlockNumber
|
|
42
46
|
): Promise<CallContractResponse>;
|
|
43
47
|
|
|
44
48
|
/**
|
|
45
|
-
* Gets the block information
|
|
49
|
+
* Gets the block information
|
|
46
50
|
*
|
|
47
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
51
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L41-L53)
|
|
48
52
|
*
|
|
49
|
-
* @param
|
|
50
|
-
* @
|
|
53
|
+
* @param blockHash
|
|
54
|
+
* @param blockNumber
|
|
55
|
+
* @returns the block object { block_number, previous_block_number, state_root, status, timestamp, transaction_receipts, transactions }
|
|
51
56
|
*/
|
|
52
|
-
public abstract getBlock(
|
|
57
|
+
public abstract getBlock(
|
|
58
|
+
blockHash?: BigNumberish,
|
|
59
|
+
blockNumber?: BlockNumber
|
|
60
|
+
): Promise<GetBlockResponse>;
|
|
53
61
|
|
|
54
62
|
/**
|
|
55
63
|
* Gets the code of the deployed contract.
|
|
56
64
|
*
|
|
57
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
65
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L55-L68)
|
|
58
66
|
*
|
|
59
67
|
* @param contractAddress
|
|
60
|
-
* @param
|
|
68
|
+
* @param blockHash
|
|
69
|
+
* @param blockNumber
|
|
61
70
|
* @returns Bytecode and ABI of compiled contract
|
|
62
71
|
*/
|
|
63
|
-
public abstract getCode(
|
|
72
|
+
public abstract getCode(
|
|
73
|
+
contractAddress: string,
|
|
74
|
+
blockHash?: BigNumberish,
|
|
75
|
+
blockNumber?: BlockNumber
|
|
76
|
+
): Promise<GetCodeResponse>;
|
|
64
77
|
|
|
65
78
|
// TODO: add proper type
|
|
66
79
|
/**
|
|
67
80
|
* Gets the contract's storage variable at a specific key.
|
|
68
81
|
*
|
|
69
|
-
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/
|
|
82
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L70-L85)
|
|
70
83
|
*
|
|
71
84
|
* @param contractAddress
|
|
72
85
|
* @param key - from getStorageVarAddress('<STORAGE_VARIABLE_NAME>') (WIP)
|
|
73
|
-
* @param
|
|
86
|
+
* @param blockHash
|
|
87
|
+
* @param blockNumber
|
|
74
88
|
* @returns the value of the storage variable
|
|
75
89
|
*/
|
|
76
90
|
public abstract getStorageAt(
|
|
77
91
|
contractAddress: string,
|
|
78
92
|
key: number,
|
|
79
|
-
|
|
93
|
+
blockHash?: BigNumberish,
|
|
94
|
+
blockNumber?: BlockNumber
|
|
80
95
|
): Promise<object>;
|
|
81
96
|
|
|
82
97
|
/**
|
|
@@ -85,7 +100,7 @@ export abstract class ProviderInterface {
|
|
|
85
100
|
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L48-L52)
|
|
86
101
|
*
|
|
87
102
|
* @param txHash
|
|
88
|
-
* @returns the transaction status object {
|
|
103
|
+
* @returns the transaction status object { block_number, tx_status: NOT_RECEIVED | RECEIVED | PENDING | REJECTED | ACCEPTED_ONCHAIN }
|
|
89
104
|
*/
|
|
90
105
|
public abstract getTransactionStatus(txHash: BigNumberish): Promise<GetTransactionStatusResponse>;
|
|
91
106
|
|
|
@@ -95,7 +110,7 @@ export abstract class ProviderInterface {
|
|
|
95
110
|
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L54-L58)
|
|
96
111
|
*
|
|
97
112
|
* @param txHash
|
|
98
|
-
* @returns the transacton object { transaction_id, status, transaction,
|
|
113
|
+
* @returns the transacton object { transaction_id, status, transaction, block_number?, block_number?, transaction_index?, transaction_failure_reason? }
|
|
99
114
|
*/
|
|
100
115
|
public abstract getTransaction(txHash: BigNumberish): Promise<GetTransactionResponse>;
|
|
101
116
|
|
|
@@ -135,7 +150,7 @@ export abstract class ProviderInterface {
|
|
|
135
150
|
contractAddress: string,
|
|
136
151
|
entrypointSelector: string,
|
|
137
152
|
calldata?: string[],
|
|
138
|
-
signature?:
|
|
153
|
+
signature?: Signature
|
|
139
154
|
): Promise<AddTransactionResponse>;
|
|
140
155
|
|
|
141
156
|
public abstract waitForTx(txHash: BigNumberish, retryInterval?: number): Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { BlockNumber } from '../types';
|
|
2
|
+
import { BigNumberish } from '../utils/number';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* TODO
|
|
6
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L148-L153)
|
|
7
|
+
*
|
|
8
|
+
* @param hashValue
|
|
9
|
+
* @param hashField
|
|
10
|
+
*/
|
|
11
|
+
export function formatHash() {}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* TODO
|
|
15
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L156-L161)
|
|
16
|
+
* @param txHash
|
|
17
|
+
* @param txId
|
|
18
|
+
*/
|
|
19
|
+
export function txIdentifier() {}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Gets the block identifier for API request
|
|
23
|
+
*
|
|
24
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L164-L173)
|
|
25
|
+
*
|
|
26
|
+
* @param blockNumber
|
|
27
|
+
* @param blockHash
|
|
28
|
+
* @returns block identifier for API request
|
|
29
|
+
*/
|
|
30
|
+
export function getFormattedBlockIdentifier(
|
|
31
|
+
blockHash?: BigNumberish,
|
|
32
|
+
blockNumber: BlockNumber = null
|
|
33
|
+
): string {
|
|
34
|
+
if (blockHash) {
|
|
35
|
+
return `?blockHash=${blockHash}`;
|
|
36
|
+
}
|
|
37
|
+
return `?blockNumber=${blockNumber}`;
|
|
38
|
+
}
|
package/src/signer/default.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import assert from 'minimalistic-assert';
|
|
2
2
|
|
|
3
3
|
import { Provider } from '../provider';
|
|
4
|
-
import { AddTransactionResponse, KeyPair, Transaction } from '../types';
|
|
4
|
+
import { AddTransactionResponse, KeyPair, Signature, Transaction } from '../types';
|
|
5
5
|
import { sign } from '../utils/ellipticCurve';
|
|
6
6
|
import { addHexPrefix } from '../utils/encode';
|
|
7
7
|
import { hashMessage } from '../utils/hash';
|
|
8
8
|
import { toBN } from '../utils/number';
|
|
9
9
|
import { getSelectorFromName } from '../utils/stark';
|
|
10
|
+
import { TypedData, getMessageHash } from '../utils/typedData';
|
|
10
11
|
import { SignerInterface } from './interface';
|
|
11
12
|
|
|
12
13
|
export class Signer extends Provider implements SignerInterface {
|
|
@@ -59,7 +60,7 @@ export class Signer extends Provider implements SignerInterface {
|
|
|
59
60
|
)
|
|
60
61
|
);
|
|
61
62
|
|
|
62
|
-
const
|
|
63
|
+
const signature = sign(this.keyPair, msgHash);
|
|
63
64
|
|
|
64
65
|
return super.addTransaction({
|
|
65
66
|
type: 'INVOKE_FUNCTION',
|
|
@@ -72,7 +73,29 @@ export class Signer extends Provider implements SignerInterface {
|
|
|
72
73
|
nonceBn.toString(),
|
|
73
74
|
].map((x) => toBN(x).toString()),
|
|
74
75
|
contract_address: this.address,
|
|
75
|
-
signature
|
|
76
|
+
signature,
|
|
76
77
|
});
|
|
77
78
|
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Sign an JSON object with the starknet private key and return the signature
|
|
82
|
+
*
|
|
83
|
+
* @param json - JSON object to be signed
|
|
84
|
+
* @returns the signature of the JSON object
|
|
85
|
+
* @throws {Error} if the JSON object is not a valid JSON
|
|
86
|
+
*/
|
|
87
|
+
public async signMessage(typedData: TypedData): Promise<Signature> {
|
|
88
|
+
return sign(this.keyPair, await this.hashMessage(typedData));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Hash a JSON object with pederson hash and return the hash
|
|
93
|
+
*
|
|
94
|
+
* @param json - JSON object to be hashed
|
|
95
|
+
* @returns the hash of the JSON object
|
|
96
|
+
* @throws {Error} if the JSON object is not a valid JSON
|
|
97
|
+
*/
|
|
98
|
+
public async hashMessage(typedData: TypedData): Promise<string> {
|
|
99
|
+
return getMessageHash(typedData, this.address);
|
|
100
|
+
}
|
|
78
101
|
}
|
package/src/signer/interface.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Provider } from '../provider';
|
|
2
|
-
import { AddTransactionResponse, Transaction } from '../types';
|
|
2
|
+
import { AddTransactionResponse, Signature, Transaction } from '../types';
|
|
3
|
+
import { TypedData } from '../utils/typedData/types';
|
|
3
4
|
|
|
4
5
|
export abstract class SignerInterface extends Provider {
|
|
5
6
|
public abstract address: string;
|
|
@@ -14,4 +15,24 @@ export abstract class SignerInterface extends Provider {
|
|
|
14
15
|
public abstract override addTransaction(
|
|
15
16
|
transaction: Transaction
|
|
16
17
|
): Promise<AddTransactionResponse>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Sign an JSON object for off-chain usage with the starknet private key and return the signature
|
|
21
|
+
* This adds a message prefix so it cant be interchanged with transactions
|
|
22
|
+
*
|
|
23
|
+
* @param json - JSON object to be signed
|
|
24
|
+
* @returns the signature of the JSON object
|
|
25
|
+
* @throws {Error} if the JSON object is not a valid JSON
|
|
26
|
+
*/
|
|
27
|
+
public abstract signMessage(typedData: TypedData): Promise<Signature>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Hash a JSON object with pederson hash and return the hash
|
|
31
|
+
* This adds a message prefix so it cant be interchanged with transactions
|
|
32
|
+
*
|
|
33
|
+
* @param json - JSON object to be hashed
|
|
34
|
+
* @returns the hash of the JSON object
|
|
35
|
+
* @throws {Error} if the JSON object is not a valid JSON
|
|
36
|
+
*/
|
|
37
|
+
public abstract hashMessage(typedData: TypedData): Promise<string>;
|
|
17
38
|
}
|
package/src/types.ts
CHANGED
|
@@ -3,14 +3,20 @@ import type { ec as EC } from 'elliptic';
|
|
|
3
3
|
import type { BigNumberish } from './utils/number';
|
|
4
4
|
|
|
5
5
|
export type KeyPair = EC.KeyPair;
|
|
6
|
-
export type Signature =
|
|
6
|
+
export type Signature = BigNumberish[];
|
|
7
7
|
|
|
8
8
|
export type GetContractAddressesResponse = {
|
|
9
9
|
Starknet: string;
|
|
10
10
|
GpsStatementVerifier: string;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
export type Status =
|
|
13
|
+
export type Status =
|
|
14
|
+
| 'NOT_RECEIVED'
|
|
15
|
+
| 'RECEIVED'
|
|
16
|
+
| 'PENDING'
|
|
17
|
+
| 'ACCEPTED_ON_L2'
|
|
18
|
+
| 'ACCEPTED_ON_L1'
|
|
19
|
+
| 'REJECTED';
|
|
14
20
|
export type TransactionStatus = 'TRANSACTION_RECEIVED';
|
|
15
21
|
export type Type = 'DEPLOY' | 'INVOKE_FUNCTION';
|
|
16
22
|
export type EntryPointType = 'EXTERNAL';
|
|
@@ -37,6 +43,7 @@ export type Abi = FunctionAbi | StructAbi;
|
|
|
37
43
|
|
|
38
44
|
export type EntryPointsByType = object;
|
|
39
45
|
export type Program = object;
|
|
46
|
+
export type BlockNumber = 'pending' | null | number;
|
|
40
47
|
|
|
41
48
|
export type CompiledContract = {
|
|
42
49
|
abi: Abi[];
|
|
@@ -57,7 +64,7 @@ export type DeployTransaction = {
|
|
|
57
64
|
export type InvokeFunctionTransaction = {
|
|
58
65
|
type: 'INVOKE_FUNCTION';
|
|
59
66
|
contract_address: string;
|
|
60
|
-
signature?:
|
|
67
|
+
signature?: Signature;
|
|
61
68
|
entry_point_type?: EntryPointType;
|
|
62
69
|
entry_point_selector: string;
|
|
63
70
|
calldata?: string[];
|
|
@@ -73,7 +80,7 @@ export type CallContractResponse = {
|
|
|
73
80
|
};
|
|
74
81
|
|
|
75
82
|
export type GetBlockResponse = {
|
|
76
|
-
|
|
83
|
+
block_number: number;
|
|
77
84
|
state_root: string;
|
|
78
85
|
block_hash: string;
|
|
79
86
|
transactions: {
|
|
@@ -89,7 +96,7 @@ export type GetBlockResponse = {
|
|
|
89
96
|
payload: string[];
|
|
90
97
|
from_address: string;
|
|
91
98
|
}[];
|
|
92
|
-
block_number:
|
|
99
|
+
block_number: BlockNumber;
|
|
93
100
|
status: Status;
|
|
94
101
|
transaction_index: number;
|
|
95
102
|
};
|
|
@@ -112,7 +119,7 @@ export type GetTransactionResponse = {
|
|
|
112
119
|
status: Status;
|
|
113
120
|
transaction: Transaction;
|
|
114
121
|
block_hash: string;
|
|
115
|
-
block_number:
|
|
122
|
+
block_number: BlockNumber;
|
|
116
123
|
transaction_index: number;
|
|
117
124
|
transaction_hash: string;
|
|
118
125
|
};
|
|
@@ -53,6 +53,17 @@ export function getStarkKey(keyPair: KeyPair): string {
|
|
|
53
53
|
return addHexPrefix(sanitizeBytes((keyPair as any).pub.getX().toString(16), 2));
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Takes a public key and casts it into `elliptic` KeyPair format.
|
|
58
|
+
*
|
|
59
|
+
* @param publicKey - public key which should get casted to a KeyPair
|
|
60
|
+
* @returns keyPair with public key only, which can be used to verify signatures, but cant sign anything
|
|
61
|
+
*/
|
|
62
|
+
export function getKeyPairFromPublicKey(publicKey: BigNumberish): KeyPair {
|
|
63
|
+
const publicKeyBn = toBN(publicKey);
|
|
64
|
+
return ec.keyFromPublic(removeHexPrefix(toHex(publicKeyBn)), 'hex');
|
|
65
|
+
}
|
|
66
|
+
|
|
56
67
|
/*
|
|
57
68
|
Signs a message using the provided key.
|
|
58
69
|
key should be an KeyPair with a valid private key.
|
|
@@ -69,7 +80,13 @@ export function sign(keyPair: KeyPair, msgHash: string): Signature {
|
|
|
69
80
|
assertInRange(r, ONE, toBN(addHexPrefix(MAX_ECDSA_VAL)), 'r');
|
|
70
81
|
assertInRange(s, ONE, toBN(addHexPrefix(EC_ORDER)), 's');
|
|
71
82
|
assertInRange(w, ONE, toBN(addHexPrefix(MAX_ECDSA_VAL)), 'w');
|
|
72
|
-
return
|
|
83
|
+
return [r, s];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function chunkArray(arr: any[], n: number): any[][] {
|
|
87
|
+
return Array(Math.ceil(arr.length / n))
|
|
88
|
+
.fill('')
|
|
89
|
+
.map((_, i) => arr.slice(i * n, i * n + n));
|
|
73
90
|
}
|
|
74
91
|
|
|
75
92
|
/*
|
|
@@ -78,15 +95,20 @@ export function sign(keyPair: KeyPair, msgHash: string): Signature {
|
|
|
78
95
|
msgSignature should be an Signature.
|
|
79
96
|
Returns a boolean true if the verification succeeds.
|
|
80
97
|
*/
|
|
81
|
-
export function verify(keyPair: KeyPair, msgHash: string, sig: Signature): boolean {
|
|
98
|
+
export function verify(keyPair: KeyPair | KeyPair[], msgHash: string, sig: Signature): boolean {
|
|
99
|
+
const keyPairArray = Array.isArray(keyPair) ? keyPair : [keyPair];
|
|
82
100
|
const msgHashBN = toBN(addHexPrefix(msgHash));
|
|
101
|
+
assert(sig.length % 2 === 0, 'Signature must be an array of length dividable by 2');
|
|
83
102
|
assertInRange(msgHashBN, ZERO, toBN(addHexPrefix(MAX_ECDSA_VAL)), 'msgHash');
|
|
84
|
-
|
|
85
|
-
const w = s.invm(ec.n!);
|
|
86
|
-
// Verify signature has valid length.
|
|
87
|
-
assertInRange(r, ONE, toBN(addHexPrefix(MAX_ECDSA_VAL)), 'r');
|
|
88
|
-
assertInRange(s, ONE, toBN(addHexPrefix(EC_ORDER)), 's');
|
|
89
|
-
assertInRange(w, ONE, toBN(addHexPrefix(MAX_ECDSA_VAL)), 'w');
|
|
103
|
+
assert(keyPairArray.length === sig.length / 2, 'Signature and keyPair length must be equal');
|
|
90
104
|
|
|
91
|
-
return
|
|
105
|
+
return chunkArray(sig, 2).every(([r, s], i) => {
|
|
106
|
+
const rBN = toBN(r);
|
|
107
|
+
const sBN = toBN(s);
|
|
108
|
+
const w = sBN.invm((ec as any).n);
|
|
109
|
+
assertInRange(rBN, ONE, toBN(addHexPrefix(MAX_ECDSA_VAL)), 'r');
|
|
110
|
+
assertInRange(sBN, ONE, toBN(addHexPrefix(EC_ORDER)), 's');
|
|
111
|
+
assertInRange(w, ONE, toBN(addHexPrefix(MAX_ECDSA_VAL)), 'w');
|
|
112
|
+
return ec.verify(fixMessage(msgHash), { r: rBN, s: sBN }, keyPairArray[i]) ?? false;
|
|
113
|
+
});
|
|
92
114
|
}
|
package/src/utils/stark.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { gzip } from 'pako';
|
|
2
2
|
|
|
3
|
-
import { CompressedProgram, Program } from '../types';
|
|
3
|
+
import { CompressedProgram, Program, Signature } from '../types';
|
|
4
4
|
import { genKeyPair, getStarkKey } from './ellipticCurve';
|
|
5
5
|
import { addHexPrefix, btoaUniversal } from './encode';
|
|
6
6
|
import { starknetKeccak } from './hash';
|
|
7
7
|
import { stringify } from './json';
|
|
8
|
-
import {
|
|
8
|
+
import { toBN, toHex } from './number';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Function to compress compiled cairo program
|
|
@@ -41,10 +41,10 @@ export function makeAddress(input: string): string {
|
|
|
41
41
|
return addHexPrefix(input).toLowerCase();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export function formatSignature(sig?:
|
|
44
|
+
export function formatSignature(sig?: Signature): string[] {
|
|
45
45
|
if (!sig) return [];
|
|
46
46
|
try {
|
|
47
|
-
return sig.map((x) => toBN(x)).map((x) => x.toString())
|
|
47
|
+
return sig.map((x) => toBN(x)).map((x) => x.toString());
|
|
48
48
|
} catch (e) {
|
|
49
49
|
return [];
|
|
50
50
|
}
|