starknet 3.18.2 → 3.19.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 +53 -0
- package/__tests__/account.test.ts +11 -56
- package/__tests__/contract.test.ts +11 -49
- package/__tests__/defaultProvider.test.ts +321 -0
- package/__tests__/fixtures.ts +32 -11
- package/__tests__/rpcProvider.test.ts +17 -0
- package/__tests__/sequencerProvider.test.ts +45 -0
- package/account/default.d.ts +54 -77
- package/account/default.js +271 -596
- package/account/index.js +18 -31
- package/account/interface.d.ts +66 -95
- package/account/interface.js +20 -30
- package/constants.d.ts +17 -19
- package/constants.js +2038 -2059
- package/contract/contractFactory.d.ts +25 -29
- package/contract/contractFactory.js +94 -210
- package/contract/default.d.ts +117 -146
- package/contract/default.js +582 -776
- package/contract/index.js +19 -32
- package/contract/interface.d.ts +72 -92
- package/contract/interface.js +6 -5
- package/dist/account/default.d.ts +5 -9
- package/dist/account/default.js +35 -169
- package/dist/account/interface.d.ts +3 -15
- package/dist/contract/contractFactory.js +4 -4
- package/dist/contract/default.d.ts +3 -3
- package/dist/contract/default.js +3 -2
- package/dist/contract/interface.d.ts +2 -2
- package/dist/provider/default.d.ts +18 -134
- package/dist/provider/default.js +47 -411
- package/dist/provider/index.d.ts +2 -0
- package/dist/provider/index.js +2 -0
- package/dist/provider/interface.d.ts +45 -50
- package/dist/provider/rpc.d.ts +57 -0
- package/dist/provider/rpc.js +364 -0
- package/dist/provider/sequencer.d.ts +66 -0
- package/dist/provider/sequencer.js +443 -0
- package/dist/types/account.d.ts +2 -3
- package/dist/types/api/index.d.ts +16 -0
- package/dist/types/api/index.js +18 -0
- package/dist/types/api/rpc.d.ts +221 -0
- package/dist/types/{api.js → api/rpc.js} +0 -0
- package/dist/types/api/sequencer.d.ts +289 -0
- package/dist/types/api/sequencer.js +2 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.js +15 -1
- package/dist/types/lib.d.ts +3 -1
- package/dist/types/provider.d.ts +86 -0
- package/dist/types/provider.js +2 -0
- package/dist/utils/provider.d.ts +4 -0
- package/dist/utils/provider.js +38 -0
- package/dist/utils/responseParser/index.d.ts +11 -0
- package/dist/utils/responseParser/index.js +9 -0
- package/dist/utils/responseParser/rpc.d.ts +13 -0
- package/dist/utils/responseParser/rpc.js +96 -0
- package/dist/utils/responseParser/sequencer.d.ts +13 -0
- package/dist/utils/responseParser/sequencer.js +124 -0
- package/index.js +42 -75
- package/package.json +1 -1
- package/provider/default.d.ts +21 -175
- package/provider/default.js +139 -704
- package/provider/errors.d.ts +4 -4
- package/provider/errors.js +30 -40
- package/provider/index.d.ts +2 -0
- package/provider/index.js +22 -33
- package/provider/interface.d.ts +104 -131
- package/provider/interface.js +6 -5
- package/provider/rpc.d.ts +57 -0
- package/provider/rpc.js +364 -0
- package/provider/sequencer.d.ts +66 -0
- package/provider/sequencer.js +443 -0
- package/provider/utils.d.ts +7 -9
- package/provider/utils.js +39 -44
- package/signer/default.d.ts +5 -9
- package/signer/default.js +72 -177
- package/signer/index.js +18 -31
- package/signer/interface.d.ts +29 -33
- package/signer/interface.js +6 -5
- package/src/account/default.ts +26 -146
- package/src/account/interface.ts +5 -20
- package/src/contract/contractFactory.ts +3 -6
- package/src/contract/default.ts +6 -4
- package/src/contract/interface.ts +2 -2
- package/src/provider/default.ts +63 -395
- package/src/provider/index.ts +2 -0
- package/src/provider/interface.ts +68 -63
- package/src/provider/rpc.ts +300 -0
- package/src/provider/sequencer.ts +384 -0
- package/src/types/account.ts +2 -3
- package/src/types/api/index.ts +17 -0
- package/src/types/api/rpc.ts +247 -0
- package/src/types/api/sequencer.ts +331 -0
- package/src/types/index.ts +3 -1
- package/src/types/lib.ts +3 -1
- package/src/types/provider.ts +108 -0
- package/src/utils/provider.ts +28 -0
- package/src/utils/responseParser/index.ts +28 -0
- package/src/utils/responseParser/rpc.ts +93 -0
- package/src/utils/responseParser/sequencer.ts +127 -0
- package/types/account.d.ts +5 -7
- package/types/account.js +2 -2
- package/types/api/index.d.ts +16 -0
- package/types/api/index.js +18 -0
- package/types/api/rpc.d.ts +221 -0
- package/types/api/rpc.js +2 -0
- package/types/api/sequencer.d.ts +289 -0
- package/types/api/sequencer.js +2 -0
- package/types/contract.d.ts +1 -1
- package/types/contract.js +2 -2
- package/types/index.d.ts +3 -1
- package/types/index.js +35 -34
- package/types/lib.d.ts +36 -41
- package/types/lib.js +2 -2
- package/types/provider.d.ts +86 -0
- package/types/provider.js +2 -0
- package/types/signer.d.ts +2 -2
- package/types/signer.js +2 -2
- package/utils/address.js +26 -37
- package/utils/ellipticCurve.d.ts +1 -6
- package/utils/ellipticCurve.js +73 -137
- package/utils/encode.js +49 -85
- package/utils/hash.d.ts +4 -31
- package/utils/hash.js +76 -141
- package/utils/json.d.ts +13 -45
- package/utils/json.js +15 -22
- package/utils/number.d.ts +2 -9
- package/utils/number.js +47 -81
- package/utils/provider.d.ts +4 -0
- package/utils/provider.js +38 -0
- package/utils/responseParser/index.d.ts +11 -0
- package/utils/responseParser/index.js +9 -0
- package/utils/responseParser/rpc.d.ts +13 -0
- package/utils/responseParser/rpc.js +96 -0
- package/utils/responseParser/sequencer.d.ts +13 -0
- package/utils/responseParser/sequencer.js +124 -0
- package/utils/shortString.js +13 -21
- package/utils/stark.d.ts +0 -1
- package/utils/stark.js +59 -93
- package/utils/transaction.d.ts +3 -6
- package/utils/transaction.js +50 -81
- package/utils/typedData/index.d.ts +3 -15
- package/utils/typedData/index.js +109 -175
- package/utils/typedData/types.d.ts +9 -9
- package/utils/typedData/types.js +2 -2
- package/utils/typedData/utils.js +6 -6
- package/utils/uint256.d.ts +5 -5
- package/utils/uint256.js +16 -26
- package/www/docs/API/account.md +3 -4
- package/www/docs/API/contract.md +2 -2
- package/www/docs/API/contractFactory.md +2 -2
- package/www/docs/API/provider.md +185 -74
- package/www/guides/account.md +1 -8
- package/www/guides/erc20.md +3 -0
- package/__tests__/provider.test.ts +0 -168
- package/dist/types/api.d.ts +0 -261
- package/src/types/api.ts +0 -303
- package/types/api.d.ts +0 -287
- package/types/api.js +0 -2
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import urljoin from 'url-join';
|
|
2
|
+
|
|
3
|
+
import { ONE, StarknetChainId, ZERO } from '../constants';
|
|
4
|
+
import {
|
|
5
|
+
BlockTag,
|
|
6
|
+
Call,
|
|
7
|
+
CallContractResponse,
|
|
8
|
+
ContractClass,
|
|
9
|
+
DeclareContractPayload,
|
|
10
|
+
DeclareContractResponse,
|
|
11
|
+
DeployContractPayload,
|
|
12
|
+
DeployContractResponse,
|
|
13
|
+
EstimateFeeResponse,
|
|
14
|
+
GetBlockResponse,
|
|
15
|
+
GetTransactionReceiptResponse,
|
|
16
|
+
GetTransactionResponse,
|
|
17
|
+
Invocation,
|
|
18
|
+
InvocationsDetails,
|
|
19
|
+
InvokeFunctionResponse,
|
|
20
|
+
} from '../types';
|
|
21
|
+
import {
|
|
22
|
+
GetContractAddressesResponse,
|
|
23
|
+
GetTransactionStatusResponse,
|
|
24
|
+
GetTransactionTraceResponse,
|
|
25
|
+
Sequencer,
|
|
26
|
+
} from '../types/api';
|
|
27
|
+
import { getSelectorFromName } from '../utils/hash';
|
|
28
|
+
import { parse, parseAlwaysAsBig, stringify } from '../utils/json';
|
|
29
|
+
import { BigNumberish, bigNumberishArrayToDecimalStringArray, toBN, toHex } from '../utils/number';
|
|
30
|
+
import { parseContract, wait } from '../utils/provider';
|
|
31
|
+
import { SequencerAPIResponseParser } from '../utils/responseParser/sequencer';
|
|
32
|
+
import { randomAddress } from '../utils/stark';
|
|
33
|
+
import { GatewayError, HttpError } from './errors';
|
|
34
|
+
import { ProviderInterface } from './interface';
|
|
35
|
+
import { BlockIdentifier, getFormattedBlockIdentifier } from './utils';
|
|
36
|
+
|
|
37
|
+
type NetworkName = 'mainnet-alpha' | 'goerli-alpha';
|
|
38
|
+
|
|
39
|
+
function isEmptyQueryObject(obj?: Record<any, any>): obj is undefined {
|
|
40
|
+
return (
|
|
41
|
+
obj === undefined ||
|
|
42
|
+
Object.keys(obj).length === 0 ||
|
|
43
|
+
(Object.keys(obj).length === 1 &&
|
|
44
|
+
Object.entries(obj).every(([k, v]) => k === 'blockIdentifier' && v === null))
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type SequencerProviderOptions =
|
|
49
|
+
| { network: NetworkName }
|
|
50
|
+
| {
|
|
51
|
+
baseUrl: string;
|
|
52
|
+
feederGatewayUrl?: string;
|
|
53
|
+
gatewayUrl?: string;
|
|
54
|
+
chainId?: StarknetChainId;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export class SequencerProvider implements ProviderInterface {
|
|
58
|
+
public baseUrl: string;
|
|
59
|
+
|
|
60
|
+
public feederGatewayUrl: string;
|
|
61
|
+
|
|
62
|
+
public gatewayUrl: string;
|
|
63
|
+
|
|
64
|
+
public chainId: StarknetChainId;
|
|
65
|
+
|
|
66
|
+
private responseParser = new SequencerAPIResponseParser();
|
|
67
|
+
|
|
68
|
+
constructor(optionsOrProvider: SequencerProviderOptions = { network: 'goerli-alpha' }) {
|
|
69
|
+
if ('network' in optionsOrProvider) {
|
|
70
|
+
this.baseUrl = SequencerProvider.getNetworkFromName(optionsOrProvider.network);
|
|
71
|
+
this.chainId = SequencerProvider.getChainIdFromBaseUrl(this.baseUrl);
|
|
72
|
+
this.feederGatewayUrl = urljoin(this.baseUrl, 'feeder_gateway');
|
|
73
|
+
this.gatewayUrl = urljoin(this.baseUrl, 'gateway');
|
|
74
|
+
} else {
|
|
75
|
+
this.baseUrl = optionsOrProvider.baseUrl;
|
|
76
|
+
this.feederGatewayUrl =
|
|
77
|
+
optionsOrProvider.feederGatewayUrl ?? urljoin(this.baseUrl, 'feeder_gateway');
|
|
78
|
+
this.gatewayUrl = optionsOrProvider.gatewayUrl ?? urljoin(this.baseUrl, 'gateway');
|
|
79
|
+
this.chainId =
|
|
80
|
+
optionsOrProvider.chainId ??
|
|
81
|
+
SequencerProvider.getChainIdFromBaseUrl(optionsOrProvider.baseUrl);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
protected static getNetworkFromName(name: NetworkName) {
|
|
86
|
+
switch (name) {
|
|
87
|
+
case 'mainnet-alpha':
|
|
88
|
+
return 'https://alpha-mainnet.starknet.io';
|
|
89
|
+
case 'goerli-alpha':
|
|
90
|
+
default:
|
|
91
|
+
return 'https://alpha4.starknet.io';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected static getChainIdFromBaseUrl(baseUrl: string): StarknetChainId {
|
|
96
|
+
try {
|
|
97
|
+
const url = new URL(baseUrl);
|
|
98
|
+
if (url.host.includes('mainnet.starknet.io')) {
|
|
99
|
+
return StarknetChainId.MAINNET;
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
// eslint-disable-next-line no-console
|
|
103
|
+
console.error(`Could not parse baseUrl: ${baseUrl}`);
|
|
104
|
+
}
|
|
105
|
+
return StarknetChainId.TESTNET;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private getFetchUrl(endpoint: keyof Sequencer.Endpoints) {
|
|
109
|
+
const gatewayUrlEndpoints = ['add_transaction'];
|
|
110
|
+
|
|
111
|
+
return gatewayUrlEndpoints.includes(endpoint) ? this.gatewayUrl : this.feederGatewayUrl;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private getFetchMethod(endpoint: keyof Sequencer.Endpoints) {
|
|
115
|
+
const postMethodEndpoints = ['add_transaction', 'call_contract', 'estimate_fee'];
|
|
116
|
+
|
|
117
|
+
return postMethodEndpoints.includes(endpoint) ? 'POST' : 'GET';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private getQueryString(query?: Record<string, any>): string {
|
|
121
|
+
if (isEmptyQueryObject(query)) {
|
|
122
|
+
return '';
|
|
123
|
+
}
|
|
124
|
+
const queryString = Object.entries(query)
|
|
125
|
+
.map(([key, value]) => {
|
|
126
|
+
if (key === 'blockIdentifier') {
|
|
127
|
+
return `${getFormattedBlockIdentifier(value)}`;
|
|
128
|
+
}
|
|
129
|
+
return `${key}=${value}`;
|
|
130
|
+
})
|
|
131
|
+
.join('&');
|
|
132
|
+
|
|
133
|
+
return `?${queryString}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private getHeaders(method: 'POST' | 'GET'): Record<string, string> | undefined {
|
|
137
|
+
if (method === 'POST') {
|
|
138
|
+
return {
|
|
139
|
+
'Content-Type': 'application/json',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// typesafe fetch
|
|
146
|
+
protected async fetchEndpoint<T extends keyof Sequencer.Endpoints>(
|
|
147
|
+
endpoint: T,
|
|
148
|
+
// typescript type magiuc to create a nice fitting function interface
|
|
149
|
+
...[query, request]: Sequencer.Endpoints[T]['QUERY'] extends never
|
|
150
|
+
? Sequencer.Endpoints[T]['REQUEST'] extends never
|
|
151
|
+
? [] // when no query and no request is needed, we can omit the query and request parameters
|
|
152
|
+
: [undefined, Sequencer.Endpoints[T]['REQUEST']]
|
|
153
|
+
: Sequencer.Endpoints[T]['REQUEST'] extends never
|
|
154
|
+
? [Sequencer.Endpoints[T]['QUERY']] // when no request is needed, we can omit the request parameter
|
|
155
|
+
: [Sequencer.Endpoints[T]['QUERY'], Sequencer.Endpoints[T]['REQUEST']] // when both query and request are needed, we cant omit anything
|
|
156
|
+
): Promise<Sequencer.Endpoints[T]['RESPONSE']> {
|
|
157
|
+
const baseUrl = this.getFetchUrl(endpoint);
|
|
158
|
+
const method = this.getFetchMethod(endpoint);
|
|
159
|
+
const queryString = this.getQueryString(query);
|
|
160
|
+
const headers = this.getHeaders(method);
|
|
161
|
+
const url = urljoin(baseUrl, endpoint, queryString);
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const res = await fetch(url, {
|
|
165
|
+
method,
|
|
166
|
+
body: stringify(request),
|
|
167
|
+
headers,
|
|
168
|
+
});
|
|
169
|
+
const textResponse = await res.text();
|
|
170
|
+
if (!res.ok) {
|
|
171
|
+
// This will allow user to handle contract errors
|
|
172
|
+
let responseBody: any;
|
|
173
|
+
try {
|
|
174
|
+
responseBody = parse(textResponse);
|
|
175
|
+
} catch {
|
|
176
|
+
// if error parsing fails, return an http error
|
|
177
|
+
throw new HttpError(res.statusText, res.status);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const errorCode = responseBody.code || ((responseBody as any)?.status_code as string); // starknet-devnet uses status_code instead of code; They need to fix that
|
|
181
|
+
throw new GatewayError(responseBody.message, errorCode); // Caught locally, and re-thrown for the user
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (endpoint === 'estimate_fee') {
|
|
185
|
+
return parseAlwaysAsBig(textResponse, (_, v) => {
|
|
186
|
+
if (v && typeof v === 'bigint') {
|
|
187
|
+
return toBN(v.toString());
|
|
188
|
+
}
|
|
189
|
+
return v;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return parse(textResponse) as Sequencer.Endpoints[T]['RESPONSE'];
|
|
193
|
+
} catch (err) {
|
|
194
|
+
// rethrow custom errors
|
|
195
|
+
if (err instanceof GatewayError || err instanceof HttpError) {
|
|
196
|
+
throw err;
|
|
197
|
+
}
|
|
198
|
+
if (err instanceof Error) {
|
|
199
|
+
throw Error(`Could not ${method} from endpoint \`${url}\`: ${err.message}`);
|
|
200
|
+
}
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public async callContract(
|
|
206
|
+
{ contractAddress, entrypoint: entryPointSelector, calldata = [] }: Call,
|
|
207
|
+
blockIdentifier: BlockIdentifier = 'pending'
|
|
208
|
+
): Promise<CallContractResponse> {
|
|
209
|
+
return this.fetchEndpoint(
|
|
210
|
+
'call_contract',
|
|
211
|
+
{ blockIdentifier },
|
|
212
|
+
{
|
|
213
|
+
signature: [],
|
|
214
|
+
contract_address: contractAddress,
|
|
215
|
+
entry_point_selector: getSelectorFromName(entryPointSelector),
|
|
216
|
+
calldata,
|
|
217
|
+
}
|
|
218
|
+
).then(this.responseParser.parseCallContractResponse);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public async getBlock(blockIdentifier: BlockIdentifier = 'pending'): Promise<GetBlockResponse> {
|
|
222
|
+
return this.fetchEndpoint('get_block', { blockIdentifier }).then(
|
|
223
|
+
this.responseParser.parseGetBlockResponse
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public async getStorageAt(
|
|
228
|
+
contractAddress: string,
|
|
229
|
+
key: BigNumberish,
|
|
230
|
+
blockHashOrTag: BlockTag | BigNumberish = 'pending'
|
|
231
|
+
): Promise<BigNumberish> {
|
|
232
|
+
const parsedKey = toBN(key).toString(10);
|
|
233
|
+
return this.fetchEndpoint('get_storage_at', {
|
|
234
|
+
blockIdentifier: blockHashOrTag,
|
|
235
|
+
contractAddress,
|
|
236
|
+
key: parsedKey,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public async getTransaction(txHash: BigNumberish): Promise<GetTransactionResponse> {
|
|
241
|
+
const txHashHex = toHex(toBN(txHash));
|
|
242
|
+
return this.fetchEndpoint('get_transaction', { transactionHash: txHashHex }).then((value) =>
|
|
243
|
+
this.responseParser.parseGetTransactionResponse(value)
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
public async getTransactionReceipt(txHash: BigNumberish): Promise<GetTransactionReceiptResponse> {
|
|
248
|
+
const txHashHex = toHex(toBN(txHash));
|
|
249
|
+
return this.fetchEndpoint('get_transaction_receipt', { transactionHash: txHashHex }).then(
|
|
250
|
+
this.responseParser.parseGetTransactionReceiptResponse
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
public async getClassAt(
|
|
255
|
+
contractAddress: string,
|
|
256
|
+
blockIdentifier: BlockIdentifier = 'pending'
|
|
257
|
+
): Promise<ContractClass> {
|
|
258
|
+
return this.fetchEndpoint('get_full_contract', { blockIdentifier, contractAddress }).then(
|
|
259
|
+
parseContract
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
public async invokeFunction(
|
|
264
|
+
functionInvocation: Invocation,
|
|
265
|
+
details: InvocationsDetails
|
|
266
|
+
): Promise<InvokeFunctionResponse> {
|
|
267
|
+
return this.fetchEndpoint('add_transaction', undefined, {
|
|
268
|
+
type: 'INVOKE_FUNCTION',
|
|
269
|
+
contract_address: functionInvocation.contractAddress,
|
|
270
|
+
entry_point_selector: getSelectorFromName(functionInvocation.entrypoint),
|
|
271
|
+
calldata: bigNumberishArrayToDecimalStringArray(functionInvocation.calldata ?? []),
|
|
272
|
+
signature: bigNumberishArrayToDecimalStringArray(functionInvocation.signature ?? []),
|
|
273
|
+
max_fee: toHex(toBN(details.maxFee || 0)),
|
|
274
|
+
version: toHex(toBN(details.version || 0)),
|
|
275
|
+
}).then(this.responseParser.parseInvokeFunctionResponse);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
public async deployContract({
|
|
279
|
+
contract,
|
|
280
|
+
constructorCalldata,
|
|
281
|
+
addressSalt,
|
|
282
|
+
}: DeployContractPayload): Promise<DeployContractResponse> {
|
|
283
|
+
const contractDefinition = parseContract(contract);
|
|
284
|
+
|
|
285
|
+
return this.fetchEndpoint('add_transaction', undefined, {
|
|
286
|
+
type: 'DEPLOY',
|
|
287
|
+
contract_address_salt: addressSalt ?? randomAddress(),
|
|
288
|
+
constructor_calldata: bigNumberishArrayToDecimalStringArray(constructorCalldata ?? []),
|
|
289
|
+
contract_definition: contractDefinition,
|
|
290
|
+
}).then(this.responseParser.parseDeployContractResponse);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
public async declareContract({
|
|
294
|
+
contract,
|
|
295
|
+
}: DeclareContractPayload): Promise<DeclareContractResponse> {
|
|
296
|
+
const contractDefinition = parseContract(contract);
|
|
297
|
+
|
|
298
|
+
return this.fetchEndpoint('add_transaction', undefined, {
|
|
299
|
+
type: 'DECLARE',
|
|
300
|
+
contract_class: contractDefinition,
|
|
301
|
+
nonce: toHex(ZERO),
|
|
302
|
+
signature: [],
|
|
303
|
+
sender_address: toHex(ONE),
|
|
304
|
+
}).then(this.responseParser.parseDeclareContractResponse);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
public async getEstimateFee(
|
|
308
|
+
invocation: Invocation,
|
|
309
|
+
blockIdentifier: BlockIdentifier = 'pending',
|
|
310
|
+
invocationDetails: InvocationsDetails = {}
|
|
311
|
+
): Promise<EstimateFeeResponse> {
|
|
312
|
+
return this.fetchEndpoint(
|
|
313
|
+
'estimate_fee',
|
|
314
|
+
{ blockIdentifier },
|
|
315
|
+
{
|
|
316
|
+
contract_address: invocation.contractAddress,
|
|
317
|
+
entry_point_selector: getSelectorFromName(invocation.entrypoint),
|
|
318
|
+
calldata: invocation.calldata ?? [],
|
|
319
|
+
signature: bigNumberishArrayToDecimalStringArray(invocation.signature || []),
|
|
320
|
+
version: toHex(toBN(invocationDetails?.version || 0)),
|
|
321
|
+
}
|
|
322
|
+
).then(this.responseParser.parseFeeEstimateResponse);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
public async waitForTransaction(txHash: BigNumberish, retryInterval: number = 8000) {
|
|
326
|
+
let onchain = false;
|
|
327
|
+
|
|
328
|
+
while (!onchain) {
|
|
329
|
+
// eslint-disable-next-line no-await-in-loop
|
|
330
|
+
await wait(retryInterval);
|
|
331
|
+
// eslint-disable-next-line no-await-in-loop
|
|
332
|
+
const res = await this.getTransactionStatus(txHash);
|
|
333
|
+
|
|
334
|
+
const successStates = ['ACCEPTED_ON_L1', 'ACCEPTED_ON_L2', 'PENDING'];
|
|
335
|
+
const errorStates = ['REJECTED', 'NOT_RECEIVED'];
|
|
336
|
+
|
|
337
|
+
if (successStates.includes(res.tx_status)) {
|
|
338
|
+
onchain = true;
|
|
339
|
+
} else if (errorStates.includes(res.tx_status)) {
|
|
340
|
+
const message = res.tx_failure_reason
|
|
341
|
+
? `${res.tx_status}: ${res.tx_failure_reason.code}\n${res.tx_failure_reason.error_message}`
|
|
342
|
+
: res.tx_status;
|
|
343
|
+
const error = new Error(message) as Error & { response: GetTransactionStatusResponse };
|
|
344
|
+
error.response = res;
|
|
345
|
+
throw error;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Gets the status of a transaction.
|
|
352
|
+
*
|
|
353
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L48-L52)
|
|
354
|
+
*
|
|
355
|
+
* @param txHash
|
|
356
|
+
* @returns the transaction status object { block_number, tx_status: NOT_RECEIVED | RECEIVED | PENDING | REJECTED | ACCEPTED_ONCHAIN }
|
|
357
|
+
*/
|
|
358
|
+
public async getTransactionStatus(txHash: BigNumberish): Promise<GetTransactionStatusResponse> {
|
|
359
|
+
const txHashHex = toHex(toBN(txHash));
|
|
360
|
+
return this.fetchEndpoint('get_transaction_status', { transactionHash: txHashHex });
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Gets the smart contract address on the goerli testnet.
|
|
365
|
+
*
|
|
366
|
+
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L13-L15)
|
|
367
|
+
* @returns starknet smart contract addresses
|
|
368
|
+
*/
|
|
369
|
+
public async getContractAddresses(): Promise<GetContractAddressesResponse> {
|
|
370
|
+
return this.fetchEndpoint('get_contract_addresses');
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Gets the transaction trace from a tx id.
|
|
375
|
+
*
|
|
376
|
+
*
|
|
377
|
+
* @param txHash
|
|
378
|
+
* @returns the transaction trace
|
|
379
|
+
*/
|
|
380
|
+
public async getTransactionTrace(txHash: BigNumberish): Promise<GetTransactionTraceResponse> {
|
|
381
|
+
const txHashHex = toHex(toBN(txHash));
|
|
382
|
+
return this.fetchEndpoint('get_transaction_trace', { transactionHash: txHashHex });
|
|
383
|
+
}
|
|
384
|
+
}
|
package/src/types/account.ts
CHANGED
|
@@ -2,10 +2,9 @@ import BN from 'bn.js';
|
|
|
2
2
|
|
|
3
3
|
import { BlockIdentifier } from '../provider/utils';
|
|
4
4
|
import { BigNumberish } from '../utils/number';
|
|
5
|
+
import { EstimateFeeResponse } from './provider';
|
|
5
6
|
|
|
6
|
-
export interface EstimateFee {
|
|
7
|
-
amount: BN;
|
|
8
|
-
unit: string;
|
|
7
|
+
export interface EstimateFee extends EstimateFeeResponse {
|
|
9
8
|
suggestedMaxFee: BN;
|
|
10
9
|
}
|
|
11
10
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BigNumberish } from '../../utils/number';
|
|
2
|
+
import { Signature } from '../lib';
|
|
3
|
+
|
|
4
|
+
export type RawArgs = {
|
|
5
|
+
[inputName: string]: string | string[] | { type: 'struct'; [k: string]: BigNumberish };
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type Calldata = string[];
|
|
9
|
+
|
|
10
|
+
export type Overrides = {
|
|
11
|
+
maxFee?: BigNumberish;
|
|
12
|
+
nonce?: BigNumberish;
|
|
13
|
+
signature?: Signature;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export * from './sequencer';
|
|
17
|
+
export * from './rpc';
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { StarknetChainId } from '../../constants';
|
|
2
|
+
import { Status } from '../lib';
|
|
3
|
+
|
|
4
|
+
export namespace RPC {
|
|
5
|
+
export type Response = {
|
|
6
|
+
id: number;
|
|
7
|
+
result: any;
|
|
8
|
+
jsonrpc: string;
|
|
9
|
+
error?: {
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type AddTransactionResponse = {
|
|
16
|
+
transaction_hash: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type GetClassResponse = {
|
|
20
|
+
program: string;
|
|
21
|
+
entry_point_by_type: any;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type DeclareResponse = {
|
|
25
|
+
transaction_hash: string;
|
|
26
|
+
class_hash: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type EstimateFeeResponse = {
|
|
30
|
+
overall_fee: number;
|
|
31
|
+
gas_consumed: number;
|
|
32
|
+
gas_price: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type GetBlockResponse = {
|
|
36
|
+
block_hash: string;
|
|
37
|
+
parent_hash: string;
|
|
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;
|
|
54
|
+
|
|
55
|
+
export type GetTransactionReceiptResponse = {
|
|
56
|
+
txn_hash: string;
|
|
57
|
+
actual_fee: string;
|
|
58
|
+
status: Status;
|
|
59
|
+
status_data: string;
|
|
60
|
+
messages_sent: Array<MessageToL1>;
|
|
61
|
+
l1_origin_message: MessageToL2;
|
|
62
|
+
events: Array<StarknetEvent>;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
interface CommonTransactionProperties {
|
|
66
|
+
txn_hash: string;
|
|
67
|
+
max_fee: string;
|
|
68
|
+
version: string;
|
|
69
|
+
nonce: string;
|
|
70
|
+
signature: Array<string>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface InvokeTransactionResponse extends CommonTransactionProperties {
|
|
74
|
+
contract_address?: string;
|
|
75
|
+
entry_point_selector?: string;
|
|
76
|
+
calldata?: Array<string>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface DeclareTransactionResponse extends CommonTransactionProperties {
|
|
80
|
+
contract_class?: GetClassResponse;
|
|
81
|
+
sender_address?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type GetTransactionResponse = InvokeTransactionResponse & DeclareTransactionResponse;
|
|
85
|
+
|
|
86
|
+
export type GetTransactionCountResponse = number;
|
|
87
|
+
|
|
88
|
+
export type GetBlockNumberResponse = number;
|
|
89
|
+
|
|
90
|
+
export type GetSyncingStatsResponse =
|
|
91
|
+
| {
|
|
92
|
+
starting_block_hash: string;
|
|
93
|
+
starting_block_num: string;
|
|
94
|
+
current_block_hash: string;
|
|
95
|
+
current_block_num: string;
|
|
96
|
+
highest_block_hash: string;
|
|
97
|
+
highest_block_num: string;
|
|
98
|
+
}
|
|
99
|
+
| boolean;
|
|
100
|
+
|
|
101
|
+
export type EventFilter = {
|
|
102
|
+
fromBlock: string;
|
|
103
|
+
toBlock: string;
|
|
104
|
+
address: string;
|
|
105
|
+
keys: string[];
|
|
106
|
+
page_size: number;
|
|
107
|
+
page_number: number;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export type GetEventsResponse = {
|
|
111
|
+
events: StarknetEmittedEvent[];
|
|
112
|
+
page_number: number;
|
|
113
|
+
is_last_page: number;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type DeployContractResponse = {
|
|
117
|
+
transaction_hash: string;
|
|
118
|
+
contract_address: string;
|
|
119
|
+
};
|
|
120
|
+
// Other
|
|
121
|
+
|
|
122
|
+
export type StarknetEvent = {
|
|
123
|
+
from_address: string;
|
|
124
|
+
keys: string[];
|
|
125
|
+
data: string[];
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export type StarknetEmittedEvent = {
|
|
129
|
+
event: StarknetEvent;
|
|
130
|
+
block_hash: string;
|
|
131
|
+
block_number: number;
|
|
132
|
+
transaction_hash: string;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export type MessageToL1 = {
|
|
136
|
+
to_address: string;
|
|
137
|
+
payload: string[];
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export type MessageToL2 = {
|
|
141
|
+
from_address: string;
|
|
142
|
+
payload: string[];
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export type Methods = {
|
|
146
|
+
starknet_getBlockByHash: {
|
|
147
|
+
QUERY: never;
|
|
148
|
+
REQUEST: any[];
|
|
149
|
+
RESPONSE: GetBlockResponse;
|
|
150
|
+
};
|
|
151
|
+
starknet_getBlockByNumber: {
|
|
152
|
+
QUERY: never;
|
|
153
|
+
REQUEST: any[];
|
|
154
|
+
RESPONSE: GetBlockResponse;
|
|
155
|
+
};
|
|
156
|
+
starknet_getStorageAt: {
|
|
157
|
+
QUERY: never;
|
|
158
|
+
REQUEST: any[];
|
|
159
|
+
RESPONSE: GetStorageAtResponse;
|
|
160
|
+
};
|
|
161
|
+
starknet_getTransactionByHash: {
|
|
162
|
+
QUERY: never;
|
|
163
|
+
REQUEST: any[];
|
|
164
|
+
RESPONSE: GetTransactionResponse;
|
|
165
|
+
};
|
|
166
|
+
starknet_getTransactionByBlockHashAndIndex: {
|
|
167
|
+
QUERY: never;
|
|
168
|
+
REQUEST: any[];
|
|
169
|
+
RESPONSE: GetTransactionResponse;
|
|
170
|
+
};
|
|
171
|
+
starknet_getTransactionByBlockNumberAndIndex: {
|
|
172
|
+
QUERY: never;
|
|
173
|
+
REQUEST: any[];
|
|
174
|
+
RESPONSE: GetTransactionResponse;
|
|
175
|
+
};
|
|
176
|
+
starknet_getTransactionReceipt: {
|
|
177
|
+
QUERY: never;
|
|
178
|
+
REQUEST: any[];
|
|
179
|
+
RESPONSE: GetTransactionReceiptResponse;
|
|
180
|
+
};
|
|
181
|
+
starknet_getBlockTransactionCountByHash: {
|
|
182
|
+
QUERY: never;
|
|
183
|
+
REQUEST: any[];
|
|
184
|
+
RESPONSE: GetTransactionCountResponse;
|
|
185
|
+
};
|
|
186
|
+
starknet_getBlockTransactionCountByNumber: {
|
|
187
|
+
QUERY: never;
|
|
188
|
+
REQUEST: any[];
|
|
189
|
+
RESPONSE: GetTransactionCountResponse;
|
|
190
|
+
};
|
|
191
|
+
starknet_getCode: {
|
|
192
|
+
QUERY: never;
|
|
193
|
+
REQUEST: any[];
|
|
194
|
+
RESPONSE: GetCodeResponse;
|
|
195
|
+
};
|
|
196
|
+
starknet_call: {
|
|
197
|
+
QUERY: never;
|
|
198
|
+
REQUEST: any[];
|
|
199
|
+
RESPONSE: string[];
|
|
200
|
+
};
|
|
201
|
+
starknet_estimateFee: {
|
|
202
|
+
QUERY: never;
|
|
203
|
+
REQUEST: any[];
|
|
204
|
+
RESPONSE: EstimateFeeResponse;
|
|
205
|
+
};
|
|
206
|
+
starknet_blockNumber: {
|
|
207
|
+
QUERY: never;
|
|
208
|
+
REQUEST: any[];
|
|
209
|
+
RESPONSE: GetBlockNumberResponse;
|
|
210
|
+
};
|
|
211
|
+
starknet_chainId: {
|
|
212
|
+
QUERY: never;
|
|
213
|
+
REQUEST: any[];
|
|
214
|
+
RESPONSE: StarknetChainId;
|
|
215
|
+
};
|
|
216
|
+
starknet_syncing: {
|
|
217
|
+
QUERY: never;
|
|
218
|
+
REQUEST: any[];
|
|
219
|
+
RESPONSE: GetSyncingStatsResponse;
|
|
220
|
+
};
|
|
221
|
+
starknet_getEvents: {
|
|
222
|
+
QUERY: never;
|
|
223
|
+
REQUEST: any[];
|
|
224
|
+
RESPONSE: GetEventsResponse;
|
|
225
|
+
};
|
|
226
|
+
starknet_addInvokeTransaction: {
|
|
227
|
+
QUERY: never;
|
|
228
|
+
REQUEST: any[];
|
|
229
|
+
RESPONSE: AddTransactionResponse;
|
|
230
|
+
};
|
|
231
|
+
starknet_addDeployTransaction: {
|
|
232
|
+
QUERY: never;
|
|
233
|
+
REQUEST: any[];
|
|
234
|
+
RESPONSE: DeployContractResponse;
|
|
235
|
+
};
|
|
236
|
+
starknet_addDeclareTransaction: {
|
|
237
|
+
QUERY: never;
|
|
238
|
+
REQUEST: any[];
|
|
239
|
+
RESPONSE: DeclareResponse;
|
|
240
|
+
};
|
|
241
|
+
starknet_getClassAt: {
|
|
242
|
+
QUERY: never;
|
|
243
|
+
REQUEST: any[];
|
|
244
|
+
RESPONSE: any;
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
}
|