starknet 2.3.0 → 2.6.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/__tests__/account.test.ts +3 -3
  3. package/__tests__/provider.test.ts +3 -3
  4. package/__tests__/signer.test.ts +17 -0
  5. package/__tests__/utils/ellipticalCurve.test.ts +1 -1
  6. package/__tests__/utils/typedData.test.ts +72 -0
  7. package/contract.d.ts +9 -3
  8. package/contract.js +23 -5
  9. package/dist/contract.d.ts +6 -3
  10. package/dist/contract.js +19 -5
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.js +2 -1
  13. package/dist/provider/default.d.ts +17 -17
  14. package/dist/provider/default.js +37 -32
  15. package/dist/provider/interface.d.ts +16 -16
  16. package/dist/signer/default.d.ts +20 -3
  17. package/dist/signer/default.js +61 -20
  18. package/dist/signer/interface.d.ts +22 -3
  19. package/dist/types.d.ts +10 -7
  20. package/dist/utils/ellipticCurve.d.ts +8 -1
  21. package/dist/utils/ellipticCurve.js +48 -9
  22. package/dist/utils/stark.d.ts +2 -6
  23. package/dist/utils/stark.js +1 -5
  24. package/dist/utils/typedData/index.d.ts +91 -0
  25. package/dist/utils/typedData/index.js +183 -0
  26. package/dist/utils/typedData/types.d.ts +82 -0
  27. package/dist/utils/typedData/types.js +47 -0
  28. package/dist/utils/typedData/utils.d.ts +24 -0
  29. package/dist/utils/typedData/utils.js +15 -0
  30. package/index.d.ts +1 -0
  31. package/index.js +3 -1
  32. package/package.json +3 -1
  33. package/provider/default.d.ts +21 -16
  34. package/provider/default.js +50 -39
  35. package/provider/interface.d.ts +22 -16
  36. package/signer/default.d.ts +20 -3
  37. package/signer/default.js +60 -17
  38. package/signer/interface.d.ts +22 -3
  39. package/src/contract.ts +17 -14
  40. package/src/index.ts +1 -0
  41. package/src/provider/default.ts +37 -31
  42. package/src/provider/interface.ts +21 -16
  43. package/src/signer/default.ts +49 -17
  44. package/src/signer/interface.ts +26 -3
  45. package/src/types.ts +16 -7
  46. package/src/utils/ellipticCurve.ts +31 -9
  47. package/src/utils/stark.ts +4 -8
  48. package/src/utils/typedData/index.ts +176 -0
  49. package/src/utils/typedData/types.ts +82 -0
  50. package/src/utils/typedData/utils.ts +13 -0
  51. package/types.d.ts +12 -8
  52. package/utils/ellipticCurve.d.ts +12 -1
  53. package/utils/ellipticCurve.js +72 -23
  54. package/utils/stark.d.ts +2 -8
  55. package/utils/stark.js +1 -6
  56. package/utils/typedData/index.d.ts +113 -0
  57. package/utils/typedData/index.js +247 -0
  58. package/utils/typedData/types.d.ts +103 -0
  59. package/utils/typedData/types.js +57 -0
  60. package/utils/typedData/utils.d.ts +27 -0
  61. package/utils/typedData/utils.js +15 -0
@@ -61,7 +61,7 @@ function wait(delay) {
61
61
  }
62
62
  var Provider = /** @class */ (function () {
63
63
  function Provider(optionsOrProvider) {
64
- if (optionsOrProvider === void 0) { optionsOrProvider = { network: 'georli-alpha' }; }
64
+ if (optionsOrProvider === void 0) { optionsOrProvider = { network: 'goerli-alpha' }; }
65
65
  if (optionsOrProvider instanceof Provider) {
66
66
  this.baseUrl = optionsOrProvider.baseUrl;
67
67
  this.feederGatewayUrl = optionsOrProvider.feederGatewayUrl;
@@ -80,7 +80,7 @@ var Provider = /** @class */ (function () {
80
80
  switch (name) {
81
81
  case 'mainnet-alpha':
82
82
  return 'https://alpha-mainnet.starknet.io';
83
- case 'georli-alpha':
83
+ case 'goerli-alpha':
84
84
  default:
85
85
  return 'https://alpha4.starknet.io';
86
86
  }
@@ -109,16 +109,17 @@ var Provider = /** @class */ (function () {
109
109
  *
110
110
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L17-L25)
111
111
  *
112
- * @param invokeTx - transaction to be invoked
113
- * @param blockId
112
+ * @param invokeTransaction - transaction to be invoked
113
+ * @param blockNumber
114
114
  * @returns the result of the function on the smart contract.
115
115
  */
116
- Provider.prototype.callContract = function (invokeTx, blockId) {
116
+ Provider.prototype.callContract = function (invokeTransaction, blockNumber) {
117
+ if (blockNumber === void 0) { blockNumber = null; }
117
118
  return __awaiter(this, void 0, void 0, function () {
118
119
  var data;
119
120
  return __generator(this, function (_a) {
120
121
  switch (_a.label) {
121
- case 0: return [4 /*yield*/, axios_1.default.post((0, url_join_1.default)(this.feederGatewayUrl, 'call_contract', "?blockId=" + (blockId !== null && blockId !== void 0 ? blockId : 'null')), __assign({ signature: [], calldata: [] }, invokeTx))];
122
+ case 0: return [4 /*yield*/, axios_1.default.post((0, url_join_1.default)(this.feederGatewayUrl, 'call_contract', "?blockNumber=" + blockNumber), __assign({ signature: [], calldata: [] }, invokeTransaction))];
122
123
  case 1:
123
124
  data = (_a.sent()).data;
124
125
  return [2 /*return*/, data];
@@ -131,15 +132,16 @@ var Provider = /** @class */ (function () {
131
132
  *
132
133
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L27-L31)
133
134
  *
134
- * @param blockId
135
- * @returns the block object { block_id, previous_block_id, state_root, status, timestamp, transaction_receipts, transactions }
135
+ * @param blockNumber
136
+ * @returns the block object { block_number, previous_block_number, state_root, status, timestamp, transaction_receipts, transactions }
136
137
  */
137
- Provider.prototype.getBlock = function (blockId) {
138
+ Provider.prototype.getBlock = function (blockNumber) {
139
+ if (blockNumber === void 0) { blockNumber = null; }
138
140
  return __awaiter(this, void 0, void 0, function () {
139
141
  var data;
140
142
  return __generator(this, function (_a) {
141
143
  switch (_a.label) {
142
- case 0: return [4 /*yield*/, axios_1.default.get((0, url_join_1.default)(this.feederGatewayUrl, 'get_block', "?blockId=" + (blockId !== null && blockId !== void 0 ? blockId : 'null')))];
144
+ case 0: return [4 /*yield*/, axios_1.default.get((0, url_join_1.default)(this.feederGatewayUrl, 'get_block', "?blockNumber=" + blockNumber))];
143
145
  case 1:
144
146
  data = (_a.sent()).data;
145
147
  return [2 /*return*/, data];
@@ -153,15 +155,16 @@ var Provider = /** @class */ (function () {
153
155
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L33-L36)
154
156
  *
155
157
  * @param contractAddress
156
- * @param blockId
158
+ * @param blockNumber
157
159
  * @returns Bytecode and ABI of compiled contract
158
160
  */
159
- Provider.prototype.getCode = function (contractAddress, blockId) {
161
+ Provider.prototype.getCode = function (contractAddress, blockNumber) {
162
+ if (blockNumber === void 0) { blockNumber = null; }
160
163
  return __awaiter(this, void 0, void 0, function () {
161
164
  var data;
162
165
  return __generator(this, function (_a) {
163
166
  switch (_a.label) {
164
- case 0: return [4 /*yield*/, axios_1.default.get((0, url_join_1.default)(this.feederGatewayUrl, 'get_code', "?contractAddress=" + contractAddress + "&blockId=" + (blockId !== null && blockId !== void 0 ? blockId : 'null')))];
167
+ case 0: return [4 /*yield*/, axios_1.default.get((0, url_join_1.default)(this.feederGatewayUrl, 'get_code', "?contractAddress=" + contractAddress + "&blockNumber=" + blockNumber))];
165
168
  case 1:
166
169
  data = (_a.sent()).data;
167
170
  return [2 /*return*/, data];
@@ -177,15 +180,16 @@ var Provider = /** @class */ (function () {
177
180
  *
178
181
  * @param contractAddress
179
182
  * @param key - from getStorageVarAddress('<STORAGE_VARIABLE_NAME>') (WIP)
180
- * @param blockId
183
+ * @param blockNumber
181
184
  * @returns the value of the storage variable
182
185
  */
183
- Provider.prototype.getStorageAt = function (contractAddress, key, blockId) {
186
+ Provider.prototype.getStorageAt = function (contractAddress, key, blockNumber) {
187
+ if (blockNumber === void 0) { blockNumber = null; }
184
188
  return __awaiter(this, void 0, void 0, function () {
185
189
  var data;
186
190
  return __generator(this, function (_a) {
187
191
  switch (_a.label) {
188
- case 0: return [4 /*yield*/, axios_1.default.get((0, url_join_1.default)(this.feederGatewayUrl, 'get_storage_at', "?contractAddress=" + contractAddress + "&key=" + key + "&blockId=" + (blockId !== null && blockId !== void 0 ? blockId : 'null')))];
192
+ case 0: return [4 /*yield*/, axios_1.default.get((0, url_join_1.default)(this.feederGatewayUrl, 'get_storage_at', "?contractAddress=" + contractAddress + "&key=" + key + "&blockNumber=" + blockNumber))];
189
193
  case 1:
190
194
  data = (_a.sent()).data;
191
195
  return [2 /*return*/, data];
@@ -199,7 +203,7 @@ var Provider = /** @class */ (function () {
199
203
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L48-L52)
200
204
  *
201
205
  * @param txHash
202
- * @returns the transaction status object { block_id, tx_status: NOT_RECEIVED | RECEIVED | PENDING | REJECTED | ACCEPTED_ONCHAIN }
206
+ * @returns the transaction status object { block_number, tx_status: NOT_RECEIVED | RECEIVED | PENDING | REJECTED | ACCEPTED_ONCHAIN }
203
207
  */
204
208
  Provider.prototype.getTransactionStatus = function (txHash) {
205
209
  return __awaiter(this, void 0, void 0, function () {
@@ -222,7 +226,7 @@ var Provider = /** @class */ (function () {
222
226
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L54-L58)
223
227
  *
224
228
  * @param txHash
225
- * @returns the transacton object { transaction_id, status, transaction, block_id?, block_number?, transaction_index?, transaction_failure_reason? }
229
+ * @returns the transacton object { transaction_id, status, transaction, block_number?, block_number?, transaction_index?, transaction_failure_reason? }
226
230
  */
227
231
  Provider.prototype.getTransaction = function (txHash) {
228
232
  return __awaiter(this, void 0, void 0, function () {
@@ -244,18 +248,18 @@ var Provider = /** @class */ (function () {
244
248
  *
245
249
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/gateway/gateway_client.py#L13-L17)
246
250
  *
247
- * @param tx - transaction to be invoked
251
+ * @param transaction - transaction to be invoked
248
252
  * @returns a confirmation of invoking a function on the starknet contract
249
253
  */
250
- Provider.prototype.addTransaction = function (tx) {
254
+ Provider.prototype.addTransaction = function (transaction) {
251
255
  return __awaiter(this, void 0, void 0, function () {
252
256
  var signature, contract_address_salt, data;
253
257
  return __generator(this, function (_a) {
254
258
  switch (_a.label) {
255
259
  case 0:
256
- signature = tx.type === 'INVOKE_FUNCTION' && (0, stark_1.formatSignature)(tx.signature);
257
- contract_address_salt = tx.type === 'DEPLOY' && (0, number_1.toHex)((0, number_1.toBN)(tx.contract_address_salt));
258
- return [4 /*yield*/, axios_1.default.post((0, url_join_1.default)(this.gatewayUrl, 'add_transaction'), (0, json_1.stringify)(__assign(__assign(__assign({}, tx), (Array.isArray(signature) && { signature: signature })), (contract_address_salt && { contract_address_salt: contract_address_salt }))), { headers: { 'Content-Type': 'application/json' } })];
260
+ signature = transaction.type === 'INVOKE_FUNCTION' && (0, stark_1.formatSignature)(transaction.signature);
261
+ contract_address_salt = transaction.type === 'DEPLOY' && (0, number_1.toHex)((0, number_1.toBN)(transaction.contract_address_salt));
262
+ return [4 /*yield*/, axios_1.default.post((0, url_join_1.default)(this.gatewayUrl, 'add_transaction'), (0, json_1.stringify)(__assign(__assign(__assign({}, transaction), (Array.isArray(signature) && { signature: signature })), (contract_address_salt && { contract_address_salt: contract_address_salt }))), { headers: { 'Content-Type': 'application/json' } })];
259
263
  case 1:
260
264
  data = (_a.sent()).data;
261
265
  return [2 /*return*/, data];
@@ -308,20 +312,21 @@ var Provider = /** @class */ (function () {
308
312
  switch (_a.label) {
309
313
  case 0:
310
314
  onchain = false;
311
- _a.label = 1;
315
+ return [4 /*yield*/, wait(retryInterval)];
312
316
  case 1:
313
- if (!!onchain) return [3 /*break*/, 4];
317
+ _a.sent();
318
+ _a.label = 2;
319
+ case 2:
320
+ if (!!onchain) return [3 /*break*/, 5];
314
321
  // eslint-disable-next-line no-await-in-loop
315
322
  return [4 /*yield*/, wait(retryInterval)];
316
- case 2:
323
+ case 3:
317
324
  // eslint-disable-next-line no-await-in-loop
318
325
  _a.sent();
319
326
  return [4 /*yield*/, this.getTransactionStatus(txHash)];
320
- case 3:
327
+ case 4:
321
328
  res = _a.sent();
322
- if (res.tx_status === 'ACCEPTED_ONCHAIN' ||
323
- (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.
324
- ) {
329
+ if (res.tx_status === 'ACCEPTED_ON_L1' || res.tx_status === 'ACCEPTED_ON_L2') {
325
330
  onchain = true;
326
331
  }
327
332
  else if (res.tx_status === 'REJECTED') {
@@ -330,8 +335,8 @@ var Provider = /** @class */ (function () {
330
335
  else if (res.tx_status === 'NOT_RECEIVED') {
331
336
  throw Error('NOT_RECEIVED');
332
337
  }
333
- return [3 /*break*/, 1];
334
- case 4: return [2 /*return*/];
338
+ return [3 /*break*/, 2];
339
+ case 5: return [2 /*return*/];
335
340
  }
336
341
  });
337
342
  });
@@ -1,4 +1,4 @@
1
- import type { AddTransactionResponse, CallContractResponse, CallContractTransaction, CompiledContract, GetBlockResponse, GetCodeResponse, GetContractAddressesResponse, GetTransactionResponse, GetTransactionStatusResponse, Transaction } from '../types';
1
+ import type { AddTransactionResponse, BlockNumber, CallContractResponse, CallContractTransaction, CompiledContract, GetBlockResponse, GetCodeResponse, GetContractAddressesResponse, GetTransactionResponse, GetTransactionStatusResponse, Signature, Transaction } from '../types';
2
2
  import type { BigNumberish } from '../utils/number';
3
3
  export declare abstract class ProviderInterface {
4
4
  abstract baseUrl: string;
@@ -16,30 +16,30 @@ export declare abstract class ProviderInterface {
16
16
  *
17
17
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L17-L25)
18
18
  *
19
- * @param invokeTx - transaction to be invoked
20
- * @param blockId
19
+ * @param invokeTransaction - transaction to be invoked
20
+ * @param blockNumber
21
21
  * @returns the result of the function on the smart contract.
22
22
  */
23
- abstract callContract(invokeTx: CallContractTransaction, blockId?: number): Promise<CallContractResponse>;
23
+ abstract callContract(invokeTransaction: CallContractTransaction, blockNumber?: BlockNumber): Promise<CallContractResponse>;
24
24
  /**
25
25
  * Gets the block information from a block ID.
26
26
  *
27
27
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L27-L31)
28
28
  *
29
- * @param blockId
30
- * @returns the block object { block_id, previous_block_id, state_root, status, timestamp, transaction_receipts, transactions }
29
+ * @param blockNumber
30
+ * @returns the block object { block_number, previous_block_number, state_root, status, timestamp, transaction_receipts, transactions }
31
31
  */
32
- abstract getBlock(blockId?: number): Promise<GetBlockResponse>;
32
+ abstract getBlock(blockNumber?: BlockNumber): Promise<GetBlockResponse>;
33
33
  /**
34
34
  * Gets the code of the deployed contract.
35
35
  *
36
36
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L33-L36)
37
37
  *
38
38
  * @param contractAddress
39
- * @param blockId
39
+ * @param blockNumber
40
40
  * @returns Bytecode and ABI of compiled contract
41
41
  */
42
- abstract getCode(contractAddress: string, blockId?: number): Promise<GetCodeResponse>;
42
+ abstract getCode(contractAddress: string, blockNumber?: BlockNumber): Promise<GetCodeResponse>;
43
43
  /**
44
44
  * Gets the contract's storage variable at a specific key.
45
45
  *
@@ -47,17 +47,17 @@ export declare abstract class ProviderInterface {
47
47
  *
48
48
  * @param contractAddress
49
49
  * @param key - from getStorageVarAddress('<STORAGE_VARIABLE_NAME>') (WIP)
50
- * @param blockId
50
+ * @param blockNumber
51
51
  * @returns the value of the storage variable
52
52
  */
53
- abstract getStorageAt(contractAddress: string, key: number, blockId?: number): Promise<object>;
53
+ abstract getStorageAt(contractAddress: string, key: number, blockNumber?: BlockNumber): Promise<object>;
54
54
  /**
55
55
  * Gets the status of a transaction.
56
56
  *
57
57
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L48-L52)
58
58
  *
59
59
  * @param txHash
60
- * @returns the transaction status object { block_id, tx_status: NOT_RECEIVED | RECEIVED | PENDING | REJECTED | ACCEPTED_ONCHAIN }
60
+ * @returns the transaction status object { block_number, tx_status: NOT_RECEIVED | RECEIVED | PENDING | REJECTED | ACCEPTED_ONCHAIN }
61
61
  */
62
62
  abstract getTransactionStatus(txHash: BigNumberish): Promise<GetTransactionStatusResponse>;
63
63
  /**
@@ -66,7 +66,7 @@ export declare abstract class ProviderInterface {
66
66
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L54-L58)
67
67
  *
68
68
  * @param txHash
69
- * @returns the transacton object { transaction_id, status, transaction, block_id?, block_number?, transaction_index?, transaction_failure_reason? }
69
+ * @returns the transacton object { transaction_id, status, transaction, block_number?, block_number?, transaction_index?, transaction_failure_reason? }
70
70
  */
71
71
  abstract getTransaction(txHash: BigNumberish): Promise<GetTransactionResponse>;
72
72
  /**
@@ -74,10 +74,10 @@ export declare abstract class ProviderInterface {
74
74
  *
75
75
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/gateway/gateway_client.py#L13-L17)
76
76
  *
77
- * @param tx - transaction to be invoked
77
+ * @param transaction - transaction to be invoked
78
78
  * @returns a confirmation of invoking a function on the starknet contract
79
79
  */
80
- abstract addTransaction(tx: Transaction): Promise<AddTransactionResponse>;
80
+ abstract addTransaction(transaction: Transaction): Promise<AddTransactionResponse>;
81
81
  /**
82
82
  * Deploys a given compiled contract (json) to starknet
83
83
  *
@@ -95,6 +95,6 @@ export declare abstract class ProviderInterface {
95
95
  * @param signature - (optional) signature to send along
96
96
  * @returns response from addTransaction
97
97
  */
98
- abstract invokeFunction(contractAddress: string, entrypointSelector: string, calldata?: string[], signature?: [BigNumberish, BigNumberish]): Promise<AddTransactionResponse>;
98
+ abstract invokeFunction(contractAddress: string, entrypointSelector: string, calldata?: string[], signature?: Signature): Promise<AddTransactionResponse>;
99
99
  abstract waitForTx(txHash: BigNumberish, retryInterval?: number): Promise<void>;
100
100
  }
@@ -1,5 +1,6 @@
1
1
  import { Provider } from '../provider';
2
- import { AddTransactionResponse, KeyPair, Transaction } from '../types';
2
+ import { AddTransactionResponse, KeyPair, Signature, Transaction } from '../types';
3
+ import { TypedData } from '../utils/typedData';
3
4
  import { SignerInterface } from './interface';
4
5
  export declare class Signer extends Provider implements SignerInterface {
5
6
  address: string;
@@ -10,8 +11,24 @@ export declare class Signer extends Provider implements SignerInterface {
10
11
  *
11
12
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/gateway/gateway_client.py#L13-L17)
12
13
  *
13
- * @param tx - transaction to be invoked
14
+ * @param transaction - transaction to be invoked
14
15
  * @returns a confirmation of invoking a function on the starknet contract
15
16
  */
16
- addTransaction(tx: Transaction): Promise<AddTransactionResponse>;
17
+ addTransaction(transaction: Transaction): Promise<AddTransactionResponse>;
18
+ /**
19
+ * Sign an JSON object with the starknet private key and return the signature
20
+ *
21
+ * @param json - JSON object to be signed
22
+ * @returns the signature of the JSON object
23
+ * @throws {Error} if the JSON object is not a valid JSON
24
+ */
25
+ signMessage(typedData: TypedData): Promise<Signature>;
26
+ /**
27
+ * Hash a JSON object with pederson hash and return the hash
28
+ *
29
+ * @param json - JSON object to be hashed
30
+ * @returns the hash of the JSON object
31
+ * @throws {Error} if the JSON object is not a valid JSON
32
+ */
33
+ hashMessage(typedData: TypedData): Promise<string>;
17
34
  }
@@ -87,6 +87,7 @@ var encode_1 = require("../utils/encode");
87
87
  var hash_1 = require("../utils/hash");
88
88
  var number_1 = require("../utils/number");
89
89
  var stark_1 = require("../utils/stark");
90
+ var typedData_1 = require("../utils/typedData");
90
91
  var Signer = /** @class */ (function (_super) {
91
92
  __extends(Signer, _super);
92
93
  function Signer(provider, address, keyPair) {
@@ -100,45 +101,85 @@ var Signer = /** @class */ (function (_super) {
100
101
  *
101
102
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/gateway/gateway_client.py#L13-L17)
102
103
  *
103
- * @param tx - transaction to be invoked
104
+ * @param transaction - transaction to be invoked
104
105
  * @returns a confirmation of invoking a function on the starknet contract
105
106
  */
106
- Signer.prototype.addTransaction = function (tx) {
107
+ Signer.prototype.addTransaction = function (transaction) {
107
108
  return __awaiter(this, void 0, void 0, function () {
108
- var result, nonceBn, calldataDecimal, msgHash, _a, r, s;
109
- return __generator(this, function (_b) {
110
- switch (_b.label) {
109
+ var nonceBn, result, calldataDecimal, msgHash, signature;
110
+ return __generator(this, function (_a) {
111
+ switch (_a.label) {
111
112
  case 0:
112
- if (tx.type === 'DEPLOY')
113
- return [2 /*return*/, _super.prototype.addTransaction.call(this, tx)];
114
- (0, minimalistic_assert_1.default)(!tx.signature, "Adding signatures to a signer tx currently isn't supported");
115
- return [4 /*yield*/, this.callContract({
116
- contract_address: this.address,
117
- entry_point_selector: (0, stark_1.getSelectorFromName)('get_nonce'),
118
- })];
119
- case 1:
120
- result = (_b.sent()).result;
113
+ if (transaction.type === 'DEPLOY')
114
+ return [2 /*return*/, _super.prototype.addTransaction.call(this, transaction)];
115
+ (0, minimalistic_assert_1.default)(!transaction.signature, "Adding signatures to a signer transaction currently isn't supported");
116
+ if (!transaction.nonce) return [3 /*break*/, 1];
117
+ nonceBn = (0, number_1.toBN)(transaction.nonce);
118
+ return [3 /*break*/, 3];
119
+ case 1: return [4 /*yield*/, this.callContract({
120
+ contract_address: this.address,
121
+ entry_point_selector: (0, stark_1.getSelectorFromName)('get_nonce'),
122
+ })];
123
+ case 2:
124
+ result = (_a.sent()).result;
121
125
  nonceBn = (0, number_1.toBN)(result[0]);
122
- calldataDecimal = (tx.calldata || []).map(function (x) { return (0, number_1.toBN)(x).toString(); });
123
- msgHash = (0, encode_1.addHexPrefix)((0, hash_1.hashMessage)(this.address, tx.contract_address, tx.entry_point_selector, calldataDecimal, nonceBn.toString()));
124
- _a = (0, ellipticCurve_1.sign)(this.keyPair, msgHash), r = _a.r, s = _a.s;
126
+ _a.label = 3;
127
+ case 3:
128
+ calldataDecimal = (transaction.calldata || []).map(function (x) { return (0, number_1.toBN)(x).toString(); });
129
+ msgHash = (0, encode_1.addHexPrefix)((0, hash_1.hashMessage)(this.address, transaction.contract_address, transaction.entry_point_selector, calldataDecimal, nonceBn.toString()));
130
+ signature = (0, ellipticCurve_1.sign)(this.keyPair, msgHash);
125
131
  return [2 /*return*/, _super.prototype.addTransaction.call(this, {
126
132
  type: 'INVOKE_FUNCTION',
127
133
  entry_point_selector: (0, stark_1.getSelectorFromName)('execute'),
128
134
  calldata: __spreadArray(__spreadArray([
129
- tx.contract_address,
130
- tx.entry_point_selector,
135
+ transaction.contract_address,
136
+ transaction.entry_point_selector,
131
137
  calldataDecimal.length.toString()
132
138
  ], __read(calldataDecimal), false), [
133
139
  nonceBn.toString(),
134
140
  ], false).map(function (x) { return (0, number_1.toBN)(x).toString(); }),
135
141
  contract_address: this.address,
136
- signature: [r, s],
142
+ signature: signature,
137
143
  })];
138
144
  }
139
145
  });
140
146
  });
141
147
  };
148
+ /**
149
+ * Sign an JSON object with the starknet private key and return the signature
150
+ *
151
+ * @param json - JSON object to be signed
152
+ * @returns the signature of the JSON object
153
+ * @throws {Error} if the JSON object is not a valid JSON
154
+ */
155
+ Signer.prototype.signMessage = function (typedData) {
156
+ return __awaiter(this, void 0, void 0, function () {
157
+ var _a, _b;
158
+ return __generator(this, function (_c) {
159
+ switch (_c.label) {
160
+ case 0:
161
+ _a = ellipticCurve_1.sign;
162
+ _b = [this.keyPair];
163
+ return [4 /*yield*/, this.hashMessage(typedData)];
164
+ case 1: return [2 /*return*/, _a.apply(void 0, _b.concat([_c.sent()]))];
165
+ }
166
+ });
167
+ });
168
+ };
169
+ /**
170
+ * Hash a JSON object with pederson hash and return the hash
171
+ *
172
+ * @param json - JSON object to be hashed
173
+ * @returns the hash of the JSON object
174
+ * @throws {Error} if the JSON object is not a valid JSON
175
+ */
176
+ Signer.prototype.hashMessage = function (typedData) {
177
+ return __awaiter(this, void 0, void 0, function () {
178
+ return __generator(this, function (_a) {
179
+ return [2 /*return*/, (0, typedData_1.getMessageHash)(typedData, this.address)];
180
+ });
181
+ });
182
+ };
142
183
  return Signer;
143
184
  }(provider_1.Provider));
144
185
  exports.Signer = Signer;
@@ -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
  export declare abstract class SignerInterface extends Provider {
4
5
  abstract address: string;
5
6
  /**
@@ -7,8 +8,26 @@ export declare abstract class SignerInterface extends Provider {
7
8
  *
8
9
  * [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/gateway/gateway_client.py#L13-L17)
9
10
  *
10
- * @param tx - transaction to be invoked
11
+ * @param transaction - transaction to be invoked
11
12
  * @returns a confirmation of invoking a function on the starknet contract
12
13
  */
13
- abstract addTransaction(tx: Transaction): Promise<AddTransactionResponse>;
14
+ abstract addTransaction(transaction: Transaction): Promise<AddTransactionResponse>;
15
+ /**
16
+ * Sign an JSON object for off-chain usage with the starknet private key and return the signature
17
+ * This adds a message prefix so it cant be interchanged with transactions
18
+ *
19
+ * @param json - JSON object to be signed
20
+ * @returns the signature of the JSON object
21
+ * @throws {Error} if the JSON object is not a valid JSON
22
+ */
23
+ abstract signMessage(typedData: TypedData): Promise<Signature>;
24
+ /**
25
+ * Hash a JSON object with pederson hash and return the hash
26
+ * This adds a message prefix so it cant be interchanged with transactions
27
+ *
28
+ * @param json - JSON object to be hashed
29
+ * @returns the hash of the JSON object
30
+ * @throws {Error} if the JSON object is not a valid JSON
31
+ */
32
+ abstract hashMessage(typedData: TypedData): Promise<string>;
14
33
  }
package/dist/types.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import type { ec as EC } from 'elliptic';
2
2
  import type { BigNumberish } from './utils/number';
3
3
  export declare type KeyPair = EC.KeyPair;
4
- export declare type Signature = EC.Signature;
4
+ export declare type Signature = BigNumberish[];
5
5
  export declare type GetContractAddressesResponse = {
6
6
  Starknet: string;
7
7
  GpsStatementVerifier: string;
8
8
  };
9
- export declare type Status = 'NOT_RECEIVED' | 'RECEIVED' | 'PENDING' | 'REJECTED' | 'ACCEPTED_ONCHAIN';
10
- export declare type TxStatus = 'TRANSACTION_RECEIVED';
9
+ export declare type Status = 'NOT_RECEIVED' | 'RECEIVED' | 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
10
+ export declare type TransactionStatus = 'TRANSACTION_RECEIVED';
11
11
  export declare type Type = 'DEPLOY' | 'INVOKE_FUNCTION';
12
12
  export declare type EntryPointType = 'EXTERNAL';
13
13
  export declare type CompressedProgram = string;
@@ -33,6 +33,7 @@ export declare type StructAbi = {
33
33
  export declare type Abi = FunctionAbi | StructAbi;
34
34
  export declare type EntryPointsByType = object;
35
35
  export declare type Program = object;
36
+ export declare type BlockNumber = 'pending' | null | number;
36
37
  export declare type CompiledContract = {
37
38
  abi: Abi[];
38
39
  entry_points_by_type: EntryPointsByType;
@@ -44,14 +45,16 @@ export declare type DeployTransaction = {
44
45
  contract_definition: CompressedCompiledContract;
45
46
  contract_address_salt: BigNumberish;
46
47
  constructor_calldata: string[];
48
+ nonce?: BigNumberish;
47
49
  };
48
50
  export declare type InvokeFunctionTransaction = {
49
51
  type: 'INVOKE_FUNCTION';
50
52
  contract_address: string;
51
- signature?: [BigNumberish, BigNumberish];
53
+ signature?: Signature;
52
54
  entry_point_type?: EntryPointType;
53
55
  entry_point_selector: string;
54
56
  calldata?: string[];
57
+ nonce?: BigNumberish;
55
58
  };
56
59
  export declare type CallContractTransaction = Omit<InvokeFunctionTransaction, 'type'>;
57
60
  export declare type Transaction = DeployTransaction | InvokeFunctionTransaction;
@@ -75,7 +78,7 @@ export declare type GetBlockResponse = {
75
78
  payload: string[];
76
79
  from_address: string;
77
80
  }[];
78
- block_number: number;
81
+ block_number: BlockNumber;
79
82
  status: Status;
80
83
  transaction_index: number;
81
84
  };
@@ -95,12 +98,12 @@ export declare type GetTransactionResponse = {
95
98
  status: Status;
96
99
  transaction: Transaction;
97
100
  block_hash: string;
98
- block_number: number;
101
+ block_number: BlockNumber;
99
102
  transaction_index: number;
100
103
  transaction_hash: string;
101
104
  };
102
105
  export declare type AddTransactionResponse = {
103
- code: TxStatus;
106
+ code: TransactionStatus;
104
107
  transaction_hash: string;
105
108
  address?: string;
106
109
  };
@@ -5,5 +5,12 @@ export declare const ec: EC;
5
5
  export declare const genKeyPair: (options?: EC.GenKeyPairOptions | undefined) => EC.KeyPair;
6
6
  export declare function getKeyPair(pk: BigNumberish): KeyPair;
7
7
  export declare function getStarkKey(keyPair: KeyPair): string;
8
+ /**
9
+ * Takes a public key and casts it into `elliptic` KeyPair format.
10
+ *
11
+ * @param publicKey - public key which should get casted to a KeyPair
12
+ * @returns keyPair with public key only, which can be used to verify signatures, but cant sign anything
13
+ */
14
+ export declare function getKeyPairFromPublicKey(publicKey: BigNumberish): KeyPair;
8
15
  export declare function sign(keyPair: KeyPair, msgHash: string): Signature;
9
- export declare function verify(keyPair: KeyPair, msgHash: string, sig: Signature): boolean;
16
+ export declare function verify(keyPair: KeyPair | KeyPair[], msgHash: string, sig: Signature): boolean;
@@ -1,9 +1,25 @@
1
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
+ };
2
18
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
19
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
20
  };
5
21
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.verify = exports.sign = exports.getStarkKey = exports.getKeyPair = exports.genKeyPair = exports.ec = void 0;
22
+ exports.verify = exports.sign = exports.getKeyPairFromPublicKey = exports.getStarkKey = exports.getKeyPair = exports.genKeyPair = exports.ec = void 0;
7
23
  var elliptic_1 = require("elliptic");
8
24
  var hash_js_1 = __importDefault(require("hash.js"));
9
25
  var minimalistic_assert_1 = __importDefault(require("minimalistic-assert"));
@@ -50,6 +66,17 @@ function getStarkKey(keyPair) {
50
66
  return (0, encode_1.addHexPrefix)((0, encode_1.sanitizeBytes)(keyPair.pub.getX().toString(16), 2));
51
67
  }
52
68
  exports.getStarkKey = getStarkKey;
69
+ /**
70
+ * Takes a public key and casts it into `elliptic` KeyPair format.
71
+ *
72
+ * @param publicKey - public key which should get casted to a KeyPair
73
+ * @returns keyPair with public key only, which can be used to verify signatures, but cant sign anything
74
+ */
75
+ function getKeyPairFromPublicKey(publicKey) {
76
+ var publicKeyBn = (0, number_1.toBN)(publicKey);
77
+ return exports.ec.keyFromPublic((0, encode_1.removeHexPrefix)((0, number_1.toHex)(publicKeyBn)), 'hex');
78
+ }
79
+ exports.getKeyPairFromPublicKey = getKeyPairFromPublicKey;
53
80
  /*
54
81
  Signs a message using the provided key.
55
82
  key should be an KeyPair with a valid private key.
@@ -66,9 +93,14 @@ function sign(keyPair, msgHash) {
66
93
  (0, number_1.assertInRange)(r, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'r');
67
94
  (0, number_1.assertInRange)(s, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.EC_ORDER)), 's');
68
95
  (0, number_1.assertInRange)(w, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'w');
69
- return msgSignature;
96
+ return [r, s];
70
97
  }
71
98
  exports.sign = sign;
99
+ function chunkArray(arr, n) {
100
+ return Array(Math.ceil(arr.length / n))
101
+ .fill('')
102
+ .map(function (_, i) { return arr.slice(i * n, i * n + n); });
103
+ }
72
104
  /*
73
105
  Verifies a message using the provided key.
74
106
  key should be an KeyPair with a valid public key.
@@ -76,14 +108,21 @@ exports.sign = sign;
76
108
  Returns a boolean true if the verification succeeds.
77
109
  */
78
110
  function verify(keyPair, msgHash, sig) {
111
+ var keyPairArray = Array.isArray(keyPair) ? keyPair : [keyPair];
79
112
  var msgHashBN = (0, number_1.toBN)((0, encode_1.addHexPrefix)(msgHash));
113
+ (0, minimalistic_assert_1.default)(sig.length % 2 === 0, 'Signature must be an array of length dividable by 2');
80
114
  (0, number_1.assertInRange)(msgHashBN, constants_1.ZERO, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'msgHash');
81
- var r = sig.r, s = sig.s;
82
- var w = s.invm(exports.ec.n);
83
- // Verify signature has valid length.
84
- (0, number_1.assertInRange)(r, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'r');
85
- (0, number_1.assertInRange)(s, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.EC_ORDER)), 's');
86
- (0, number_1.assertInRange)(w, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'w');
87
- return keyPair.verify(fixMessage(msgHash), sig);
115
+ (0, minimalistic_assert_1.default)(keyPairArray.length === sig.length / 2, 'Signature and keyPair length must be equal');
116
+ return chunkArray(sig, 2).every(function (_a, i) {
117
+ var _b;
118
+ var _c = __read(_a, 2), r = _c[0], s = _c[1];
119
+ var rBN = (0, number_1.toBN)(r);
120
+ var sBN = (0, number_1.toBN)(s);
121
+ var w = sBN.invm(exports.ec.n);
122
+ (0, number_1.assertInRange)(rBN, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'r');
123
+ (0, number_1.assertInRange)(sBN, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.EC_ORDER)), 's');
124
+ (0, number_1.assertInRange)(w, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'w');
125
+ return (_b = exports.ec.verify(fixMessage(msgHash), { r: rBN, s: sBN }, keyPairArray[i])) !== null && _b !== void 0 ? _b : false;
126
+ });
88
127
  }
89
128
  exports.verify = verify;