Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: remove additional dryrun call #1731

Merged
merged 17 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/modern-adults-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@fuel-ts/program": patch
"@fuel-ts/providers": patch
"@fuel-ts/wallet": patch
---

remove additional dryrun call
2 changes: 0 additions & 2 deletions apps/demo-typegen/src/demo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ test('Example script', async () => {
const provider = await Provider.create(FUEL_NETWORK_URL);
const wallet = await generateTestWallet(provider, [[500_000, BaseAssetId]]);

// TODO: investigate why do we need to specify the gasLimit here. If we don't specify it, the call fails saying `FuelError: Gas limit '0' is lower than the required: '19'.`

// #region typegen-demo-script
// #context import { ScriptAbi__factory } from './types';

Expand Down
25 changes: 15 additions & 10 deletions packages/program/src/functions/base-invocation-scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,8 @@ export class BaseInvocationScope<TReturn = any> {
async call<T = TReturn>(): Promise<FunctionInvocationResult<T>> {
assert(this.program.account, 'Wallet is required!');

const provider = this.getProvider();

const transactionRequest = await this.getTransactionRequest();
const { maxFee, gasUsed } = await this.getTransactionCost();
const { minGasPrice } = provider.getGasConfig();
const { maxFee, gasUsed, minGasPrice } = await this.getTransactionCost();

this.setDefaultTxParams(transactionRequest, minGasPrice, gasUsed);

Expand Down Expand Up @@ -335,11 +332,8 @@ export class BaseInvocationScope<TReturn = any> {
return this.dryRun<T>();
}

const provider = this.getProvider();

const transactionRequest = await this.getTransactionRequest();
const { maxFee, gasUsed } = await this.getTransactionCost();
const { minGasPrice } = provider.getGasConfig();
const { maxFee, gasUsed, minGasPrice } = await this.getTransactionCost();

this.setDefaultTxParams(transactionRequest, minGasPrice, gasUsed);

Expand All @@ -361,8 +355,7 @@ export class BaseInvocationScope<TReturn = any> {
const provider = this.getProvider();

const transactionRequest = await this.getTransactionRequest();
const { maxFee, gasUsed } = await this.getTransactionCost();
const { minGasPrice } = provider.getGasConfig();
const { maxFee, gasUsed, minGasPrice } = await this.getTransactionCost();

this.setDefaultTxParams(transactionRequest, minGasPrice, gasUsed);

Expand Down Expand Up @@ -411,12 +404,24 @@ export class BaseInvocationScope<TReturn = any> {
const gasLimitSpecified = !!this.txParameters?.gasLimit || this.hasCallParamsGasLimit;
const gasPriceSpecified = !!this.txParameters?.gasPrice;

const { gasLimit, gasPrice } = transactionRequest;

if (!gasLimitSpecified) {
transactionRequest.gasLimit = gasUsed;
} else if (gasLimit.lt(gasUsed)) {
throw new FuelError(
ErrorCode.GAS_LIMIT_TOO_LOW,
`Gas limit '${gasLimit}' is lower than the required: '${gasUsed}'.`
);
arboleya marked this conversation as resolved.
Show resolved Hide resolved
}

if (!gasPriceSpecified) {
transactionRequest.gasPrice = minGasPrice;
} else if (gasPrice.lt(minGasPrice)) {
throw new FuelError(
ErrorCode.GAS_PRICE_TOO_LOW,
`Gas price '${gasPrice}' is lower than the required: '${minGasPrice}'.`
);
}
}
}
21 changes: 0 additions & 21 deletions packages/providers/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,27 +583,6 @@ export default class Provider {
}
// #endregion Provider-sendTransaction

const { gasUsed, minGasPrice } = await this.getTransactionCost(transactionRequest, [], {
estimateTxDependencies: false,
estimatePredicates: false,
});

if (bn(minGasPrice).gt(bn(transactionRequest.gasPrice))) {
Torres-ssf marked this conversation as resolved.
Show resolved Hide resolved
throw new FuelError(
ErrorCode.GAS_PRICE_TOO_LOW,
`Gas price '${transactionRequest.gasPrice}' is lower than the required: '${minGasPrice}'.`
);
}

const isScriptTransaction = transactionRequest.type === TransactionType.Script;

if (isScriptTransaction && bn(gasUsed).gt(bn(transactionRequest.gasLimit))) {
throw new FuelError(
ErrorCode.GAS_LIMIT_TOO_LOW,
`Gas limit '${transactionRequest.gasLimit}' is lower than the required: '${gasUsed}'.`
);
}

const encodedTransaction = hexlify(transactionRequest.toTransactionBytes());

if (awaitExecution) {
Expand Down
72 changes: 1 addition & 71 deletions packages/providers/test/provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getBytesCopy, hexlify } from 'ethers';
import type { BytesLike } from 'ethers';

import { fromTai64ToDate } from '../src';
import type { ChainInfo, NodeInfo, TransactionCost, FetchRequestOptions } from '../src/provider';
import type { ChainInfo, NodeInfo, FetchRequestOptions } from '../src/provider';
import Provider from '../src/provider';
import type {
CoinTransactionRequestInput,
Expand Down Expand Up @@ -870,76 +870,6 @@ describe('Provider', () => {
});
});

it('throws when gas limit is lower than tx gas used', async () => {
const provider = await Provider.create(FUEL_NETWORK_URL);
const gasLimit = 1;
const gasUsed = bn(1000);
const transactionCost: TransactionCost = {
gasUsed,
gasPrice: bn(1),
minGasPrice: bn(1),
maxFee: bn(2),
minFee: bn(1),
receipts: [],
requiredQuantities: [],
maxGas: bn(1),
minGas: bn(1),
usedFee: bn(1),
};

const estimateTxSpy = vi.spyOn(provider, 'estimateTxDependencies').mockResolvedValueOnce();

const txCostSpy = vi
.spyOn(provider, 'getTransactionCost')
.mockReturnValue(Promise.resolve(transactionCost));

await expectToThrowFuelError(
() => provider.sendTransaction(new ScriptTransactionRequest({ gasPrice: 1, gasLimit })),
{
code: ErrorCode.GAS_LIMIT_TOO_LOW,
message: `Gas limit '${gasLimit}' is lower than the required: '${gasUsed}'.`,
}
);

expect(txCostSpy).toHaveBeenCalled();
expect(estimateTxSpy).toHaveBeenCalled();
});

it('throws when gas price is lower than min tx gas price', async () => {
const provider = await Provider.create(FUEL_NETWORK_URL);
const gasPrice = 1;
const minGasPrice = bn(1000);
const transactionCost: TransactionCost = {
minGasPrice,
gasPrice: bn(1),
gasUsed: bn(1),
maxFee: bn(2),
minFee: bn(1),
receipts: [],
requiredQuantities: [],
maxGas: bn(1),
minGas: bn(1),
usedFee: bn(1),
};

const estimateTxSpy = vi.spyOn(provider, 'estimateTxDependencies').mockResolvedValueOnce();

const txCostSpy = vi
.spyOn(provider, 'getTransactionCost')
.mockReturnValue(Promise.resolve(transactionCost));

await expectToThrowFuelError(
() => provider.sendTransaction(new ScriptTransactionRequest({ gasPrice, gasLimit: 1000 })),
{
code: ErrorCode.GAS_PRICE_TOO_LOW,
message: `Gas price '${gasPrice}' is lower than the required: '${minGasPrice}'.`,
}
);

expect(txCostSpy).toHaveBeenCalled();
expect(estimateTxSpy).toHaveBeenCalled();
});

it('An invalid subscription request throws a FuelError and does not hold the test runner (closes all handles)', async () => {
const provider = await Provider.create(FUEL_NETWORK_URL);

Expand Down
159 changes: 7 additions & 152 deletions packages/wallet/src/account.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import { Address } from '@fuel-ts/address';
import { BaseAssetId } from '@fuel-ts/address/configs';
import { bn } from '@fuel-ts/math';
import type {
CallResult,
Coin,
CoinQuantity,
Message,
Resource,
TransactionRequestLike,
} from '@fuel-ts/providers';
import { TransactionResponse, ScriptTransactionRequest, Provider } from '@fuel-ts/providers';
import type { Coin, CoinQuantity, Message, Resource } from '@fuel-ts/providers';
import { ScriptTransactionRequest, Provider } from '@fuel-ts/providers';
import * as providersMod from '@fuel-ts/providers';

import type { TxParamsType } from './account';
import { Account } from './account';
import { FUEL_NETWORK_URL } from './configs';

Expand Down Expand Up @@ -294,149 +285,13 @@ describe('Account', () => {
expect(addResourcesSpy).toHaveBeenCalledWith(resourcesToSpend);
});

it('should execute transfer just as fine', async () => {
const amount = bn(1);
const assetId = '0x0101010101010101010101010101010101010101010101010101010101010101';
const destination = Address.fromAddressOrString(
'0x0202020202020202020202020202020202020202020202020202020202020202'
);
const txParam: TxParamsType = {
gasLimit: bn(1),
gasPrice: bn(1),
maturity: 1,
};

const transactionCost: providersMod.TransactionCost = {
gasUsed: bn(234),
gasPrice: bn(1),
minGasPrice: bn(1),
maxFee: bn(2),
minFee: bn(1),
receipts: [],
requiredQuantities: [],
maxGas: bn(1),
minGas: bn(1),
usedFee: bn(1),
};

const request = new ScriptTransactionRequest();
vi.spyOn(providersMod, 'ScriptTransactionRequest').mockImplementation(() => request);

const transactionResponse = new TransactionResponse('transactionId', provider);

const addCoinOutputSpy = vi.spyOn(request, 'addCoinOutput');

const fundSpy = vi.spyOn(Account.prototype, 'fund').mockImplementation(() => Promise.resolve());

const sendTransactionSpy = vi
.spyOn(Account.prototype, 'sendTransaction')
.mockImplementation(() => Promise.resolve(transactionResponse));

const getTransactionCost = vi
.spyOn(Provider.prototype, 'getTransactionCost')
.mockImplementation(() => Promise.resolve(transactionCost));

const account = new Account(
'0x09c0b2d1a486c439a87bcba6b46a7a1a23f3897cc83a94521a96da5c23bc58db',
provider
);

await account.transfer(destination, amount, assetId, txParam);

expect(addCoinOutputSpy).toHaveBeenCalledTimes(1);
expect(addCoinOutputSpy).toHaveBeenCalledWith(destination, amount, assetId);

expect(getTransactionCost).toHaveBeenCalledTimes(1);

expect(fundSpy).toHaveBeenCalledTimes(1);
expect(fundSpy).toHaveBeenCalledWith(
request,
transactionCost.requiredQuantities,
transactionCost.maxFee
);

expect(sendTransactionSpy).toHaveBeenCalledTimes(1);
expect(sendTransactionSpy).toHaveBeenCalledWith(request);
});

it('should execute withdrawToBaseLayer just fine', async () => {
const recipient = Address.fromRandom();
const txParams: TxParamsType = {};
const amount = bn(1);

const assetId = '0x0101010101010101010101010101010101010101010101010101010101010101';

const request = new ScriptTransactionRequest();

const quantities: CoinQuantity[] = [
{
amount: bn(1),
assetId,
},
];
const cost: providersMod.TransactionCost = {
gasPrice: bn(1),
gasUsed: bn(1),
maxFee: bn(1),
maxGas: bn(1),
minFee: bn(1),
minGas: bn(1),
minGasPrice: bn(1),
receipts: [],
requiredQuantities: quantities,
usedFee: bn(1),
};

const transactionResponse = {} as unknown as TransactionResponse;

const scriptTransactionRequest = vi
.spyOn(providersMod, 'ScriptTransactionRequest')
.mockImplementation(() => request);

const getTransactionCost = vi
.spyOn(providersMod.Provider.prototype, 'getTransactionCost')
.mockImplementation(() => Promise.resolve(cost));

const fund = vi.spyOn(Account.prototype, 'fund').mockImplementation(() => Promise.resolve());

const sendTransaction = vi
.spyOn(Account.prototype, 'sendTransaction')
.mockImplementation(() => Promise.resolve(transactionResponse));

const account = new Account(
'0x09c0b2d1a486c439a87bcba6b46a7a1a23f3897cc83a94521a96da5c23bc58db',
provider
);

let result = await account.withdrawToBaseLayer(recipient, amount, txParams);

expect(result).toEqual(transactionResponse);

expect(scriptTransactionRequest).toHaveBeenCalledTimes(1);

expect(sendTransaction).toHaveBeenCalledTimes(1);
expect(sendTransaction).toHaveBeenCalledWith(request);

expect(getTransactionCost).toHaveBeenCalledTimes(1);
expect(fund).toHaveBeenCalledTimes(1);

// without txParams
result = await account.withdrawToBaseLayer(recipient, amount);

expect(result).toEqual(transactionResponse);

expect(scriptTransactionRequest).toHaveBeenCalledTimes(2);

expect(sendTransaction).toHaveBeenCalledTimes(2);
expect(sendTransaction).toHaveBeenCalledWith(request);
});

it('should execute sendTransaction just fine', async () => {
const transactionRequestLike: TransactionRequestLike = {
const transactionRequestLike: providersMod.TransactionRequestLike = {
type: providersMod.TransactionType.Script,
};
const transactionRequest = new ScriptTransactionRequest();
const transactionResponse = 'transactionResponse' as unknown as TransactionResponse;
const transactionResponse =
'transactionResponse' as unknown as providersMod.TransactionResponse;

const transactionRequestify = vi.spyOn(providersMod, 'transactionRequestify');

Expand Down Expand Up @@ -468,11 +323,11 @@ describe('Account', () => {
});

it('should execute simulateTransaction just fine', async () => {
const transactionRequestLike: TransactionRequestLike = {
const transactionRequestLike: providersMod.TransactionRequestLike = {
type: providersMod.TransactionType.Script,
};
const transactionRequest = new ScriptTransactionRequest();
const callResult = 'callResult' as unknown as CallResult;
const callResult = 'callResult' as unknown as providersMod.CallResult;

const transactionRequestify = vi
.spyOn(providersMod, 'transactionRequestify')
Expand Down
Loading
Loading