starknet 4.1.0 → 4.3.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 +32 -0
- package/__tests__/defaultProvider.test.ts +11 -24
- package/__tests__/rpcProvider.test.ts +3 -3
- package/__tests__/sequencerProvider.test.ts +40 -2
- package/__tests__/utils/address.test.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/provider/default.d.ts +2 -2
- package/dist/provider/default.js +3 -3
- package/dist/provider/interface.d.ts +6 -3
- package/dist/provider/rpc.d.ts +9 -4
- package/dist/provider/rpc.js +67 -25
- package/dist/provider/sequencer.d.ts +2 -2
- package/dist/provider/sequencer.js +9 -9
- package/dist/provider/utils.d.ts +12 -0
- package/dist/provider/utils.js +17 -1
- package/dist/types/api/openrpc.d.ts +151 -0
- package/dist/types/api/openrpc.js +9 -0
- package/dist/types/api/rpc.d.ts +22 -43
- package/dist/types/provider.d.ts +5 -5
- package/dist/utils/address.js +1 -1
- package/dist/utils/ellipticCurve.d.ts +13 -0
- package/dist/utils/ellipticCurve.js +20 -16
- package/dist/utils/hash.d.ts +1 -0
- package/dist/utils/hash.js +8 -1
- package/dist/utils/responseParser/rpc.d.ts +13 -3
- package/dist/utils/responseParser/rpc.js +2 -10
- package/dist/utils/responseParser/sequencer.d.ts +4 -1
- package/dist/utils/responseParser/sequencer.js +1 -7
- package/dist/utils/url.d.ts +7 -0
- package/dist/utils/url.js +49 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
- package/provider/default.d.ts +2 -2
- package/provider/default.js +3 -3
- package/provider/interface.d.ts +6 -3
- package/provider/rpc.d.ts +9 -4
- package/provider/rpc.js +67 -25
- package/provider/sequencer.d.ts +2 -2
- package/provider/sequencer.js +9 -9
- package/provider/utils.d.ts +12 -0
- package/provider/utils.js +17 -1
- package/src/index.ts +1 -0
- package/src/provider/default.ts +2 -3
- package/src/provider/interface.ts +5 -3
- package/src/provider/rpc.ts +56 -34
- package/src/provider/sequencer.ts +11 -9
- package/src/provider/utils.ts +22 -1
- package/src/types/api/openrpc.ts +168 -0
- package/src/types/api/rpc.ts +22 -45
- package/src/types/provider.ts +5 -5
- package/src/utils/address.ts +2 -2
- package/src/utils/ellipticCurve.ts +20 -16
- package/src/utils/hash.ts +8 -1
- package/src/utils/responseParser/rpc.ts +16 -13
- package/src/utils/responseParser/sequencer.ts +5 -8
- package/src/utils/url.ts +53 -0
- package/types/api/openrpc.d.ts +151 -0
- package/types/api/openrpc.js +9 -0
- package/types/api/rpc.d.ts +22 -43
- package/types/provider.d.ts +5 -5
- package/utils/address.js +1 -1
- package/utils/ellipticCurve.d.ts +13 -0
- package/utils/ellipticCurve.js +20 -16
- package/utils/hash.d.ts +1 -0
- package/utils/hash.js +8 -1
- package/utils/responseParser/rpc.d.ts +13 -3
- package/utils/responseParser/rpc.js +2 -10
- package/utils/responseParser/sequencer.d.ts +4 -1
- package/utils/responseParser/sequencer.js +1 -7
- package/utils/url.d.ts +7 -0
- package/utils/url.js +49 -0
- package/www/docs/API/account.md +20 -18
- package/www/docs/API/contract.md +10 -10
- package/www/docs/API/contractFactory.md +14 -11
- package/www/docs/API/provider.md +60 -37
- package/www/docs/API/signer.md +8 -10
- package/www/docs/API/utils.md +151 -74
- package/www/guides/account.md +25 -3
- package/www/guides/erc20.md +20 -4
- package/www/guides/intro.md +3 -1
|
@@ -2,7 +2,6 @@ import urljoin from 'url-join';
|
|
|
2
2
|
|
|
3
3
|
import { ONE, StarknetChainId, ZERO } from '../constants';
|
|
4
4
|
import {
|
|
5
|
-
BlockTag,
|
|
6
5
|
Call,
|
|
7
6
|
CallContractResponse,
|
|
8
7
|
ContractClass,
|
|
@@ -31,6 +30,7 @@ import { BigNumberish, bigNumberishArrayToDecimalStringArray, toBN, toHex } from
|
|
|
31
30
|
import { parseContract, wait } from '../utils/provider';
|
|
32
31
|
import { SequencerAPIResponseParser } from '../utils/responseParser/sequencer';
|
|
33
32
|
import { randomAddress } from '../utils/stark';
|
|
33
|
+
import { buildUrl } from '../utils/url';
|
|
34
34
|
import { GatewayError, HttpError } from './errors';
|
|
35
35
|
import { ProviderInterface } from './interface';
|
|
36
36
|
import { BlockIdentifier, getFormattedBlockIdentifier } from './utils';
|
|
@@ -74,9 +74,13 @@ export class SequencerProvider implements ProviderInterface {
|
|
|
74
74
|
this.gatewayUrl = urljoin(this.baseUrl, 'gateway');
|
|
75
75
|
} else {
|
|
76
76
|
this.baseUrl = optionsOrProvider.baseUrl;
|
|
77
|
-
this.feederGatewayUrl =
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
this.feederGatewayUrl = buildUrl(
|
|
78
|
+
this.baseUrl,
|
|
79
|
+
'feeder_gateway',
|
|
80
|
+
optionsOrProvider.feederGatewayUrl
|
|
81
|
+
);
|
|
82
|
+
this.gatewayUrl = buildUrl(this.baseUrl, 'gateway', optionsOrProvider.gatewayUrl);
|
|
83
|
+
|
|
80
84
|
this.chainId =
|
|
81
85
|
optionsOrProvider.chainId ??
|
|
82
86
|
SequencerProvider.getChainIdFromBaseUrl(optionsOrProvider.baseUrl);
|
|
@@ -228,11 +232,11 @@ export class SequencerProvider implements ProviderInterface {
|
|
|
228
232
|
public async getStorageAt(
|
|
229
233
|
contractAddress: string,
|
|
230
234
|
key: BigNumberish,
|
|
231
|
-
|
|
235
|
+
blockIdentifier: BlockIdentifier = 'pending'
|
|
232
236
|
): Promise<BigNumberish> {
|
|
233
237
|
const parsedKey = toBN(key).toString(10);
|
|
234
238
|
return this.fetchEndpoint('get_storage_at', {
|
|
235
|
-
blockIdentifier
|
|
239
|
+
blockIdentifier,
|
|
236
240
|
contractAddress,
|
|
237
241
|
key: parsedKey,
|
|
238
242
|
});
|
|
@@ -327,9 +331,7 @@ export class SequencerProvider implements ProviderInterface {
|
|
|
327
331
|
contractAddress: string,
|
|
328
332
|
blockIdentifier: BlockIdentifier = 'pending'
|
|
329
333
|
): Promise<Sequencer.GetCodeResponse> {
|
|
330
|
-
return this.fetchEndpoint('get_code', { contractAddress, blockIdentifier })
|
|
331
|
-
this.responseParser.parseGetCodeResponse
|
|
332
|
-
);
|
|
334
|
+
return this.fetchEndpoint('get_code', { contractAddress, blockIdentifier });
|
|
333
335
|
}
|
|
334
336
|
|
|
335
337
|
public async waitForTransaction(txHash: BigNumberish, retryInterval: number = 8000) {
|
package/src/provider/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BlockNumber } from '../types';
|
|
2
|
-
import { BigNumberish, toBN, toHex } from '../utils/number';
|
|
2
|
+
import { BigNumberish, isHex, toBN, toHex } from '../utils/number';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
@@ -31,11 +31,32 @@ export function txIdentifier(txHash?: BigNumberish, txId?: BigNumberish): string
|
|
|
31
31
|
// hex string and BN are detected as block hashes
|
|
32
32
|
// decimal string and number are detected as block numbers
|
|
33
33
|
// null appends nothing to the request url
|
|
34
|
+
|
|
34
35
|
export type BlockIdentifier = BlockNumber | BigNumberish;
|
|
35
36
|
type BlockIdentifierObject =
|
|
36
37
|
| { type: 'BLOCK_NUMBER'; data: BlockNumber }
|
|
37
38
|
| { type: 'BLOCK_HASH'; data: BigNumberish };
|
|
38
39
|
|
|
40
|
+
export class BlockIdentifierClass {
|
|
41
|
+
blockIdentifier: BlockIdentifier;
|
|
42
|
+
|
|
43
|
+
constructor(blockIdentifier: BlockIdentifier) {
|
|
44
|
+
this.blockIdentifier = blockIdentifier;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getIdentifier() {
|
|
48
|
+
if (typeof this.blockIdentifier === 'string' && isHex(this.blockIdentifier)) {
|
|
49
|
+
return { block_hash: this.blockIdentifier };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (typeof this.blockIdentifier === 'number') {
|
|
53
|
+
return { block_number: this.blockIdentifier };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return this.blockIdentifier;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
39
60
|
/**
|
|
40
61
|
* Identifies the block to be queried.
|
|
41
62
|
*
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starknet RPC version 0.1.0
|
|
3
|
+
* starknet_api_openrpc version 0.31.0
|
|
4
|
+
*
|
|
5
|
+
* TypeScript Representation of OpenRpc protocol types | results
|
|
6
|
+
* errors are not implemented here only results
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* "type": "string",
|
|
11
|
+
* "title": "Field element",
|
|
12
|
+
* "$comment": "A field element, represented as a string of hex digits",
|
|
13
|
+
* "description": "A field element. Represented as up to 63 hex digits and leading 4 bits zeroed.",
|
|
14
|
+
* "pattern": "^0x0[a-fA-F0-9]{1,63}$"
|
|
15
|
+
*/
|
|
16
|
+
type FELT = string;
|
|
17
|
+
type BLOCK_NUMBER = number;
|
|
18
|
+
type BLOCK_HASH = FELT;
|
|
19
|
+
type TXN_HASH = FELT;
|
|
20
|
+
type TXN_STATUS = 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
|
|
21
|
+
type TXN_TYPE = 'DECLARE' | 'DEPLOY' | 'INVOKE' | 'L1_HANDLER';
|
|
22
|
+
type MSG_TO_L1 = {
|
|
23
|
+
to_address: FELT;
|
|
24
|
+
payload: Array<FELT>;
|
|
25
|
+
};
|
|
26
|
+
type EVENT = {
|
|
27
|
+
from_address: FELT;
|
|
28
|
+
keys: Array<FELT>;
|
|
29
|
+
data: Array<FELT>;
|
|
30
|
+
};
|
|
31
|
+
type COMMON_RECEIPT_PROPERTIES = {
|
|
32
|
+
transaction_hash: TXN_HASH;
|
|
33
|
+
actual_fee: FELT;
|
|
34
|
+
status: TXN_STATUS;
|
|
35
|
+
block_hash: BLOCK_HASH;
|
|
36
|
+
block_number: BLOCK_NUMBER;
|
|
37
|
+
type?: TXN_TYPE;
|
|
38
|
+
};
|
|
39
|
+
type INVOKE_TXN_RECEIPT_PROPERTIES = {
|
|
40
|
+
messages_sent: MSG_TO_L1;
|
|
41
|
+
events: EVENT;
|
|
42
|
+
};
|
|
43
|
+
type PENDING_COMMON_RECEIPT_PROPERTIES = {
|
|
44
|
+
transaction_hash: TXN_HASH;
|
|
45
|
+
actual_fee: FELT;
|
|
46
|
+
type?: TXN_TYPE;
|
|
47
|
+
};
|
|
48
|
+
type INVOKE_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES & INVOKE_TXN_RECEIPT_PROPERTIES;
|
|
49
|
+
type L1_HANDLER_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES;
|
|
50
|
+
type DECLARE_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES;
|
|
51
|
+
type DEPLOY_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES;
|
|
52
|
+
type PENDING_INVOKE_TXN_RECEIPT = PENDING_COMMON_RECEIPT_PROPERTIES & INVOKE_TXN_RECEIPT_PROPERTIES;
|
|
53
|
+
type PENDING_TXN_RECEIPT = PENDING_INVOKE_TXN_RECEIPT | PENDING_COMMON_RECEIPT_PROPERTIES;
|
|
54
|
+
type TXN_RECEIPT =
|
|
55
|
+
| INVOKE_TXN_RECEIPT
|
|
56
|
+
| L1_HANDLER_TXN_RECEIPT
|
|
57
|
+
| DECLARE_TXN_RECEIPT
|
|
58
|
+
| DEPLOY_TXN_RECEIPT
|
|
59
|
+
| PENDING_TXN_RECEIPT;
|
|
60
|
+
|
|
61
|
+
export namespace RPC_1 {
|
|
62
|
+
export type GetTransactionReceiptResponse = TXN_RECEIPT;
|
|
63
|
+
|
|
64
|
+
export type Methods = {
|
|
65
|
+
starknet_getTransactionReceipt: {
|
|
66
|
+
QUERY: never;
|
|
67
|
+
REQUEST: any[];
|
|
68
|
+
RESPONSE: GetTransactionReceiptResponse;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// starknet_getBlockWithTxHashes
|
|
74
|
+
type BLOCK_HEADER = {
|
|
75
|
+
block_hash: BLOCK_HASH;
|
|
76
|
+
parent_hash: BLOCK_HASH;
|
|
77
|
+
block_number: BLOCK_NUMBER;
|
|
78
|
+
new_root: FELT;
|
|
79
|
+
timestamp: number;
|
|
80
|
+
sequencer_address: FELT;
|
|
81
|
+
};
|
|
82
|
+
type BLOCK_BODY_WITH_TX_HASHES = {
|
|
83
|
+
transactions: Array<TXN_HASH>;
|
|
84
|
+
};
|
|
85
|
+
type BLOCK_WITH_TX_HASHES = {
|
|
86
|
+
status: TXN_STATUS;
|
|
87
|
+
} & BLOCK_HEADER &
|
|
88
|
+
BLOCK_BODY_WITH_TX_HASHES;
|
|
89
|
+
type PENDING_BLOCK_WITH_TX_HASHES = BLOCK_BODY_WITH_TX_HASHES & {
|
|
90
|
+
timestamp: number;
|
|
91
|
+
sequencer_address: FELT;
|
|
92
|
+
parent_hash: BLOCK_HASH;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// starknet_getBlockWithTx
|
|
96
|
+
type BLOCK_STATUS = 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
|
|
97
|
+
/**
|
|
98
|
+
* "title": "An integer number in hex format (0x...)",
|
|
99
|
+
* "pattern": "^0x[a-fA-F0-9]+$"
|
|
100
|
+
*/
|
|
101
|
+
type NUM_AS_HEX = string;
|
|
102
|
+
type SIGNATURE = Array<FELT>;
|
|
103
|
+
type COMMON_TXN_PROPERTIES = {
|
|
104
|
+
transaction_hash: TXN_HASH;
|
|
105
|
+
max_fee: FELT;
|
|
106
|
+
version: NUM_AS_HEX;
|
|
107
|
+
signature: SIGNATURE;
|
|
108
|
+
nonce: FELT;
|
|
109
|
+
type: TXN_TYPE;
|
|
110
|
+
};
|
|
111
|
+
type ADDRESS = FELT;
|
|
112
|
+
type FUNCTION_CALL = {
|
|
113
|
+
contract_address: ADDRESS;
|
|
114
|
+
entry_point_selector: FELT;
|
|
115
|
+
calldata: Array<FELT>;
|
|
116
|
+
};
|
|
117
|
+
type INVOKE_TXN = COMMON_TXN_PROPERTIES & FUNCTION_CALL;
|
|
118
|
+
type DECLARE_TXN = COMMON_TXN_PROPERTIES & {
|
|
119
|
+
class_hash: FELT;
|
|
120
|
+
sender_address: ADDRESS;
|
|
121
|
+
};
|
|
122
|
+
type DEPLOY_TXN = {
|
|
123
|
+
transaction_hash: TXN_HASH;
|
|
124
|
+
class_hash: FELT;
|
|
125
|
+
version: NUM_AS_HEX;
|
|
126
|
+
type: TXN_TYPE;
|
|
127
|
+
contract_address: FELT;
|
|
128
|
+
contract_address_salt: FELT;
|
|
129
|
+
constructor_calldata: Array<FELT>;
|
|
130
|
+
};
|
|
131
|
+
type TXN = INVOKE_TXN | DECLARE_TXN | DEPLOY_TXN;
|
|
132
|
+
type BLOCK_BODY_WITH_TXS = {
|
|
133
|
+
transactions: Array<TXN>;
|
|
134
|
+
};
|
|
135
|
+
type BLOCK_WITH_TXS = {
|
|
136
|
+
status: BLOCK_STATUS;
|
|
137
|
+
} & BLOCK_HEADER &
|
|
138
|
+
BLOCK_BODY_WITH_TXS;
|
|
139
|
+
|
|
140
|
+
type PENDING_BLOCK_WITH_TXS = BLOCK_BODY_WITH_TXS & {
|
|
141
|
+
timestamp: number;
|
|
142
|
+
sequencer_address: FELT;
|
|
143
|
+
parent_hash: BLOCK_HASH;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
type CONTRACT_CLASS = {
|
|
147
|
+
program: string; // A base64 representation of the compressed program code
|
|
148
|
+
entry_points_by_type: {
|
|
149
|
+
CONSTRUCTOR: CONTRACT_ENTRY_POINT_LIST;
|
|
150
|
+
EXTERNAL: CONTRACT_ENTRY_POINT_LIST;
|
|
151
|
+
L1_HANDLER: CONTRACT_ENTRY_POINT_LIST;
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
type CONTRACT_ENTRY_POINT_LIST = Array<CONTRACT_ENTRY_POINT>;
|
|
156
|
+
type CONTRACT_ENTRY_POINT = {
|
|
157
|
+
offset: NUM_AS_HEX;
|
|
158
|
+
selector: FELT;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export namespace OPENRPC {
|
|
162
|
+
export type GetBlockWithTxHashesResponse = BLOCK_WITH_TX_HASHES | PENDING_BLOCK_WITH_TX_HASHES;
|
|
163
|
+
export type GetBlockWithTxs = BLOCK_WITH_TXS | PENDING_BLOCK_WITH_TXS;
|
|
164
|
+
export type GetStorageAtResponse = FELT;
|
|
165
|
+
export type GetTransactionByHashResponse = TXN;
|
|
166
|
+
export type GetTransactionByBlockIdAndIndex = TXN;
|
|
167
|
+
export type GetClassResponse = CONTRACT_CLASS;
|
|
168
|
+
}
|
package/src/types/api/rpc.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { StarknetChainId } from '../../constants';
|
|
2
|
+
import { BlockIdentifier } from '../../provider/utils';
|
|
2
3
|
import { Status } from '../lib';
|
|
4
|
+
import { OPENRPC } from './openrpc';
|
|
3
5
|
|
|
4
6
|
export namespace RPC {
|
|
5
7
|
export type Response = {
|
|
@@ -32,25 +34,9 @@ export namespace RPC {
|
|
|
32
34
|
gas_price: number;
|
|
33
35
|
};
|
|
34
36
|
|
|
35
|
-
export type
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
block_number: number;
|
|
39
|
-
status: Status;
|
|
40
|
-
sequencer: string;
|
|
41
|
-
new_root: string;
|
|
42
|
-
old_root: string;
|
|
43
|
-
accepted_time: number;
|
|
44
|
-
gas_price: string;
|
|
45
|
-
transactions: string[];
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export type GetCodeResponse = {
|
|
49
|
-
bytecode: string[];
|
|
50
|
-
abi: string;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export type GetStorageAtResponse = string;
|
|
37
|
+
export type GetBlockWithTxHashesResponse = OPENRPC.GetBlockWithTxHashesResponse;
|
|
38
|
+
export type GetBlockWithTxs = OPENRPC.GetBlockWithTxs;
|
|
39
|
+
export type GetStorageAtResponse = OPENRPC.GetStorageAtResponse;
|
|
54
40
|
|
|
55
41
|
export type GetTransactionReceiptResponse = {
|
|
56
42
|
txn_hash: string;
|
|
@@ -81,7 +67,8 @@ export namespace RPC {
|
|
|
81
67
|
sender_address?: string;
|
|
82
68
|
}
|
|
83
69
|
|
|
84
|
-
export type
|
|
70
|
+
export type GetTransactionByHashResponse = OPENRPC.GetTransactionByHashResponse;
|
|
71
|
+
export type GetTransactionByBlockIdAndIndex = OPENRPC.GetTransactionByBlockIdAndIndex;
|
|
85
72
|
|
|
86
73
|
export type GetTransactionCountResponse = number;
|
|
87
74
|
|
|
@@ -99,8 +86,8 @@ export namespace RPC {
|
|
|
99
86
|
| boolean;
|
|
100
87
|
|
|
101
88
|
export type EventFilter = {
|
|
102
|
-
fromBlock:
|
|
103
|
-
toBlock:
|
|
89
|
+
fromBlock: BlockIdentifier;
|
|
90
|
+
toBlock: BlockIdentifier;
|
|
104
91
|
address: string;
|
|
105
92
|
keys: string[];
|
|
106
93
|
page_size: number;
|
|
@@ -143,56 +130,46 @@ export namespace RPC {
|
|
|
143
130
|
};
|
|
144
131
|
|
|
145
132
|
export type Methods = {
|
|
146
|
-
|
|
133
|
+
starknet_getBlockWithTxHashes: {
|
|
147
134
|
QUERY: never;
|
|
148
135
|
REQUEST: any[];
|
|
149
|
-
RESPONSE:
|
|
136
|
+
RESPONSE: GetBlockWithTxHashesResponse;
|
|
150
137
|
};
|
|
151
|
-
|
|
138
|
+
starknet_getBlockWithTxs: {
|
|
152
139
|
QUERY: never;
|
|
153
140
|
REQUEST: any[];
|
|
154
|
-
RESPONSE:
|
|
141
|
+
RESPONSE: GetBlockWithTxs;
|
|
155
142
|
};
|
|
156
|
-
|
|
143
|
+
starknet_getNonce: {
|
|
157
144
|
QUERY: never;
|
|
158
145
|
REQUEST: any[];
|
|
159
|
-
RESPONSE:
|
|
146
|
+
RESPONSE: string;
|
|
160
147
|
};
|
|
161
|
-
|
|
148
|
+
starknet_getStorageAt: {
|
|
162
149
|
QUERY: never;
|
|
163
150
|
REQUEST: any[];
|
|
164
|
-
RESPONSE:
|
|
151
|
+
RESPONSE: GetStorageAtResponse;
|
|
165
152
|
};
|
|
166
|
-
|
|
153
|
+
starknet_getTransactionByHash: {
|
|
167
154
|
QUERY: never;
|
|
168
155
|
REQUEST: any[];
|
|
169
|
-
RESPONSE:
|
|
156
|
+
RESPONSE: GetTransactionByHashResponse;
|
|
170
157
|
};
|
|
171
|
-
|
|
158
|
+
starknet_getTransactionByBlockIdAndIndex: {
|
|
172
159
|
QUERY: never;
|
|
173
160
|
REQUEST: any[];
|
|
174
|
-
RESPONSE:
|
|
161
|
+
RESPONSE: GetTransactionByBlockIdAndIndex;
|
|
175
162
|
};
|
|
176
163
|
starknet_getTransactionReceipt: {
|
|
177
164
|
QUERY: never;
|
|
178
165
|
REQUEST: any[];
|
|
179
166
|
RESPONSE: GetTransactionReceiptResponse;
|
|
180
167
|
};
|
|
181
|
-
|
|
182
|
-
QUERY: never;
|
|
183
|
-
REQUEST: any[];
|
|
184
|
-
RESPONSE: GetTransactionCountResponse;
|
|
185
|
-
};
|
|
186
|
-
starknet_getBlockTransactionCountByNumber: {
|
|
168
|
+
starknet_getBlockTransactionCount: {
|
|
187
169
|
QUERY: never;
|
|
188
170
|
REQUEST: any[];
|
|
189
171
|
RESPONSE: GetTransactionCountResponse;
|
|
190
172
|
};
|
|
191
|
-
starknet_getCode: {
|
|
192
|
-
QUERY: never;
|
|
193
|
-
REQUEST: any[];
|
|
194
|
-
RESPONSE: GetCodeResponse;
|
|
195
|
-
};
|
|
196
173
|
starknet_call: {
|
|
197
174
|
QUERY: never;
|
|
198
175
|
REQUEST: any[];
|
package/src/types/provider.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common interface response
|
|
3
|
+
* Intersection (sequencer response ∩ (∪ rpc responses))
|
|
4
|
+
*/
|
|
1
5
|
import BN from 'bn.js';
|
|
2
6
|
|
|
3
7
|
import { Abi, CompressedProgram, EntryPointsByType, RawCalldata, Signature, Status } from './lib';
|
|
4
8
|
|
|
5
9
|
export interface GetBlockResponse {
|
|
6
|
-
|
|
10
|
+
timestamp: number;
|
|
7
11
|
block_hash: string;
|
|
8
12
|
block_number: number;
|
|
9
|
-
gas_price: string;
|
|
10
13
|
new_root: string;
|
|
11
|
-
old_root?: string;
|
|
12
14
|
parent_hash: string;
|
|
13
|
-
sequencer: string;
|
|
14
15
|
status: Status;
|
|
15
16
|
transactions: Array<string>;
|
|
16
|
-
starknet_version?: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface GetCodeResponse {
|
package/src/utils/address.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { arrayify } from '@ethersproject/bytes';
|
|
|
3
3
|
|
|
4
4
|
import { MASK_251, ZERO } from '../constants';
|
|
5
5
|
import { addHexPrefix, removeHexPrefix } from './encode';
|
|
6
|
-
import {
|
|
6
|
+
import { keccakBn } from './hash';
|
|
7
7
|
import { BigNumberish, assertInRange, toBN, toHex } from './number';
|
|
8
8
|
|
|
9
9
|
export function addAddressPadding(address: BigNumberish): string {
|
|
@@ -25,7 +25,7 @@ export function validateAndParseAddress(address: BigNumberish): string {
|
|
|
25
25
|
// from https://github.com/ethers-io/ethers.js/blob/fc1e006575d59792fa97b4efb9ea2f8cca1944cf/packages/address/src.ts/index.ts#L12
|
|
26
26
|
export function getChecksumAddress(address: BigNumberish): string {
|
|
27
27
|
const chars = removeHexPrefix(validateAndParseAddress(address)).toLowerCase().split('');
|
|
28
|
-
const hashed = arrayify(
|
|
28
|
+
const hashed = arrayify(keccakBn(address), { hexPad: 'left' }); // in case the hash is 251 bits (63 chars) we need to pad it to 64 chars without changing the number value ("left")
|
|
29
29
|
|
|
30
30
|
for (let i = 0; i < chars.length; i += 2) {
|
|
31
31
|
if (hashed[i >> 1] >> 4 >= 8) {
|
|
@@ -21,11 +21,13 @@ export const ec = new EC(
|
|
|
21
21
|
})
|
|
22
22
|
);
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
The function _truncateToN in lib/elliptic/ec/index.js does a shift-right of 4 bits
|
|
26
|
-
in some cases. This function does the opposite operation so that
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The function _truncateToN in lib/elliptic/ec/index.js does a shift-right of 4 bits
|
|
26
|
+
* in some cases. This function does the opposite operation so that
|
|
27
|
+
* _truncateToN(fixMessage(msg)) == msg.
|
|
28
|
+
*
|
|
29
|
+
* @param msg
|
|
30
|
+
*/
|
|
29
31
|
function fixMessage(msg: string) {
|
|
30
32
|
const pureHex = msg.replace(/^0x0*/, '');
|
|
31
33
|
|
|
@@ -64,11 +66,12 @@ export function getKeyPairFromPublicKey(publicKey: BigNumberish): KeyPair {
|
|
|
64
66
|
return ec.keyFromPublic(removeHexPrefix(toHex(publicKeyBn)), 'hex');
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
Signs a message using the provided key.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Signs a message using the provided key.
|
|
71
|
+
*
|
|
72
|
+
* @param keyPair should be an KeyPair with a valid private key.
|
|
73
|
+
* @returns an Signature.
|
|
74
|
+
*/
|
|
72
75
|
export function sign(keyPair: KeyPair, msgHash: string): Signature {
|
|
73
76
|
const msgHashBN = toBN(addHexPrefix(msgHash));
|
|
74
77
|
// Verify message hash has valid length.
|
|
@@ -89,12 +92,13 @@ function chunkArray(arr: any[], n: number): any[][] {
|
|
|
89
92
|
.map((_, i) => arr.slice(i * n, i * n + n));
|
|
90
93
|
}
|
|
91
94
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Verifies a message using the provided key.
|
|
97
|
+
*
|
|
98
|
+
* @param keyPair should be an KeyPair with a valid public key.
|
|
99
|
+
* @param sig should be an Signature.
|
|
100
|
+
* @returns true if the verification succeeds.
|
|
101
|
+
*/
|
|
98
102
|
export function verify(keyPair: KeyPair | KeyPair[], msgHash: string, sig: Signature): boolean {
|
|
99
103
|
const keyPairArray = Array.isArray(keyPair) ? keyPair : [keyPair];
|
|
100
104
|
const msgHashBN = toBN(addHexPrefix(msgHash));
|
package/src/utils/hash.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BN from 'bn.js';
|
|
2
2
|
import { keccak256 } from 'ethereum-cryptography/keccak';
|
|
3
|
+
import { hexToBytes } from 'ethereum-cryptography/utils';
|
|
3
4
|
import assert from 'minimalistic-assert';
|
|
4
5
|
|
|
5
6
|
import {
|
|
@@ -13,12 +14,18 @@ import {
|
|
|
13
14
|
} from '../constants';
|
|
14
15
|
import { RawCalldata } from '../types/lib';
|
|
15
16
|
import { ec } from './ellipticCurve';
|
|
16
|
-
import { addHexPrefix, buf2hex, utf8ToArray } from './encode';
|
|
17
|
+
import { addHexPrefix, buf2hex, removeHexPrefix, utf8ToArray } from './encode';
|
|
17
18
|
import { BigNumberish, toBN, toFelt, toHex } from './number';
|
|
18
19
|
|
|
19
20
|
export const transactionVersion = 0;
|
|
20
21
|
export const feeTransactionVersion = toBN(2).pow(toBN(128)).add(toBN(transactionVersion));
|
|
21
22
|
|
|
23
|
+
export function keccakBn(value: BigNumberish): string {
|
|
24
|
+
const hexWithoutPrefix = removeHexPrefix(toHex(toBN(value)));
|
|
25
|
+
const evenHex = hexWithoutPrefix.length % 2 === 0 ? hexWithoutPrefix : `0${hexWithoutPrefix}`;
|
|
26
|
+
return addHexPrefix(buf2hex(keccak256(hexToBytes(evenHex))));
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
function keccakHex(value: string): string {
|
|
23
30
|
return addHexPrefix(buf2hex(keccak256(utf8ToArray(value))));
|
|
24
31
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map RPC Response to common interface response
|
|
3
|
+
* Intersection (sequencer response ∩ (∪ rpc responses))
|
|
4
|
+
*/
|
|
1
5
|
import {
|
|
2
6
|
CallContractResponse,
|
|
3
7
|
DeclareContractResponse,
|
|
@@ -12,33 +16,36 @@ import { RPC } from '../../types/api';
|
|
|
12
16
|
import { toBN } from '../number';
|
|
13
17
|
import { ResponseParser } from '.';
|
|
14
18
|
|
|
19
|
+
type RpcGetBlockResponse = RPC.GetBlockWithTxHashesResponse & {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type GetTransactionByHashResponse = RPC.GetTransactionByHashResponse & {
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
};
|
|
26
|
+
|
|
15
27
|
export class RPCResponseParser extends ResponseParser {
|
|
16
|
-
public parseGetBlockResponse(res:
|
|
28
|
+
public parseGetBlockResponse(res: RpcGetBlockResponse): GetBlockResponse {
|
|
17
29
|
return {
|
|
18
|
-
|
|
30
|
+
timestamp: res.timestamp,
|
|
19
31
|
block_hash: res.block_hash,
|
|
20
32
|
block_number: res.block_number,
|
|
21
|
-
gas_price: res.gas_price,
|
|
22
33
|
new_root: res.new_root,
|
|
23
|
-
old_root: res.old_root,
|
|
24
34
|
parent_hash: res.parent_hash,
|
|
25
|
-
sequencer: res.sequencer,
|
|
26
35
|
status: res.status,
|
|
27
36
|
transactions: res.transactions,
|
|
28
37
|
};
|
|
29
38
|
}
|
|
30
39
|
|
|
31
|
-
public parseGetTransactionResponse(res:
|
|
40
|
+
public parseGetTransactionResponse(res: GetTransactionByHashResponse): GetTransactionResponse {
|
|
32
41
|
return {
|
|
33
42
|
calldata: res.calldata || [],
|
|
34
43
|
contract_address: res.contract_address,
|
|
35
|
-
contract_class: res.contract_class,
|
|
36
44
|
entry_point_selector: res.entry_point_selector,
|
|
37
45
|
max_fee: res.max_fee,
|
|
38
46
|
nonce: res.nonce,
|
|
39
|
-
sender_address: res.sender_address,
|
|
40
47
|
signature: res.signature || [],
|
|
41
|
-
transaction_hash: res.
|
|
48
|
+
transaction_hash: res.transaction_hash,
|
|
42
49
|
version: res.version,
|
|
43
50
|
};
|
|
44
51
|
}
|
|
@@ -57,10 +64,6 @@ export class RPCResponseParser extends ResponseParser {
|
|
|
57
64
|
};
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
public parseGetCodeResponse(res: RPC.GetCodeResponse): RPC.GetCodeResponse {
|
|
61
|
-
return res;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
67
|
public parseFeeEstimateResponse(res: RPC.EstimateFeeResponse): EstimateFeeResponse {
|
|
65
68
|
return {
|
|
66
69
|
overall_fee: toBN(res.overall_fee),
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map Sequencer Response to common interface response
|
|
3
|
+
* Intersection (sequencer response ∩ (∪ rpc responses))
|
|
4
|
+
*/
|
|
1
5
|
import {
|
|
2
6
|
CallContractResponse,
|
|
3
7
|
DeclareContractResponse,
|
|
@@ -15,14 +19,11 @@ import { ResponseParser } from '.';
|
|
|
15
19
|
export class SequencerAPIResponseParser extends ResponseParser {
|
|
16
20
|
public parseGetBlockResponse(res: Sequencer.GetBlockResponse): GetBlockResponse {
|
|
17
21
|
return {
|
|
18
|
-
|
|
22
|
+
timestamp: res.timestamp,
|
|
19
23
|
block_hash: res.block_hash,
|
|
20
24
|
block_number: res.block_number,
|
|
21
|
-
gas_price: res.gas_price,
|
|
22
25
|
new_root: res.state_root,
|
|
23
|
-
old_root: undefined,
|
|
24
26
|
parent_hash: res.parent_block_hash,
|
|
25
|
-
sequencer: res.sequencer_address,
|
|
26
27
|
status: res.status,
|
|
27
28
|
transactions: Object.values(res.transactions)
|
|
28
29
|
.map((value) => 'transaction_hash' in value && value.transaction_hash)
|
|
@@ -70,10 +71,6 @@ export class SequencerAPIResponseParser extends ResponseParser {
|
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
public parseGetCodeResponse(res: Sequencer.GetCodeResponse): Sequencer.GetCodeResponse {
|
|
74
|
-
return res;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
74
|
public parseFeeEstimateResponse(res: Sequencer.EstimateFeeResponse): EstimateFeeResponse {
|
|
78
75
|
if ('overall_fee' in res) {
|
|
79
76
|
let gasInfo = {};
|
package/src/utils/url.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import urljoin from 'url-join';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Inspired from https://github.com/segmentio/is-url
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* RegExps.
|
|
9
|
+
* A URL must match #1 and then at least one of #2/#3.
|
|
10
|
+
* Use two levels of REs to avoid REDOS.
|
|
11
|
+
*/
|
|
12
|
+
const protocolAndDomainRE = /^(?:\w+:)?\/\/(\S+)$/;
|
|
13
|
+
|
|
14
|
+
const localhostDomainRE = /^localhost[:?\d]*(?:[^:?\d]\S*)?$/;
|
|
15
|
+
const nonLocalhostDomainRE = /^[^\s.]+\.\S{2,}$/;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Loosely validate a URL `string`.
|
|
19
|
+
* @param {String} s
|
|
20
|
+
* @return {Boolean}
|
|
21
|
+
*/
|
|
22
|
+
export function isUrl(s?: string): boolean {
|
|
23
|
+
if (!s) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (typeof s !== 'string') {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const match = s.match(protocolAndDomainRE);
|
|
32
|
+
if (!match) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const everythingAfterProtocol = match[1];
|
|
37
|
+
if (!everythingAfterProtocol) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
localhostDomainRE.test(everythingAfterProtocol) ||
|
|
43
|
+
nonLocalhostDomainRE.test(everythingAfterProtocol)
|
|
44
|
+
) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function buildUrl(baseUrl: string, defaultPath: string, urlOrPath?: string) {
|
|
52
|
+
return isUrl(urlOrPath) ? urlOrPath! : urljoin(baseUrl, urlOrPath ?? defaultPath);
|
|
53
|
+
}
|