-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
TL;DR
The idea is to provide a facade API composed of interconnected factory methods.
The aim is to shortcut the interaction with fuel nodes by:
- Providing a single
fuelsentry point within thefuelslibrary (aka a provider factory) - The returned object from the previous step should contain module initializers for:
- wallet
- contract
- predicate
- script
- From there, most methods can be chained and used fluidly.
This proposal can enable:
- Intuitive API that doesn't require memorization
- Concise onliners to be easily composed and exchanged
- Seamless usage across different platforms (node, browser)
- Easily digestible code snippets to be used in documentation
- Etc.
A public API crafted around this idea can narrow the user journey to what matters, hiding away most of the internal implementation details (not all) and paving the way for broader refactorings down the road, in which we can change or swap underlying pieces without changing the public APIs, reducing the occurrences of breaking changes.
Pseudo-code
Important
All code samples in this page are pesude code.
API
Here's a rough example of how it would look.
// single import from fuels, the rest comes from the dApps
import { fuels, TESTNET_NETWORK_URL } from 'fuels';
// typegen'd classes
import {
MyContractFactory,
MyContract2Factory,
MyContract3Factory,
} from './sway-api';
// usage example
const options: fuels.Options = { ... };
(await fuels(TESTNET_NETWORK_URL, options))
.contract(MyContractFactory)
.addContracts([ MyContract2Factory, MyContract3Factory ])
.get_counter()
.callParams({
forward: CoinQuantityLike;
gasLimit: BigNumberish;
})
.txParams({
gasPrice: BigNumberish;
gas limit: BigNumberish;
maturity?: number;
maxFee?: BigNumberish;
witnessLimit?: BigNumberish;
variableOutputs: number;
})
.<get|dryRun|simulate|call>();Promises
The fuels entry point is a provider factory that returns a promise.
The promise is resolved after initializing the connection with the node.
From there, the user has everything to move on.
import { fuels, DEVNET_NETWORK_URL } from 'fuels';
import { MyContractFactory } from './sway-api';
fuels(DEVNET_NETWORK_URL)
.then(({ contract ) => {
const counter = contract(MyContractFactory).fns.getCounter().get();
console.log({ counter });
});Callbacks (+ transfer example)
The same can be seamlessly achieved with callbacks.
import { fuels, DEVNET_NETWORK_URL } from 'fuels';
import { MyContractFactory } from './sway-api';
fuels(DEVNET_NETWORK_URL, async ({ wallet, nodeInfo }) => {
const assetId = nodeInfo.getBaseAssetId();
const privateKey = 'abc..xyz';
const amount = 10;
const address = '0x...';
const transfer = await wallet({ privateKey }).transfer(address, amount, assetId);
const balance = await wallet({ address }).getBalance(assetId);
expect(transfer.abc).toEqual(xyz);
expect(balance.toNumber()).toBeGreaterOrEqualThan(amount);
});Oneliners
import { fuels, TESTNET_NETWORK_URL } from 'fuels';
import { MyContract, MyPredicate, MyScript } from './sway-api';
// reading block info
(await fuels(TESTNET_NETWORK_URL)).getBlock();
// provider's methods
(await fuels(TESTNET_NETWORK_URL)).fetchChain();
(await fuels(TESTNET_NETWORK_URL)).<otherProviderMethod>();
// wallet
(await fuels(TESTNET_NETWORK_URL)).wallet("0x...").getBalance();
// contract
(await fuels(TESTNET_NETWORK_URL)).contract(MyContract).fns.get_counter().get();
// predicate
(await fuels(TESTNET_NETWORK_URL)).predicate(MyPredicate).transfer();
// script
(await fuels(TESTNET_NETWORK_URL)).script(MyScript).run();Normalized TX cost estimation
import { fuels, TESTNET_NETWORK_URL } from 'fuels';
import { MyContract, MyPredicate, MyScript } from './sway-api';
const client = await fuels(TESTNET_NETWORK_URL);
const cost1 = await client.contract(MyContract).fns.get_counter().estimateCost();
const cost2 = await client.predicate(MyPredicate).fns.main().estimateCost();
const cost3 = await client.script(MyScript).fns.main().estimateCost();
console.log({ cost1, cost2, cost3 });Custom TX Builder
TBD