fuels-ts icon indicating copy to clipboard operation
fuels-ts copied to clipboard

feat!: prettify `typegen` api

Open arboleya opened this issue 1 year ago • 3 comments

  • Closes #2686
  • Closes #2707

Release notes

In this release, we:

  • Made typegend API more straightforward and ergonomic

Summary

Parts of our great experience are shipped through the RTypegend files, which contain part of the boilerplate necessary to make some things work. This PR revisits these templates and trims them nicely to support a more ergonomic and intuitive API.

All main Typegen templates have changed:

  1. Contract
  2. ContractFactory ⁽¹⁾
  3. Script
  4. Predicate

⁽¹⁾ Contract bytecode lives inside the Factory class now, no more .hex.ts files

To follow these changes, we also modified:

  • launchTestNode utility
  • Predicate class

Special thanks ❤️

Goes to @petertonysmith94, for the rigorous reviews and additional API prettification via:

  • https://github.com/FuelLabs/fuels-ts/pull/2876.

Also, thank you to @nedsalk for all the involvement and for not letting this fade out on the side during such an agitated moment. Releasing this will undoubtedly pave the way for other good things to happen!

Breaking Changes

Predicate class

  • Predicate class constructor parameters renamed: inputData > data
// before
import { Predicate } from 'fuels';

const predicate = new Predicate({
  ...unchangedParameters,
  inputData,
});
// after
import { Predicate } from 'fuels';

const predicate = new Predicate({
  ...unchangedParameters,
  data,
});
  • Typegen extended/generated Predicate now accepts a single parameter for initialization
// before
import { TestPredicateAbi__factory } from './typegend';

TestPredicateAbi__factory.createInstance(provider, data, configurableConstants);
// after
import { TestPredicate } from './typegen';

new TestPredicate({
  provider,
  data,
  configurableConstants
});

launchTestNode utility

  • Renamed contractsConfigs[].deployer to contractsConfigs[].factory
  • Removed contractsConfigs[].bytecode and .hex.ts file

The bytecode is now saved within the factory class, so you don't have to deal with it.

// before
import { TokenAbi__factory } from './typegend';
import TokenAbiHex from './typegend/contracts/TokenAbi.hex';

using launched = await launchTestNode({
  contractsConfigs: [{
    deployer: TokenAbi__factory,
    bytecode: TokenAbiHex
  }],
});
// after
import { TokenFactory } from './typegend';

using launched = await launchTestNode({
  contractsConfigs: [{
    factory: TokenFactory,
  }],
})

Renamed method deployContract to deploy

Removed the redundant suffix on the ContractFactory class method name.

// before
import { ContractFactory } from 'fuels';

const factory = new ContractFactory(wallet);

factory.deployContract();
// after
import { ContractFactory } from 'fuels';

const factory = new ContractFactory(wallet);

factory.deploy();

Typegend Contract template

  • Removed Abi__factory suffix from class names
  • The file <name>.hex was removed (access it via <Name>.bytecode)
  • The files <name>__factory.ts and <name>.d.dts were merged into <name>.ts
  • The class <Name> and the interface <Name>Abi are now just <Name>
// before
import { TestContractAbi, TestContract__factory } from './typegen'
import testContractBytecode from './typegen/contracts/TestContract.hex'

const instance: TestContractAbi = await TestContract__factory.connect(id, wallet);

const deploy = await TestContract__factory.deployContract(testContractBytecode, wallet);
const { contract } = await deploy.waitForResult();
// after
import { TestContract, TestContractFactory } from './typegen'

const instance = new TestContract(id, wallet);

const deploy = await TestContractFactory.deploy(wallet);
const { contract } = await deploy.waitForResult();

Typegend Predicate template

  • Removed Abi__factory suffix from class names
  • Started accepting a single param object in constructor
// before
import { TestPredicateAbi__factory } from './typegen'

const predicate = TestPredicateAbi__factory.createInstance(provider);
// after
import { TestPredicate } from './typegen'

const predicate = new TestPredicate({ provider });

Typegend Script template

  • Removed Abi__factory suffix from class names
// before
import { TestPredicateAbi__factory } from './typegen'

const script = TestScriptAbi__factory.createInstance(wallet);
// after
import { TestPredicate } from './typegen'

const script = new TestScript(wallet);

Checklist

  • [x] I addedtests to prove my changes
  • [x] I updated — all the necessary docs
  • [x] I reviewed — the entire PR myself, using the GitHub UI
  • [x] I described — all breaking changes and the Migration Guide

arboleya avatar Jul 23 '24 23:07 arboleya

Outlining the foundation and current state of each template.

typegen

arboleya avatar Jul 23 '24 23:07 arboleya

  1. In the breaking changes section, the typegend Predicate before and after are using wallet whereas they should be using provider:
// before
const predicate = TestPredicateAbi__factory.createInstance(wallet);
// should be
const predicate = TestPredicateAbi__factory.createInstance(provider);

// after
const predicate = new TestPredicate({ wallet }); 
// should be
const predicate = new TestPredicate({ provider });
  1. In the Script example in the "after" section, the typegend script takes in a wallet argument but it's part of an object { wallet } whereas it should be used directly:
// after
const script = new TestScript({ wallet });
// should be
const script = new TestScript(wallet);

nedsalk avatar Aug 01 '24 19:08 nedsalk

Coverage Report:

Lines Branches Functions Statements
79.51%(+0%) 71.75%(-0.05%) 77.49%(+0.01%) 79.65%(+0%)
Changed Files:
Ok File (✨=New File) Lines Branches Functions Statements
✨ packages/abi-typegen/src/templates/contract/main.ts 100%
(+100%)
100%
(+100%)
100%
(+100%)
100%
(+100%)
✨ packages/abi-typegen/src/templates/predicate/main.ts 100%
(+100%)
100%
(+100%)
100%
(+100%)
100%
(+100%)
✨ packages/abi-typegen/src/templates/script/main.ts 100%
(+100%)
100%
(+100%)
100%
(+100%)
100%
(+100%)
🔴 packages/abi-typegen/src/templates/utils/formatEnums.ts 100%
(+0%)
50%
(-50%)
100%
(+0%)
100%
(+0%)
🔴 packages/abi-typegen/src/templates/utils/formatStructs.ts 100%
(+0%)
50%
(-50%)
100%
(+0%)
100%
(+0%)

github-actions[bot] avatar Aug 06 '24 12:08 github-actions[bot]

@arboleya after this change, whenever I rebuild locally, the old factories remain in place:

contracts/factories/TestContractAbi__factory.ts

Then I have experienced type errors:

template-nextjs:build: Type error: Property 'deployContract' does not exist on type 'ContractFactory'.
template-nextjs:build: 
template-nextjs:build:   102 |     const factory = new ContractFactory(bytecode, _abi, wallet);
template-nextjs:build:   103 |
template-nextjs:build: > 104 |     return factory.deployContract<TestContractAbi>({
template-nextjs:build:       |                    ^
template-nextjs:build:   105 |       storageSlots: _storageSlots,
template-nextjs:build:   106 |       ...options,
template-nextjs:build:   107 |     });

May it be worth deleting the typegen folder before a typegen build?

petertonysmith94 avatar Aug 07 '24 06:08 petertonysmith94

@petertonysmith94 Deleting things is always very dangerous.

However, these old files should not be a problem if they're just there and never imported.

The error you pasted looks valid, no? The deployContract method was renamed to deploy.

arboleya avatar Aug 07 '24 10:08 arboleya

@arboleya You're right - deleting does seem dangerous.

The error is valid and will cause issues if consumers have TS checking across their project.

Maybe we could add an advisory in the release notes that this factory folder should be deleted?

petertonysmith94 avatar Aug 07 '24 11:08 petertonysmith94

Oh, this is a very specific tip.

Would you mind editing the PR description and adding this mention?

It will be re-fetched and used in the changelog before the next release.

arboleya avatar Aug 08 '24 15:08 arboleya