Skip to content

Commit

Permalink
feat: better typegen contract factory integration with `launchTestNod…
Browse files Browse the repository at this point in the history
…e` (#3398)

* feat: better typegen contract factory integration with `launchTestNode`

* give name to type

* remove type assertion to improve inference

* update docs to new approach

* changeset

* revert unnecessary change

* rerun workflows

* revert change

* give name to intermediary type

---------

Co-authored-by: Chad Nehemiah <[email protected]>
  • Loading branch information
nedsalk and maschad authored Nov 19, 2024
1 parent c904a98 commit 6ab3e6b
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 43 deletions.
5 changes: 5 additions & 0 deletions .changeset/twenty-needles-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/contract": patch
---

feat: better typegen contract factory integration with `launchTestNode`
2 changes: 1 addition & 1 deletion apps/docs-snippets2/src/testing/launching-a-test-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ customLaunchTestNode.cleanup();
import { CounterFactory } from '../typegend/contracts/CounterFactory';

using launchedContractNode = await launchTestNode({
contractsConfigs: [{ factory: CounterFactory }],
contractsConfigs: [CounterFactory],
});

const {
Expand Down
32 changes: 27 additions & 5 deletions packages/contract/src/test-utils/launch-test-node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,37 @@ describe('launchTestNode', () => {
expect(response.value).toBe(true);
});

test('a contract can be deployed by passing the static factory method directly', async () => {
using launched = await launchTestNode({
contractsConfigs: [
{
deploy: async (wallet, options) => {
const factory = new ContractFactory(binHexlified, abiContents, wallet);
return factory.deploy(options);
},
},
],
});

const {
contracts: [contract],
wallets: [wallet],
} = launched;

const { waitForResult } = await contract.functions.test_function().call();
const response = await waitForResult();
expect(response.value).toBe(true);

expect(contract.account).toEqual(wallet);
});

test('multiple contracts can be deployed', async () => {
using launched = await launchTestNode({
contractsConfigs: [
{
factory: {
deploy: async (wallet, options) => {
const factory = new ContractFactory(binHexlified, abiContents, wallet);
return factory.deploy(options);
},
deploy: async (wallet, options) => {
const factory = new ContractFactory(binHexlified, abiContents, wallet);
return factory.deploy(options);
},
},
{
Expand Down
58 changes: 36 additions & 22 deletions packages/contract/src/test-utils/launch-test-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,22 @@ export interface DeployableContractFactory {
deploy(wallet: Account, options?: DeployContractOptions): Promise<DeployContractResult>;
}

export interface DeployContractConfig {
/**
* Contract factory class outputted by `pnpm fuels typegen`.
*/
factory: DeployableContractFactory;
/**
* Options for contract deployment taken from `ContractFactory`.
*/
options?: DeployContractOptions;
/**
* Index of wallet to be used for deployment. Defaults to `0` (first wallet).
*/
walletIndex?: number;
}
export type DeployContractConfig =
| DeployableContractFactory
| {
/**
* Contract factory class outputted by `pnpm fuels typegen`.
*/
factory: DeployableContractFactory;
/**
* Options for contract deployment taken from `ContractFactory`.
*/
options?: DeployContractOptions;
/**
* Index of wallet to be used for deployment. Defaults to `0` (first wallet).
*/
walletIndex?: number;
};

export interface LaunchTestNodeOptions<TContractConfigs extends DeployContractConfig[]>
extends LaunchCustomProviderAndGetWalletsOptions {
Expand All @@ -38,10 +40,23 @@ export interface LaunchTestNodeOptions<TContractConfigs extends DeployContractCo
*/
contractsConfigs: TContractConfigs;
}

type ExtractDeployedContract<
T extends DeployContractConfig,
Deploy extends DeployableContractFactory['deploy'] = T extends DeployableContractFactory
? T['deploy']
: T extends {
factory: DeployableContractFactory;
}
? T['factory']['deploy']
: never,
WaitForResult extends DeployContractResult['waitForResult'] = Awaited<
ReturnType<Deploy>
>['waitForResult'],
> = Awaited<ReturnType<WaitForResult>>['contract'];

export type TContracts<T extends DeployContractConfig[]> = {
[K in keyof T]: Awaited<
ReturnType<Awaited<ReturnType<T[K]['factory']['deploy']>>['waitForResult']>
>['contract'];
[K in keyof T]: ExtractDeployedContract<T[K]>;
};
export interface LaunchTestNodeReturn<TFactories extends DeployContractConfig[]>
extends SetupTestProviderAndWalletsReturn {
Expand Down Expand Up @@ -105,7 +120,7 @@ function getFuelCoreArgs<TFactories extends DeployContractConfig[]>(
}

function getWalletForDeployment(config: DeployContractConfig, wallets: WalletUnlocked[]) {
if (!config.walletIndex) {
if (!('walletIndex' in config) || !config.walletIndex) {
return wallets[0];
}

Expand Down Expand Up @@ -144,10 +159,9 @@ export async function launchTestNode<const TFactories extends DeployContractConf
try {
for (let i = 0; i < configs.length; i++) {
const config = configs[i];
const { waitForResult } = await config.factory.deploy(
getWalletForDeployment(config, wallets),
config.options ?? {}
);
const deploy = 'factory' in config ? config.factory.deploy : config.deploy;
const options = 'factory' in config ? (config.options ?? {}) : {};
const { waitForResult } = await deploy(getWalletForDeployment(config, wallets), options);
const { contract } = await waitForResult();
contracts.push(contract);
}
Expand Down
14 changes: 2 additions & 12 deletions packages/fuel-gauge/src/contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {
launchTestNode,
TestAssetId,
} from 'fuels/test-utils';
import type { DeployContractConfig } from 'fuels/test-utils';

import {
CallTestContract,
Expand All @@ -42,23 +41,14 @@ import { PredicateTrue } from '../test/typegen/predicates/PredicateTrue';

import { launchTestContract } from './utils';

const contractsConfigs: DeployContractConfig[] = [
{
factory: CallTestContractFactory,
},
{
factory: CallTestContractFactory,
},
];
const contractsConfigs = [CallTestContractFactory, CallTestContractFactory];

const txPointer = '0x00000000000000000000000000000000';

const AltToken = '0x0101010101010101010101010101010101010101010101010101010101010101';

function setupTestContract() {
return launchTestContract({
factory: CallTestContractFactory,
});
return launchTestContract(CallTestContractFactory);
}

/**
Expand Down
4 changes: 1 addition & 3 deletions packages/fuel-gauge/src/coverage-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ enum MixedNativeEnum {
}

function setupContract() {
return launchTestContract({
factory: CoverageContractFactory,
});
return launchTestContract(CoverageContractFactory);
}

/**
Expand Down

0 comments on commit 6ab3e6b

Please sign in to comment.