Skip to content

Commit 5ee94f7

Browse files
committed
feat: update estimateFeeBulk
1 parent e716a18 commit 5ee94f7

File tree

9 files changed

+264
-123
lines changed

9 files changed

+264
-123
lines changed

__tests__/account.test.ts

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,27 +65,39 @@ describe('deploy and test Wallet', () => {
6565
innerInvokeEstFeeSpy.mockClear();
6666
});
6767

68-
test('estimate fee bulk', async () => {
69-
const estimate = await account.estimateInvokeFeeBulk([
68+
test('estimate invoke fee bulk', async () => {
69+
const innerInvokeEstFeeSpy = jest.spyOn(account.signer, 'signTransaction');
70+
const { overall_fee } = await account.estimateFeeBulk([
71+
{
72+
type: 'DECLARE',
73+
contract: compiledErc20,
74+
classHash: '0x54328a1075b8820eb43caf0caa233923148c983742402dcfc38541dd843d01a',
75+
},
76+
{
77+
type: 'DEPLOY',
78+
classHash: '0x54328a1075b8820eb43caf0caa233923148c983742402dcfc38541dd843d01a',
79+
constructorCalldata: [
80+
encodeShortString('Token'),
81+
encodeShortString('ERC20'),
82+
account.address,
83+
],
84+
},
85+
{
86+
type: 'INVOKE_FUNCTION',
87+
contractAddress: erc20Address,
88+
entrypoint: 'approve',
89+
calldata: [erc20Address, '10', '0'],
90+
},
7091
{
92+
type: 'INVOKE_FUNCTION',
7193
contractAddress: erc20Address,
7294
entrypoint: 'transfer',
7395
calldata: [erc20.address, '10', '0'],
7496
},
75-
[
76-
{
77-
contractAddress: erc20Address,
78-
entrypoint: 'transfer',
79-
calldata: [erc20.address, '10', '0'],
80-
},
81-
{
82-
contractAddress: erc20Address,
83-
entrypoint: 'transfer',
84-
calldata: [erc20.address, '10', '0'],
85-
},
86-
],
8797
]);
88-
expect(isBN(estimate.overall_fee)).toBe(true);
98+
expect(isBN(overall_fee)).toBe(true);
99+
expect(innerInvokeEstFeeSpy.mock.calls[0][1].version).toBe(feeTransactionVersion);
100+
innerInvokeEstFeeSpy.mockClear();
89101
});
90102

91103
test('read balance of wallet', async () => {

src/account/default.ts

Lines changed: 155 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
KeyPair,
2727
MultiDeployContractResponse,
2828
Signature,
29+
TransactionBulk,
2930
UniversalDeployerContractPayload,
3031
} from '../types';
3132
import { parseUDCEvent } from '../utils/events';
@@ -150,59 +151,6 @@ export class Account extends Provider implements AccountInterface {
150151
};
151152
}
152153

153-
public async estimateInvokeFeeBulk(
154-
calls: Array<AllowArray<Call>>,
155-
{ nonce: providedNonce, blockIdentifier }: EstimateFeeDetails = {}
156-
): Promise<EstimateFee> {
157-
let nonce = toBN(providedNonce ?? (await this.getNonce()));
158-
const version = toBN(feeTransactionVersion);
159-
const chainId = await this.getChainId();
160-
161-
const invocations: any = await Promise.all(
162-
[].concat(calls as []).map(async (call) => {
163-
const transactions = Array.isArray(call) ? call : [call];
164-
const signerDetails: InvocationsSignerDetails = {
165-
walletAddress: this.address,
166-
nonce,
167-
maxFee: ZERO,
168-
version,
169-
chainId,
170-
};
171-
const invocation = await this.buildInvocation(transactions, signerDetails);
172-
const res = {
173-
...invocation,
174-
version,
175-
nonce,
176-
blockIdentifier,
177-
};
178-
nonce = toBN(Number(nonce) + 1);
179-
return res;
180-
})
181-
);
182-
183-
const response = await super.getInvokeEstimateFeeBulk(invocations, blockIdentifier);
184-
const suggestedMaxFee = estimatedFeeToMaxFee(response.overall_fee);
185-
186-
return {
187-
...response,
188-
suggestedMaxFee,
189-
};
190-
}
191-
192-
private async buildInvocation(
193-
call: Array<Call>,
194-
signerDetails: InvocationsSignerDetails
195-
): Promise<Invocation> {
196-
const calldata = fromCallsToExecuteCalldata(call);
197-
const signature = await this.signer.signTransaction(call, signerDetails);
198-
199-
return {
200-
contractAddress: this.address,
201-
calldata,
202-
signature,
203-
};
204-
}
205-
206154
public async estimateDeclareFee(
207155
{ classHash, contract }: DeclareContractPayload,
208156
{ blockIdentifier, nonce: providedNonce }: EstimateFeeDetails = {}
@@ -303,6 +251,160 @@ export class Account extends Provider implements AccountInterface {
303251
return this.estimateInvokeFee(calls, transactionsDetail);
304252
}
305253

254+
public async estimateFeeBulk(
255+
calls: Array<TransactionBulk>,
256+
{ nonce: providedNonce, blockIdentifier }: EstimateFeeDetails = {}
257+
): Promise<EstimateFee> {
258+
const nonce = toBN(providedNonce ?? (await this.getNonce()));
259+
const version = toBN(feeTransactionVersion);
260+
const chainId = await this.getChainId();
261+
262+
const invocations: any = await Promise.all(
263+
[].concat(calls as []).map(async (transaction: any, index: number) => {
264+
const signerDetails: InvocationsSignerDetails = {
265+
walletAddress: this.address,
266+
nonce: toBN(Number(nonce) + index),
267+
maxFee: ZERO,
268+
version,
269+
chainId,
270+
};
271+
272+
let res;
273+
if (
274+
typeof transaction === 'object' &&
275+
transaction.type === 'INVOKE_FUNCTION' &&
276+
'entrypoint' in transaction &&
277+
'contractAddress' in transaction &&
278+
'calldata' in transaction
279+
) {
280+
const transactions: any = Array.isArray(transaction) ? transaction : [transaction];
281+
const invocation = await this.buildInvocation(transactions, signerDetails);
282+
res = {
283+
type: 'INVOKE_FUNCTION',
284+
...invocation,
285+
version,
286+
nonce: toBN(Number(nonce) + index),
287+
blockIdentifier,
288+
};
289+
} else if (
290+
typeof transaction === 'object' &&
291+
transaction.type === 'DECLARE' &&
292+
'contract' in transaction &&
293+
'classHash' in transaction
294+
) {
295+
const contractDefinition = parseContract(transaction.contract);
296+
const signature = await this.signer.signDeclareTransaction({
297+
classHash: transaction.classHash,
298+
senderAddress: this.address,
299+
chainId,
300+
maxFee: ZERO,
301+
version,
302+
nonce: toBN(Number(nonce) + index),
303+
});
304+
res = {
305+
type: 'DECLARE',
306+
senderAddress: this.address,
307+
signature,
308+
contractDefinition,
309+
version,
310+
nonce: toBN(Number(nonce) + index),
311+
blockIdentifier,
312+
};
313+
} else if (
314+
typeof transaction === 'object' &&
315+
transaction.type === 'DEPLOY_ACCOUNT' &&
316+
'classHash' in transaction
317+
) {
318+
const contractAddress =
319+
transaction.contractAddress ??
320+
calculateContractAddressFromHash(
321+
transaction.addressSalt || 0,
322+
transaction.classHash,
323+
transaction.constructorCalldata || [],
324+
0
325+
);
326+
327+
const signature = await this.signer.signDeployAccountTransaction({
328+
classHash: transaction.classHash,
329+
contractAddress,
330+
chainId,
331+
maxFee: ZERO,
332+
version,
333+
nonce: toBN(Number(nonce) + index),
334+
addressSalt: transaction.addressSalt || 0,
335+
constructorCalldata: transaction.constructorCalldata || [],
336+
});
337+
338+
res = {
339+
type: 'DEPLOY_ACCOUNT',
340+
classHash: transaction.classHash,
341+
addressSalt: transaction.addressSalt || 0,
342+
constructorCalldata: transaction.constructorCalldata || [],
343+
signature,
344+
version,
345+
nonce,
346+
blockIdentifier,
347+
};
348+
} else if (
349+
typeof transaction === 'object' &&
350+
transaction.type === 'DEPLOY' &&
351+
'classHash' in transaction
352+
) {
353+
const {
354+
classHash,
355+
salt = '0',
356+
unique = true,
357+
constructorCalldata = [],
358+
} = transaction as UniversalDeployerContractPayload;
359+
const compiledConstructorCallData = compileCalldata(constructorCalldata);
360+
const call = {
361+
contractAddress: UDC.ADDRESS,
362+
entrypoint: UDC.ENTRYPOINT,
363+
calldata: [
364+
classHash,
365+
salt,
366+
toCairoBool(unique),
367+
compiledConstructorCallData.length,
368+
...compiledConstructorCallData,
369+
],
370+
};
371+
const transactions: any = Array.isArray(call) ? call : [call];
372+
const invocation = await this.buildInvocation(transactions, signerDetails);
373+
res = {
374+
type: 'INVOKE_FUNCTION',
375+
...invocation,
376+
version,
377+
nonce: toBN(Number(nonce) + index),
378+
blockIdentifier,
379+
};
380+
}
381+
return res;
382+
})
383+
);
384+
385+
const response = await super.getEstimateFeeBulk(invocations, blockIdentifier);
386+
const suggestedMaxFee = estimatedFeeToMaxFee(response.overall_fee);
387+
388+
return {
389+
...response,
390+
suggestedMaxFee,
391+
};
392+
}
393+
394+
private async buildInvocation(
395+
call: Array<Call>,
396+
signerDetails: InvocationsSignerDetails
397+
): Promise<Invocation> {
398+
const calldata = fromCallsToExecuteCalldata(call);
399+
const signature = await this.signer.signTransaction(call, signerDetails);
400+
401+
return {
402+
contractAddress: this.address,
403+
calldata,
404+
signature,
405+
};
406+
}
407+
306408
public async execute(
307409
calls: AllowArray<Call>,
308410
abis: Abi[] | undefined = undefined,

src/account/interface.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
InvokeFunctionResponse,
2020
MultiDeployContractResponse,
2121
Signature,
22+
TransactionBulk,
2223
UniversalDeployerContractPayload,
2324
} from '../types';
2425
import { BigNumberish } from '../utils/number';
@@ -60,21 +61,6 @@ export abstract class AccountInterface extends ProviderInterface {
6061
estimateFeeDetails?: EstimateFeeDetails
6162
): Promise<EstimateFeeResponse>;
6263

63-
/**
64-
* Estimate Fee for executing a list of INVOKE transaction on starknet
65-
*
66-
* @param calls the invocation object containing:
67-
* - contractAddress - the address of the contract
68-
* - entrypoint - the entrypoint of the contract
69-
* - calldata - (defaults to []) the calldata
70-
*
71-
* @returns response from estimate_fee
72-
*/
73-
public abstract estimateInvokeFeeBulk(
74-
calls: Array<AllowArray<Call>>,
75-
estimateFeeDetails?: EstimateFeeDetails
76-
): Promise<EstimateFeeResponse>;
77-
7864
/**
7965
* Estimate Fee for executing a DECLARE transaction on starknet
8066
*
@@ -123,6 +109,20 @@ export abstract class AccountInterface extends ProviderInterface {
123109
transactionsDetail?: InvocationsDetails
124110
): Promise<EstimateFeeResponse>;
125111

112+
/**
113+
* Estimate Fee for executing a list of transactions on starknet
114+
*
115+
* @param transactions array of transaction object containing :
116+
* - type - the type of transaction : 'DECLARE' | 'DEPLOY' | 'INVOKE_FUNCTION' | 'DEPLOY_ACCOUNT'
117+
* - payload - the payload of the transaction
118+
*
119+
* @returns response from estimate_fee
120+
*/
121+
public abstract estimateFeeBulk(
122+
calls: Array<TransactionBulk>,
123+
estimateFeeDetails?: EstimateFeeDetails
124+
): Promise<EstimateFeeResponse>;
125+
126126
/**
127127
* Invoke execute function in account contract
128128
*

src/provider/default.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ export class Provider implements ProviderInterface {
104104
);
105105
}
106106

107-
public async getInvokeEstimateFeeBulk(
107+
public async getEstimateFeeBulk(
108108
invocations: Array<InvocationBulk>,
109109
blockIdentifier?: BlockIdentifier
110110
): Promise<EstimateFeeResponse> {
111-
return this.provider.getInvokeEstimateFeeBulk(invocations, blockIdentifier);
111+
return this.provider.getEstimateFeeBulk(invocations, blockIdentifier);
112112
}
113113

114114
public async getNonceForAddress(

src/provider/interface.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -227,23 +227,6 @@ export abstract class ProviderInterface {
227227
blockIdentifier?: BlockIdentifier
228228
): Promise<EstimateFeeResponse>;
229229

230-
/**
231-
* Estimates the fee for a list of INVOKE transaction
232-
*
233-
* @param invocations the array of invocation and invocation details object containing:
234-
* - contractAddress - the address of the account
235-
* - calldata - (defaults to []) the calldata
236-
* - signature - (defaults to []) the signature
237-
* - nonce - optional nonce
238-
* - version - optional version
239-
* @param blockIdentifier - block identifier
240-
* @returns the estimated fee
241-
*/
242-
public abstract getInvokeEstimateFeeBulk(
243-
invocations: Array<InvocationBulk>,
244-
blockIdentifier?: BlockIdentifier
245-
): Promise<EstimateFeeResponse>;
246-
247230
/**
248231
* Estimates the fee for a given DECLARE transaction
249232
*
@@ -285,6 +268,23 @@ export abstract class ProviderInterface {
285268
blockIdentifier?: BlockIdentifier
286269
): Promise<EstimateFeeResponse>;
287270

271+
/**
272+
* Estimates the fee for a list of INVOKE transaction
273+
*
274+
* @param invocations the array of invocation and invocation details object containing:
275+
* - contractAddress - the address of the account
276+
* - calldata - (defaults to []) the calldata
277+
* - signature - (defaults to []) the signature
278+
* - nonce - optional nonce
279+
* - version - optional version
280+
* @param blockIdentifier - block identifier
281+
* @returns the estimated fee
282+
*/
283+
public abstract getEstimateFeeBulk(
284+
invocations: Array<InvocationBulk>,
285+
blockIdentifier?: BlockIdentifier
286+
): Promise<EstimateFeeResponse>;
287+
288288
/**
289289
* Wait for the transaction to be accepted
290290
* @param txHash - transaction hash

0 commit comments

Comments
 (0)