starknet 4.5.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +3 -1
- package/__tests__/account.test.ts +2 -5
- package/__tests__/contract.test.ts +0 -1
- package/__tests__/defaultProvider.test.ts +16 -10
- package/__tests__/rpcProvider.test.ts +107 -12
- package/__tests__/sequencerProvider.test.ts +10 -8
- package/__tests__/utils/ellipticalCurve.test.ts +7 -8
- package/__tests__/utils/utils.test.ts +17 -0
- package/account/default.d.ts +3 -2
- package/account/default.js +22 -29
- package/account/interface.d.ts +2 -1
- package/contract/contractFactory.d.ts +1 -2
- package/contract/default.d.ts +2 -2
- package/contract/default.js +7 -3
- package/dist/account/default.d.ts +3 -2
- package/dist/account/default.js +22 -29
- package/dist/account/interface.d.ts +2 -1
- package/dist/contract/contractFactory.d.ts +1 -2
- package/dist/contract/default.d.ts +2 -2
- package/dist/contract/default.js +7 -3
- package/dist/provider/default.d.ts +4 -3
- package/dist/provider/default.js +9 -3
- package/dist/provider/interface.d.ts +10 -3
- package/dist/provider/rpc.d.ts +24 -12
- package/dist/provider/rpc.js +167 -105
- package/dist/provider/sequencer.d.ts +4 -3
- package/dist/provider/sequencer.js +16 -7
- package/dist/provider/utils.d.ts +11 -35
- package/dist/provider/utils.js +52 -63
- package/dist/signer/default.d.ts +2 -2
- package/dist/signer/default.js +2 -2
- package/dist/signer/interface.d.ts +2 -2
- package/dist/types/api/openrpc.d.ts +395 -45
- package/dist/types/api/openrpc.js +21 -3
- package/dist/types/api/rpc.d.ts +34 -191
- package/dist/types/api/sequencer.d.ts +15 -4
- package/dist/types/lib.d.ts +10 -4
- package/dist/types/provider.d.ts +3 -2
- package/dist/utils/hash.d.ts +2 -2
- package/dist/utils/hash.js +5 -5
- package/dist/utils/responseParser/rpc.d.ts +6 -6
- package/dist/utils/responseParser/rpc.js +3 -39
- package/package.json +1 -1
- package/provider/default.d.ts +4 -3
- package/provider/default.js +9 -3
- package/provider/interface.d.ts +10 -3
- package/provider/rpc.d.ts +24 -12
- package/provider/rpc.js +167 -105
- package/provider/sequencer.d.ts +4 -3
- package/provider/sequencer.js +16 -7
- package/provider/utils.d.ts +11 -35
- package/provider/utils.js +52 -63
- package/signer/default.d.ts +2 -2
- package/signer/default.js +2 -2
- package/signer/interface.d.ts +2 -2
- package/src/account/default.ts +21 -20
- package/src/account/interface.ts +2 -1
- package/src/contract/contractFactory.ts +1 -2
- package/src/contract/default.ts +16 -8
- package/src/provider/default.ts +12 -5
- package/src/provider/interface.ts +15 -4
- package/src/provider/rpc.ts +152 -102
- package/src/provider/sequencer.ts +19 -10
- package/src/provider/utils.ts +43 -56
- package/src/signer/default.ts +8 -8
- package/src/signer/interface.ts +2 -2
- package/src/types/api/openrpc.ts +378 -53
- package/src/types/api/rpc.ts +33 -211
- package/src/types/api/sequencer.ts +17 -4
- package/src/types/lib.ts +7 -5
- package/src/types/provider.ts +3 -2
- package/src/utils/hash.ts +7 -6
- package/src/utils/responseParser/rpc.ts +13 -27
- package/types/api/openrpc.d.ts +395 -45
- package/types/api/openrpc.js +21 -3
- package/types/api/rpc.d.ts +34 -191
- package/types/api/sequencer.d.ts +15 -4
- package/types/lib.d.ts +10 -4
- package/types/provider.d.ts +3 -2
- package/utils/hash.d.ts +2 -2
- package/utils/hash.js +5 -5
- package/utils/responseParser/rpc.d.ts +6 -6
- package/utils/responseParser/rpc.js +3 -39
- package/www/docs/API/account.md +3 -3
- package/www/docs/API/contract.md +2 -2
- package/www/docs/API/provider.md +6 -0
- package/www/docs/API/utils.md +2 -2
package/src/provider/rpc.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
GetTransactionReceiptResponse,
|
|
13
13
|
GetTransactionResponse,
|
|
14
14
|
Invocation,
|
|
15
|
-
|
|
15
|
+
InvocationsDetailsWithNonce,
|
|
16
16
|
InvokeFunctionResponse,
|
|
17
17
|
} from '../types';
|
|
18
18
|
import { RPC } from '../types/api';
|
|
@@ -29,90 +29,126 @@ import { parseCalldata, parseContract, wait } from '../utils/provider';
|
|
|
29
29
|
import { RPCResponseParser } from '../utils/responseParser/rpc';
|
|
30
30
|
import { randomAddress } from '../utils/stark';
|
|
31
31
|
import { ProviderInterface } from './interface';
|
|
32
|
-
import {
|
|
32
|
+
import { Block, BlockIdentifier } from './utils';
|
|
33
33
|
|
|
34
|
-
export type RpcProviderOptions = {
|
|
34
|
+
export type RpcProviderOptions = {
|
|
35
|
+
nodeUrl: string;
|
|
36
|
+
retries?: number;
|
|
37
|
+
};
|
|
35
38
|
|
|
36
39
|
export class RpcProvider implements ProviderInterface {
|
|
37
40
|
public nodeUrl: string;
|
|
38
41
|
|
|
42
|
+
// from interface
|
|
39
43
|
public chainId!: StarknetChainId;
|
|
40
44
|
|
|
41
45
|
private responseParser = new RPCResponseParser();
|
|
42
46
|
|
|
47
|
+
private retries: number;
|
|
48
|
+
|
|
43
49
|
constructor(optionsOrProvider: RpcProviderOptions) {
|
|
44
|
-
const { nodeUrl } = optionsOrProvider;
|
|
50
|
+
const { nodeUrl, retries } = optionsOrProvider;
|
|
45
51
|
this.nodeUrl = nodeUrl;
|
|
52
|
+
this.retries = retries || 200;
|
|
46
53
|
|
|
47
54
|
this.getChainId().then((chainId) => {
|
|
48
55
|
this.chainId = chainId;
|
|
49
56
|
});
|
|
50
57
|
}
|
|
51
58
|
|
|
59
|
+
public fetch(method: any, params: any): Promise<any> {
|
|
60
|
+
return fetch(this.nodeUrl, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
body: stringify({ method, jsonrpc: '2.0', params, id: 0 }),
|
|
63
|
+
headers: { 'Content-Type': 'application/json' },
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
protected errorHandler(error: any) {
|
|
68
|
+
if (error) {
|
|
69
|
+
const { code, message } = error;
|
|
70
|
+
throw new Error(`${code}: ${message}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
52
74
|
protected async fetchEndpoint<T extends keyof RPC.Methods>(
|
|
53
75
|
method: T,
|
|
54
|
-
|
|
55
|
-
): Promise<RPC.Methods[T]['
|
|
56
|
-
const requestData = {
|
|
57
|
-
method,
|
|
58
|
-
jsonrpc: '2.0',
|
|
59
|
-
params: request,
|
|
60
|
-
id: 0,
|
|
61
|
-
};
|
|
62
|
-
|
|
76
|
+
params?: RPC.Methods[T]['params']
|
|
77
|
+
): Promise<RPC.Methods[T]['result']> {
|
|
63
78
|
try {
|
|
64
|
-
const rawResult = await fetch(
|
|
65
|
-
method: 'POST',
|
|
66
|
-
body: stringify(requestData),
|
|
67
|
-
headers: {
|
|
68
|
-
'Content-Type': 'application/json',
|
|
69
|
-
},
|
|
70
|
-
});
|
|
79
|
+
const rawResult = await this.fetch(method, params);
|
|
71
80
|
const { error, result } = await rawResult.json();
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
throw new Error(`${code}: ${message}`);
|
|
75
|
-
} else {
|
|
76
|
-
return result as RPC.Methods[T]['RESPONSE'];
|
|
77
|
-
}
|
|
81
|
+
this.errorHandler(error);
|
|
82
|
+
return result as RPC.Methods[T]['result'];
|
|
78
83
|
} catch (error: any) {
|
|
79
|
-
|
|
80
|
-
if (data?.message) {
|
|
81
|
-
throw new Error(`${data.code}: ${data.message}`);
|
|
82
|
-
}
|
|
84
|
+
this.errorHandler(error?.response?.data);
|
|
83
85
|
throw error;
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
|
|
89
|
+
// Methods from Interface
|
|
90
|
+
public async getChainId(): Promise<any> {
|
|
88
91
|
return this.fetchEndpoint('starknet_chainId');
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
//
|
|
94
|
+
// Methods from Interface
|
|
92
95
|
public async getBlock(blockIdentifier: BlockIdentifier = 'pending'): Promise<GetBlockResponse> {
|
|
93
96
|
return this.getBlockWithTxHashes(blockIdentifier).then(
|
|
94
97
|
this.responseParser.parseGetBlockResponse
|
|
95
98
|
);
|
|
96
99
|
}
|
|
97
100
|
|
|
101
|
+
public async getBlockHashAndNumber(): Promise<RPC.BlockHashAndNumber> {
|
|
102
|
+
return this.fetchEndpoint('starknet_blockHashAndNumber');
|
|
103
|
+
}
|
|
104
|
+
|
|
98
105
|
public async getBlockWithTxHashes(
|
|
99
106
|
blockIdentifier: BlockIdentifier = 'pending'
|
|
100
107
|
): Promise<RPC.GetBlockWithTxHashesResponse> {
|
|
101
|
-
const
|
|
102
|
-
return this.fetchEndpoint('starknet_getBlockWithTxHashes',
|
|
103
|
-
blockIdentifierGetter.getIdentifier(),
|
|
104
|
-
]);
|
|
108
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
109
|
+
return this.fetchEndpoint('starknet_getBlockWithTxHashes', { block_id });
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
public async getBlockWithTxs(
|
|
108
113
|
blockIdentifier: BlockIdentifier = 'pending'
|
|
109
114
|
): Promise<RPC.GetBlockWithTxs> {
|
|
110
|
-
const
|
|
111
|
-
return this.fetchEndpoint('starknet_getBlockWithTxs',
|
|
115
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
116
|
+
return this.fetchEndpoint('starknet_getBlockWithTxs', { block_id });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public async getClassHashAt(
|
|
120
|
+
blockIdentifier: BlockIdentifier,
|
|
121
|
+
contractAddress: RPC.ContractAddress
|
|
122
|
+
): Promise<RPC.Felt> {
|
|
123
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
124
|
+
return this.fetchEndpoint('starknet_getClassHashAt', {
|
|
125
|
+
block_id,
|
|
126
|
+
contract_address: contractAddress,
|
|
127
|
+
});
|
|
112
128
|
}
|
|
113
129
|
|
|
114
|
-
public async getNonce(
|
|
115
|
-
|
|
130
|
+
public async getNonce(
|
|
131
|
+
contractAddress: string,
|
|
132
|
+
blockIdentifier: BlockIdentifier = 'pending'
|
|
133
|
+
): Promise<RPC.Nonce> {
|
|
134
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
135
|
+
return this.fetchEndpoint('starknet_getNonce', {
|
|
136
|
+
contract_address: contractAddress,
|
|
137
|
+
block_id,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public async getPendingTransactions(): Promise<RPC.PendingTransactions> {
|
|
142
|
+
return this.fetchEndpoint('starknet_pendingTransactions');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public async getProtocolVersion(): Promise<Error> {
|
|
146
|
+
throw new Error('Pathfinder does not implement this rpc 0.1.0 method');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public async getStateUpdate(blockIdentifier: BlockIdentifier): Promise<RPC.StateUpdate> {
|
|
150
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
151
|
+
return this.fetchEndpoint('starknet_getStateUpdate', { block_id });
|
|
116
152
|
}
|
|
117
153
|
|
|
118
154
|
public async getStorageAt(
|
|
@@ -121,61 +157,75 @@ export class RpcProvider implements ProviderInterface {
|
|
|
121
157
|
blockIdentifier: BlockIdentifier = 'pending'
|
|
122
158
|
): Promise<BigNumberish> {
|
|
123
159
|
const parsedKey = toHex(toBN(key));
|
|
124
|
-
const
|
|
125
|
-
return this.fetchEndpoint('starknet_getStorageAt',
|
|
126
|
-
contractAddress,
|
|
127
|
-
parsedKey,
|
|
128
|
-
|
|
129
|
-
|
|
160
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
161
|
+
return this.fetchEndpoint('starknet_getStorageAt', {
|
|
162
|
+
contract_address: contractAddress,
|
|
163
|
+
key: parsedKey,
|
|
164
|
+
block_id,
|
|
165
|
+
});
|
|
130
166
|
}
|
|
131
167
|
|
|
132
|
-
//
|
|
133
|
-
public async getTransaction(txHash:
|
|
168
|
+
// Methods from Interface
|
|
169
|
+
public async getTransaction(txHash: string): Promise<GetTransactionResponse> {
|
|
134
170
|
return this.getTransactionByHash(txHash).then(this.responseParser.parseGetTransactionResponse);
|
|
135
171
|
}
|
|
136
172
|
|
|
137
|
-
public async getTransactionByHash(
|
|
138
|
-
|
|
139
|
-
): Promise<RPC.GetTransactionByHashResponse> {
|
|
140
|
-
return this.fetchEndpoint('starknet_getTransactionByHash', [txHash]);
|
|
173
|
+
public async getTransactionByHash(txHash: string): Promise<RPC.GetTransactionByHashResponse> {
|
|
174
|
+
return this.fetchEndpoint('starknet_getTransactionByHash', { transaction_hash: txHash });
|
|
141
175
|
}
|
|
142
176
|
|
|
143
177
|
public async getTransactionByBlockIdAndIndex(
|
|
144
178
|
blockIdentifier: BlockIdentifier,
|
|
145
179
|
index: number
|
|
146
180
|
): Promise<RPC.GetTransactionByBlockIdAndIndex> {
|
|
147
|
-
|
|
181
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
182
|
+
return this.fetchEndpoint('starknet_getTransactionByBlockIdAndIndex', { block_id, index });
|
|
148
183
|
}
|
|
149
184
|
|
|
150
|
-
public async getTransactionReceipt(txHash:
|
|
151
|
-
return this.fetchEndpoint('starknet_getTransactionReceipt',
|
|
185
|
+
public async getTransactionReceipt(txHash: string): Promise<GetTransactionReceiptResponse> {
|
|
186
|
+
return this.fetchEndpoint('starknet_getTransactionReceipt', { transaction_hash: txHash }).then(
|
|
152
187
|
this.responseParser.parseGetTransactionReceiptResponse
|
|
153
188
|
);
|
|
154
189
|
}
|
|
155
190
|
|
|
156
|
-
public async
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
191
|
+
public async getClass(classHash: RPC.Felt): Promise<RPC.ContractClass> {
|
|
192
|
+
return this.fetchEndpoint('starknet_getClass', { class_hash: classHash });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
public async getClassAt(
|
|
196
|
+
contractAddress: string,
|
|
197
|
+
blockIdentifier: BlockIdentifier
|
|
198
|
+
): Promise<RPC.ContractClass> {
|
|
199
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
200
|
+
return this.fetchEndpoint('starknet_getClassAt', {
|
|
201
|
+
block_id,
|
|
202
|
+
contract_address: contractAddress,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public async getCode(
|
|
207
|
+
_contractAddress: string,
|
|
208
|
+
_blockIdentifier?: BlockIdentifier
|
|
209
|
+
): Promise<GetCodeResponse> {
|
|
210
|
+
throw new Error('RPC 0.1.0 does not implement getCode function');
|
|
162
211
|
}
|
|
163
212
|
|
|
164
213
|
public async getEstimateFee(
|
|
165
214
|
invocation: Invocation,
|
|
166
|
-
|
|
167
|
-
|
|
215
|
+
invocationDetails: InvocationsDetailsWithNonce,
|
|
216
|
+
blockIdentifier: BlockIdentifier = 'pending'
|
|
168
217
|
): Promise<EstimateFeeResponse> {
|
|
169
|
-
|
|
170
|
-
|
|
218
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
219
|
+
return this.fetchEndpoint('starknet_estimateFee', {
|
|
220
|
+
request: {
|
|
171
221
|
contract_address: invocation.contractAddress,
|
|
172
|
-
entry_point_selector: getSelectorFromName(invocation.entrypoint),
|
|
173
222
|
calldata: parseCalldata(invocation.calldata),
|
|
174
223
|
signature: bigNumberishArrayToHexadecimalStringArray(invocation.signature || []),
|
|
175
224
|
version: toHex(toBN(invocationDetails?.version || 0)),
|
|
225
|
+
max_fee: toHex(toBN(invocationDetails?.maxFee || 0)),
|
|
176
226
|
},
|
|
177
|
-
|
|
178
|
-
|
|
227
|
+
block_id,
|
|
228
|
+
}).then(this.responseParser.parseFeeEstimateResponse);
|
|
179
229
|
}
|
|
180
230
|
|
|
181
231
|
public async declareContract({
|
|
@@ -184,14 +234,14 @@ export class RpcProvider implements ProviderInterface {
|
|
|
184
234
|
}: DeclareContractPayload): Promise<DeclareContractResponse> {
|
|
185
235
|
const contractDefinition = parseContract(contract);
|
|
186
236
|
|
|
187
|
-
return this.fetchEndpoint('starknet_addDeclareTransaction',
|
|
188
|
-
{
|
|
237
|
+
return this.fetchEndpoint('starknet_addDeclareTransaction', {
|
|
238
|
+
contract_class: {
|
|
189
239
|
program: contractDefinition.program,
|
|
190
240
|
entry_points_by_type: contractDefinition.entry_points_by_type,
|
|
191
241
|
abi: contractDefinition.abi, // rpc 2.0
|
|
192
242
|
},
|
|
193
|
-
toHex(toBN(version || 0)),
|
|
194
|
-
|
|
243
|
+
version: toHex(toBN(version || 0)),
|
|
244
|
+
});
|
|
195
245
|
}
|
|
196
246
|
|
|
197
247
|
public async deployContract({
|
|
@@ -201,59 +251,61 @@ export class RpcProvider implements ProviderInterface {
|
|
|
201
251
|
}: DeployContractPayload): Promise<DeployContractResponse> {
|
|
202
252
|
const contractDefinition = parseContract(contract);
|
|
203
253
|
|
|
204
|
-
return this.fetchEndpoint('starknet_addDeployTransaction',
|
|
205
|
-
addressSalt ?? randomAddress(),
|
|
206
|
-
bigNumberishArrayToHexadecimalStringArray(constructorCalldata ?? []),
|
|
207
|
-
{
|
|
254
|
+
return this.fetchEndpoint('starknet_addDeployTransaction', {
|
|
255
|
+
contract_address_salt: addressSalt ?? randomAddress(),
|
|
256
|
+
constructor_calldata: bigNumberishArrayToHexadecimalStringArray(constructorCalldata ?? []),
|
|
257
|
+
contract_definition: {
|
|
208
258
|
program: contractDefinition.program,
|
|
209
259
|
entry_points_by_type: contractDefinition.entry_points_by_type,
|
|
210
260
|
abi: contractDefinition.abi, // rpc 2.0
|
|
211
261
|
},
|
|
212
|
-
|
|
262
|
+
});
|
|
213
263
|
}
|
|
214
264
|
|
|
215
265
|
public async invokeFunction(
|
|
216
266
|
functionInvocation: Invocation,
|
|
217
|
-
details:
|
|
267
|
+
details: InvocationsDetailsWithNonce
|
|
218
268
|
): Promise<InvokeFunctionResponse> {
|
|
219
|
-
return this.fetchEndpoint('starknet_addInvokeTransaction',
|
|
220
|
-
{
|
|
269
|
+
return this.fetchEndpoint('starknet_addInvokeTransaction', {
|
|
270
|
+
function_invocation: {
|
|
221
271
|
contract_address: functionInvocation.contractAddress,
|
|
222
|
-
entry_point_selector: getSelectorFromName(functionInvocation.entrypoint),
|
|
223
272
|
calldata: parseCalldata(functionInvocation.calldata),
|
|
224
273
|
},
|
|
225
|
-
bigNumberishArrayToHexadecimalStringArray(functionInvocation.signature || []),
|
|
226
|
-
toHex(toBN(details.maxFee || 0)),
|
|
227
|
-
toHex(toBN(details.version || 0)),
|
|
228
|
-
|
|
274
|
+
signature: bigNumberishArrayToHexadecimalStringArray(functionInvocation.signature || []),
|
|
275
|
+
max_fee: toHex(toBN(details.maxFee || 0)),
|
|
276
|
+
version: toHex(toBN(details.version || 0)),
|
|
277
|
+
});
|
|
229
278
|
}
|
|
230
279
|
|
|
280
|
+
// Methods from Interface
|
|
231
281
|
public async callContract(
|
|
232
282
|
call: Call,
|
|
233
283
|
blockIdentifier: BlockIdentifier = 'pending'
|
|
234
284
|
): Promise<CallContractResponse> {
|
|
235
|
-
const
|
|
236
|
-
|
|
285
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
286
|
+
const result = await this.fetchEndpoint('starknet_call', {
|
|
287
|
+
request: {
|
|
237
288
|
contract_address: call.contractAddress,
|
|
238
289
|
entry_point_selector: getSelectorFromName(call.entrypoint),
|
|
239
290
|
calldata: parseCalldata(call.calldata),
|
|
240
291
|
},
|
|
241
|
-
|
|
242
|
-
|
|
292
|
+
block_id,
|
|
293
|
+
});
|
|
243
294
|
|
|
244
295
|
return this.responseParser.parseCallContractResponse(result);
|
|
245
296
|
}
|
|
246
297
|
|
|
247
|
-
public async
|
|
248
|
-
|
|
249
|
-
_blockIdentifier?: BlockIdentifier
|
|
250
|
-
): Promise<GetCodeResponse> {
|
|
251
|
-
throw new Error('RPC 0.1.0 does not implement getCode function');
|
|
298
|
+
public async traceTransaction(transactionHash: RPC.TransactionHash): Promise<RPC.Trace> {
|
|
299
|
+
return this.fetchEndpoint('starknet_traceTransaction', { transaction_hash: transactionHash });
|
|
252
300
|
}
|
|
253
301
|
|
|
254
|
-
public async
|
|
302
|
+
public async traceBlockTransactions(blockHash: RPC.BlockHash): Promise<RPC.Traces> {
|
|
303
|
+
return this.fetchEndpoint('starknet_traceBlockTransactions', { block_hash: blockHash });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
public async waitForTransaction(txHash: string, retryInterval: number = 8000) {
|
|
307
|
+
let { retries } = this;
|
|
255
308
|
let onchain = false;
|
|
256
|
-
let retries = 100;
|
|
257
309
|
|
|
258
310
|
while (!onchain) {
|
|
259
311
|
const successStates = ['ACCEPTED_ON_L1', 'ACCEPTED_ON_L2', 'PENDING'];
|
|
@@ -279,7 +331,7 @@ export class RpcProvider implements ProviderInterface {
|
|
|
279
331
|
}
|
|
280
332
|
|
|
281
333
|
if (retries === 0) {
|
|
282
|
-
throw
|
|
334
|
+
throw new Error('waitForTransaction timedout with retries');
|
|
283
335
|
}
|
|
284
336
|
}
|
|
285
337
|
|
|
@@ -299,10 +351,8 @@ export class RpcProvider implements ProviderInterface {
|
|
|
299
351
|
public async getTransactionCount(
|
|
300
352
|
blockIdentifier: BlockIdentifier
|
|
301
353
|
): Promise<RPC.GetTransactionCountResponse> {
|
|
302
|
-
const
|
|
303
|
-
return this.fetchEndpoint('starknet_getBlockTransactionCount',
|
|
304
|
-
blockIdentifierGetter.getIdentifier(),
|
|
305
|
-
]);
|
|
354
|
+
const block_id = new Block(blockIdentifier).identifier;
|
|
355
|
+
return this.fetchEndpoint('starknet_getBlockTransactionCount', { block_id });
|
|
306
356
|
}
|
|
307
357
|
|
|
308
358
|
/**
|
|
@@ -332,6 +382,6 @@ export class RpcProvider implements ProviderInterface {
|
|
|
332
382
|
* @returns events and the pagination of the events
|
|
333
383
|
*/
|
|
334
384
|
public async getEvents(eventFilter: RPC.EventFilter): Promise<RPC.GetEventsResponse> {
|
|
335
|
-
return this.fetchEndpoint('starknet_getEvents',
|
|
385
|
+
return this.fetchEndpoint('starknet_getEvents', { filter: eventFilter });
|
|
336
386
|
}
|
|
337
387
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
GetTransactionReceiptResponse,
|
|
15
15
|
GetTransactionResponse,
|
|
16
16
|
Invocation,
|
|
17
|
-
|
|
17
|
+
InvocationsDetailsWithNonce,
|
|
18
18
|
InvokeFunctionResponse,
|
|
19
19
|
} from '../types';
|
|
20
20
|
import {
|
|
@@ -33,7 +33,7 @@ import { randomAddress } from '../utils/stark';
|
|
|
33
33
|
import { buildUrl } from '../utils/url';
|
|
34
34
|
import { GatewayError, HttpError } from './errors';
|
|
35
35
|
import { ProviderInterface } from './interface';
|
|
36
|
-
import {
|
|
36
|
+
import { Block, BlockIdentifier } from './utils';
|
|
37
37
|
|
|
38
38
|
type NetworkName = 'mainnet-alpha' | 'goerli-alpha';
|
|
39
39
|
|
|
@@ -129,7 +129,8 @@ export class SequencerProvider implements ProviderInterface {
|
|
|
129
129
|
const queryString = Object.entries(query)
|
|
130
130
|
.map(([key, value]) => {
|
|
131
131
|
if (key === 'blockIdentifier') {
|
|
132
|
-
|
|
132
|
+
const block = new Block(value);
|
|
133
|
+
return `${block.queryIdentifier}`;
|
|
133
134
|
}
|
|
134
135
|
return `${key}=${value}`;
|
|
135
136
|
})
|
|
@@ -233,6 +234,13 @@ export class SequencerProvider implements ProviderInterface {
|
|
|
233
234
|
);
|
|
234
235
|
}
|
|
235
236
|
|
|
237
|
+
public async getNonce(
|
|
238
|
+
contractAddress: string,
|
|
239
|
+
blockIdentifier: BlockIdentifier = 'pending'
|
|
240
|
+
): Promise<BigNumberish> {
|
|
241
|
+
return this.fetchEndpoint('get_nonce', { contractAddress, blockIdentifier });
|
|
242
|
+
}
|
|
243
|
+
|
|
236
244
|
public async getStorageAt(
|
|
237
245
|
contractAddress: string,
|
|
238
246
|
key: BigNumberish,
|
|
@@ -271,16 +279,16 @@ export class SequencerProvider implements ProviderInterface {
|
|
|
271
279
|
|
|
272
280
|
public async invokeFunction(
|
|
273
281
|
functionInvocation: Invocation,
|
|
274
|
-
details:
|
|
282
|
+
details: InvocationsDetailsWithNonce
|
|
275
283
|
): Promise<InvokeFunctionResponse> {
|
|
276
284
|
return this.fetchEndpoint('add_transaction', undefined, {
|
|
277
285
|
type: 'INVOKE_FUNCTION',
|
|
278
286
|
contract_address: functionInvocation.contractAddress,
|
|
279
|
-
entry_point_selector: getSelectorFromName(functionInvocation.entrypoint),
|
|
280
287
|
calldata: bigNumberishArrayToDecimalStringArray(functionInvocation.calldata ?? []),
|
|
281
288
|
signature: bigNumberishArrayToDecimalStringArray(functionInvocation.signature ?? []),
|
|
289
|
+
nonce: toHex(toBN(details.nonce)),
|
|
282
290
|
max_fee: toHex(toBN(details.maxFee || 0)),
|
|
283
|
-
version: toHex(toBN(details.version ||
|
|
291
|
+
version: toHex(toBN(details.version || 1)),
|
|
284
292
|
}).then(this.responseParser.parseInvokeFunctionResponse);
|
|
285
293
|
}
|
|
286
294
|
|
|
@@ -315,18 +323,19 @@ export class SequencerProvider implements ProviderInterface {
|
|
|
315
323
|
|
|
316
324
|
public async getEstimateFee(
|
|
317
325
|
invocation: Invocation,
|
|
318
|
-
|
|
319
|
-
|
|
326
|
+
invocationDetails: InvocationsDetailsWithNonce,
|
|
327
|
+
blockIdentifier: BlockIdentifier = 'pending'
|
|
320
328
|
): Promise<EstimateFeeResponse> {
|
|
321
329
|
return this.fetchEndpoint(
|
|
322
330
|
'estimate_fee',
|
|
323
331
|
{ blockIdentifier },
|
|
324
332
|
{
|
|
333
|
+
type: 'INVOKE_FUNCTION',
|
|
325
334
|
contract_address: invocation.contractAddress,
|
|
326
|
-
entry_point_selector: getSelectorFromName(invocation.entrypoint),
|
|
327
335
|
calldata: invocation.calldata ?? [],
|
|
328
336
|
signature: bigNumberishArrayToDecimalStringArray(invocation.signature || []),
|
|
329
|
-
version: toHex(toBN(invocationDetails?.version ||
|
|
337
|
+
version: toHex(toBN(invocationDetails?.version || 1)),
|
|
338
|
+
nonce: toHex(toBN(invocationDetails.nonce)),
|
|
330
339
|
}
|
|
331
340
|
).then(this.responseParser.parseFeeEstimateResponse);
|
|
332
341
|
}
|
package/src/provider/utils.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-classes-per-file */
|
|
1
2
|
import type { BlockNumber } from '../types';
|
|
2
3
|
import { BigNumberish, isHex, toBN, toHex } from '../utils/number';
|
|
3
4
|
|
|
@@ -33,73 +34,59 @@ export function txIdentifier(txHash?: BigNumberish, txId?: BigNumberish): string
|
|
|
33
34
|
// null appends nothing to the request url
|
|
34
35
|
|
|
35
36
|
export type BlockIdentifier = BlockNumber | BigNumberish;
|
|
36
|
-
type BlockIdentifierObject =
|
|
37
|
-
| { type: 'BLOCK_NUMBER'; data: BlockNumber }
|
|
38
|
-
| { type: 'BLOCK_HASH'; data: BigNumberish };
|
|
39
37
|
|
|
40
|
-
export class
|
|
41
|
-
|
|
38
|
+
export class Block {
|
|
39
|
+
hash: BlockIdentifier = null;
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
number: BlockIdentifier = null;
|
|
42
|
+
|
|
43
|
+
tag: BlockIdentifier = null;
|
|
44
|
+
|
|
45
|
+
private setIdentifier: (_identifier: BlockIdentifier) => void;
|
|
46
|
+
|
|
47
|
+
constructor(_identifier: BlockIdentifier) {
|
|
48
|
+
this.setIdentifier = function (__identifier: BlockIdentifier) {
|
|
49
|
+
if (typeof __identifier === 'string' && isHex(__identifier)) {
|
|
50
|
+
this.hash = __identifier;
|
|
51
|
+
} else if (typeof __identifier === 'number') {
|
|
52
|
+
this.number = __identifier;
|
|
53
|
+
} else {
|
|
54
|
+
this.tag = __identifier;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
this.setIdentifier(_identifier);
|
|
45
59
|
}
|
|
46
60
|
|
|
47
|
-
|
|
48
|
-
if (
|
|
49
|
-
return {
|
|
61
|
+
get queryIdentifier(): any {
|
|
62
|
+
if (this.number !== null) {
|
|
63
|
+
return `blockNumber=${this.number}`;
|
|
50
64
|
}
|
|
51
65
|
|
|
52
|
-
if (
|
|
53
|
-
return {
|
|
66
|
+
if (this.hash !== null) {
|
|
67
|
+
return `blockHash=${this.hash}`;
|
|
54
68
|
}
|
|
55
69
|
|
|
56
|
-
return this.
|
|
70
|
+
return `blockNumber=${this.tag}`;
|
|
57
71
|
}
|
|
58
|
-
}
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* @returns block identifier object
|
|
65
|
-
*/
|
|
66
|
-
export function getBlockIdentifier(blockIdentifier: BlockIdentifier): BlockIdentifierObject {
|
|
67
|
-
if (blockIdentifier === null || blockIdentifier === 'latest') {
|
|
68
|
-
return { type: 'BLOCK_NUMBER', data: 'latest' }; // default to latest block
|
|
69
|
-
}
|
|
70
|
-
if (blockIdentifier === 'pending') {
|
|
71
|
-
return { type: 'BLOCK_NUMBER', data: 'pending' };
|
|
72
|
-
}
|
|
73
|
-
if (typeof blockIdentifier === 'number' || typeof blockIdentifier === 'bigint') {
|
|
74
|
-
return { type: 'BLOCK_NUMBER', data: blockIdentifier };
|
|
75
|
-
}
|
|
76
|
-
if (typeof blockIdentifier === 'string' && blockIdentifier.startsWith('0x')) {
|
|
77
|
-
return { type: 'BLOCK_HASH', data: blockIdentifier };
|
|
78
|
-
}
|
|
79
|
-
if (typeof blockIdentifier === 'string' && !Number.isNaN(parseInt(blockIdentifier, 10))) {
|
|
80
|
-
return { type: 'BLOCK_NUMBER', data: parseInt(blockIdentifier, 10) };
|
|
81
|
-
}
|
|
82
|
-
if (typeof blockIdentifier === 'string') {
|
|
83
|
-
throw new Error(`Invalid block identifier: ${blockIdentifier}`);
|
|
84
|
-
}
|
|
85
|
-
return { type: 'BLOCK_HASH', data: blockIdentifier };
|
|
86
|
-
}
|
|
73
|
+
get identifier(): any {
|
|
74
|
+
if (this.number !== null) {
|
|
75
|
+
return { block_number: this.number };
|
|
76
|
+
}
|
|
87
77
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* @param blockIdentifier
|
|
94
|
-
* @returns block identifier for API request
|
|
95
|
-
*/
|
|
96
|
-
export function getFormattedBlockIdentifier(blockIdentifier: BlockIdentifier = null): string {
|
|
97
|
-
const blockIdentifierObject = getBlockIdentifier(blockIdentifier);
|
|
98
|
-
if (blockIdentifierObject.type === 'BLOCK_NUMBER' && blockIdentifierObject.data === null) {
|
|
99
|
-
return '';
|
|
78
|
+
if (this.hash !== null) {
|
|
79
|
+
return { block_hash: this.hash };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return this.tag;
|
|
100
83
|
}
|
|
101
|
-
|
|
102
|
-
|
|
84
|
+
|
|
85
|
+
set identifier(_identifier: BlockIdentifier) {
|
|
86
|
+
this.setIdentifier(_identifier);
|
|
103
87
|
}
|
|
104
|
-
|
|
88
|
+
|
|
89
|
+
valueOf = () => this.number;
|
|
90
|
+
|
|
91
|
+
toString = () => this.hash;
|
|
105
92
|
}
|
package/src/signer/default.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Abi,
|
|
1
|
+
import { Abi, Call, InvocationsSignerDetails, KeyPair, Signature } from '../types';
|
|
2
2
|
import { genKeyPair, getStarkKey, sign } from '../utils/ellipticCurve';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { calculateTransactionHash } from '../utils/hash';
|
|
4
|
+
import { fromCallsToExecuteCalldata } from '../utils/transaction';
|
|
5
5
|
import { TypedData, getMessageHash } from '../utils/typedData';
|
|
6
6
|
import { SignerInterface } from './interface';
|
|
7
7
|
|
|
@@ -17,7 +17,7 @@ export class Signer implements SignerInterface {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
public async signTransaction(
|
|
20
|
-
transactions:
|
|
20
|
+
transactions: Call[],
|
|
21
21
|
transactionsDetail: InvocationsSignerDetails,
|
|
22
22
|
abis?: Abi[]
|
|
23
23
|
): Promise<Signature> {
|
|
@@ -26,15 +26,15 @@ export class Signer implements SignerInterface {
|
|
|
26
26
|
}
|
|
27
27
|
// now use abi to display decoded data somewhere, but as this signer is headless, we can't do that
|
|
28
28
|
|
|
29
|
-
const calldata =
|
|
29
|
+
const calldata = fromCallsToExecuteCalldata(transactions);
|
|
30
30
|
|
|
31
|
-
const msgHash =
|
|
31
|
+
const msgHash = calculateTransactionHash(
|
|
32
32
|
transactionsDetail.walletAddress,
|
|
33
33
|
transactionsDetail.version,
|
|
34
|
-
getSelectorFromName('__execute__'),
|
|
35
34
|
calldata,
|
|
36
35
|
transactionsDetail.maxFee,
|
|
37
|
-
transactionsDetail.chainId
|
|
36
|
+
transactionsDetail.chainId,
|
|
37
|
+
transactionsDetail.nonce
|
|
38
38
|
);
|
|
39
39
|
|
|
40
40
|
return sign(this.keyPair, msgHash);
|
package/src/signer/interface.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Abi,
|
|
1
|
+
import { Abi, Call, InvocationsSignerDetails, Signature } from '../types';
|
|
2
2
|
import { TypedData } from '../utils/typedData';
|
|
3
3
|
|
|
4
4
|
export abstract class SignerInterface {
|
|
@@ -33,7 +33,7 @@ export abstract class SignerInterface {
|
|
|
33
33
|
* @returns signature
|
|
34
34
|
*/
|
|
35
35
|
public abstract signTransaction(
|
|
36
|
-
transactions:
|
|
36
|
+
transactions: Call[],
|
|
37
37
|
transactionsDetail: InvocationsSignerDetails,
|
|
38
38
|
abis?: Abi[]
|
|
39
39
|
): Promise<Signature>;
|