Skip to content

Commit

Permalink
feat: implement get method on BaseInvocationScope (#1860)
Browse files Browse the repository at this point in the history
  • Loading branch information
Torres-ssf committed Mar 14, 2024
1 parent 4c912c6 commit b8c3401
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 182 deletions.
5 changes: 5 additions & 0 deletions .changeset/small-falcons-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/program": patch
---

implement `get` method on `BaseInvocationScope`
6 changes: 2 additions & 4 deletions apps/demo-fuels/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('ExampleContract', () => {
expect((<Error>error).message).toMatch('not enough coins to fit the target');
});

it('should throw when dry running via contract factory with wallet with no resources', async () => {
it('should not throw when dry running via contract factory with wallet with no resources', async () => {
const provider = await Provider.create(FUEL_NETWORK_URL);
const fundedWallet = await generateTestWallet(provider, [[500_000, BaseAssetId]]);
const unfundedWallet = Wallet.generate({ provider });
Expand All @@ -83,9 +83,7 @@ describe('ExampleContract', () => {
const contract = await factory.deployContract({ gasPrice });
const contractInstance = SampleAbi__factory.connect(contract.id, unfundedWallet);

const { error } = await safeExec(() => contractInstance.functions.return_input(1337).dryRun());

expect((<Error>error).message).toMatch('not enough coins to fit the target');
await expect(contractInstance.functions.return_input(1337).dryRun()).resolves.not.toThrow();
});

it('should demo how to use generated files just fine', async () => {
Expand Down
6 changes: 2 additions & 4 deletions apps/demo-typegen/src/demo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ it('should throw when simulating via contract factory with wallet with no resour
expect((<Error>error).message).toMatch('not enough coins to fit the target');
});

it('should throw when dry running via contract factory with wallet with no resources', async () => {
it('should not throw when dry running via contract factory with wallet with no resources', async () => {
const provider = await Provider.create(FUEL_NETWORK_URL);
const fundedWallet = await generateTestWallet(provider, [[500_000, BaseAssetId]]);
const unfundedWallet = Wallet.generate({ provider });
Expand All @@ -114,9 +114,7 @@ it('should throw when dry running via contract factory with wallet with no resou
const contract = await factory.deployContract({ gasPrice });
const contractInstance = DemoContractAbi__factory.connect(contract.id, unfundedWallet);

const { error } = await safeExec(() => contractInstance.functions.return_input(1337).dryRun());

expect((<Error>error).message).toMatch('not enough coins to fit the target');
await expect(contractInstance.functions.return_input(1337).dryRun()).resolves.not.toThrow();
});

test('Example script', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { Provider } from 'fuels';
import { BaseAssetId, Contract } from 'fuels';

import { DocSnippetProjectsEnum } from '../../../test/fixtures/forc-projects';
import { createAndDeployContractFromProject, getTestWallet } from '../../utils';

/**
* @group node
*/
describe(__filename, () => {
let counterContract: Contract;
let provider: Provider;
beforeAll(async () => {
counterContract = await createAndDeployContractFromProject(DocSnippetProjectsEnum.COUNTER);
provider = counterContract.provider;
});

it('should successfully use "get" to read from the blockchain', async () => {
await counterContract.functions.increment_count(1).call();

const { id: contractId, interface: abi } = counterContract;

// #region interacting-with-contracts-1
const contract = new Contract(contractId, abi, provider);

const { value } = await contract.functions.get_count().get();
// #endregion interacting-with-contracts-1
expect(value.toNumber()).toBeGreaterThanOrEqual(1);
});

it('should successfully use "dryRun" to validate a TX without a wallet', async () => {
const { id: contractId, interface: abi } = counterContract;

// #region interacting-with-contracts-2
const contract = new Contract(contractId, abi, provider);

const { value } = await contract.functions.increment_count(1).dryRun();
// #endregion interacting-with-contracts-2
expect(value.toNumber()).toBeGreaterThanOrEqual(1);
});

it('should successfully use "simulate" to validate if wallet can pay for transaction', async () => {
const { id: contractId, interface: abi } = counterContract;

const fundedWallet = await getTestWallet([[1000, BaseAssetId]]);

// #region interacting-with-contracts-3
const contract = new Contract(contractId, abi, fundedWallet);

const { value } = await contract.functions.increment_count(10).simulate();
// #endregion interacting-with-contracts-3
expect(value.toNumber()).toBeGreaterThanOrEqual(10);
});

it('should successfully execute a contract call without a wallet', async () => {
const contract = counterContract;

// #region interacting-with-contracts-4
await contract.functions.increment_count(10).call();
// #endregion interacting-with-contracts-4

const { value } = await contract.functions.get_count().get();
expect(value.toNumber()).toBeGreaterThanOrEqual(10);
});
});

This file was deleted.

4 changes: 2 additions & 2 deletions apps/docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ export default defineConfig({
link: '/guide/contracts/managing-deployed-contracts',
},
{
text: 'Simulate Transactions',
link: '/guide/contracts/simulate-transactions',
text: 'Interacting With Contracts',
link: '/guide/contracts/interacting-with-contracts',
},
{
text: 'Transaction Parameters',
Expand Down
31 changes: 31 additions & 0 deletions apps/docs/src/guide/contracts/interacting-with-contracts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Interacting With Contracts

There are 4 ways to interact with contracts: `get`, `dryRun`, `simulate`, `call`.

## `get`

The `get` method should be used to read data from the blockchain without using resources. It can be used with an unfunded wallet or even without a wallet at all:

<<< @/../../docs-snippets/src/guide/contracts/interacting-with-contracts.test.ts#interacting-with-contracts-1{ts:line-numbers}

## `dryRun`

The `dryRun` method should be used to dry-run a contract call. It does not spend resources and can be used with an unfunded wallet or even without a wallet at all:

<<< @/../../docs-snippets/src/guide/contracts/interacting-with-contracts.test.ts#interacting-with-contracts-2{ts:line-numbers}

## `simulate`

The `simulate` method should be used to dry-run a contract call, ensuring that the wallet used has sufficient funds to cover the transaction fees, without consuming any resources.

A funded wallet it's required:

<<< @/../../docs-snippets/src/guide/contracts/interacting-with-contracts.test.ts#interacting-with-contracts-3{ts:line-numbers}

## `call`

The `call` method should be used to submit a real contract call transaction to the node.

Real resources are consumed, and any operations executed by the contract function will be processed on the blockchain.

<<< @/../../docs-snippets/src/guide/contracts/interacting-with-contracts.test.ts#interacting-with-contracts-4{ts:line-numbers}
46 changes: 0 additions & 46 deletions apps/docs/src/guide/contracts/simulate-transactions.md

This file was deleted.

11 changes: 4 additions & 7 deletions packages/account/src/providers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ export type TransactionCost = {
minFee: BN;
maxFee: BN;
usedFee: BN;
outputVariables: number;
missingContractIds: string[];
estimatedInputs: TransactionRequest['inputs'];
};
// #endregion cost-estimation-1

Expand Down Expand Up @@ -815,13 +818,7 @@ export default class Provider {
estimatePredicates = true,
resourcesOwner,
}: TransactionCostParams = {}
): Promise<
TransactionCost & {
estimatedInputs: TransactionRequest['inputs'];
outputVariables: number;
missingContractIds: string[];
}
> {
): Promise<TransactionCost> {
const txRequestClone = clone(transactionRequestify(transactionRequestLike));
const chainInfo = this.getChain();
const { gasPriceFactor, minGasPrice, maxGasPerTx } = this.getGasConfig();
Expand Down
1 change: 1 addition & 0 deletions packages/errors/src/error-codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export enum ErrorCode {
// wallet / account
INVALID_PASSWORD = 'invalid-password',
ACCOUNT_REQUIRED = 'account-required',
UNLOCKED_WALLET_REQUIRED = 'unlocked-wallet-required',

// chain
LATEST_BLOCK_UNAVAILABLE = 'latest-block-unavailable',
Expand Down
Loading

0 comments on commit b8c3401

Please sign in to comment.