-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Prettify typegen API #2686
Comments
@nedsalk What do you think about separating deployment stuff from the rest? I've been questioning our weird suffixes for these files; maybe they could go. Related: import { Counter, deployCounter } from './typegend';
|
I wholeheartedly agree with the direction. I think we could give the users the full factory and have them do whatever they want with it: // counter-factory.ts
import { Account, Provider, ContractFactory } from 'fuels';
import { Counter, abi } from './Counter'
export const counterBytecode = '0x1af03..';
// as a class
export class CounterFactory extends ContractFactory {
constructor(accountOrProvider: Account | Provider | null) {
super(counterBytecode, abi, accountOrProvider);
}
}
// or as a factory function, which is nicer for importing,
// but which could give import problems to those who use multiple factories.
// although who uses multiple factories in their code anyways ... except us in tests :sweat_smile:
export function factory(accountOrProvider: Account | Provider | null = null) {
return new ContractFactory<Counter>(counterBytecode, abi, accountOrProvider);
} This way we wouldn't have any logic in typegen outputs and it'd just be a type wrapper/implementer of the real classes. |
Important All pseudo code. We can use prefixes/sufixes to avoid naming collisions.
// Counter.ts
export interface Counter {
functions: {
get_count: {
inputs: [];
output: BN;
};
increment_count: {
inputs: [amount: BigNumberish];
output: BN;
};
};
configurableConstants: { };
}
export const counterAbi = "...";
export const counterStorageSlots = [];
export function createCounterInterface() {
return new Interface<Counter>(counterAbi);
}
export function createCounter(
id: string | AbstractAddress,
accountOrProvider: Account | Provider
) {
return new Contract<Counter>(id, counterAbi, accountOrProvider);
} // CounterFactory.ts
import { Counter, counterAbi, counterStorageSlots } from './Counter'
export const counterBytecode = '0x1af03..';
export class CounterFactory extends ContractFactory {
constructor(accountOrProvider: Account | Provider | null) {
super(counterBytecode, counterAbi, accountOrProvider);
}
}
export async function factoryCounter(wallet: Account): DeployContractResult {
return new CounterFactory(wallet);
}
export async function deployCounter(
wallet: Account,
options: DeployContractOptions = {}
): Promise<DeployContractResult> {
return factoryCounter(wallet).deployContract({
storageSlots: counterStorageSlots,
...options,
});
} |
It seems users should mainly be concerned with:
|
This is how it should be used: const deploy = await deployCounter(wallet);
const { contract } = await deploy.waitForResult(); Full snippet (with hypothetical unified API): import type { TxParams } from 'fuels';
import { LOCAL_NETWORK_URL, fuels, bn } from 'fuels';
import { WALLET_PVT_KEY } from './env';
import { deployCounter } from './typegend';
const client = await fuels(LOCAL_NETWORK_URL);
const wallet = client.wallet(WALLET_PVT_KEY);
const deploy = await deployCounter(wallet);
const { contract } = await deploy.waitForResult();
const txParams: TxParams = {
gasLimit: bn(69242),
maxFee: bn(69242),
tip: bn(100),
maturity: 1,
witnessLimit: bn(5000),
};
const { waitForResult } = await contract.functions
.increment_count(15) //
.txParams(txParams)
.call();
const {
value,
transactionResult: { isStatusSuccess },
} = await waitForResult();
console.log({ value, isStatusSuccess }); Note @danielbate This is also a port of the |
The end goal is to have
typegen
only output types and integrate those types with the real classes via generic type parameters.typegen
currently outputs code which casts programs as the types it generates. For example, for a simple counter contract which looks like this:The generated outputs are
CounterAbi.d.ts
andCounterAbi__factory.ts
, respectively:The idea is for
CounterAbi.d.ts
to contain an appropriate type representation of the ABI which would be passed toInterface<TAbi>
andContract<TAbi>
classes, removing the need for theas unknown as CounterAbi
casts. Below is an idea of the updatedCounterAbi.d.ts
andCounterAbi__factory.ts
contents, respectively:This same interface can be generated for predicate and script abis:
This approach allows clean integration of logs (#2330) into the same interface as well later down the line, although that issue is not blocked by this one:
The text was updated successfully, but these errors were encountered: