Skip to content

v0.94.0

Compare
Choose a tag to compare
@fuel-service-user fuel-service-user released this 20 Aug 00:38
· 209 commits to master since this release
d64db24

Summary

In this release, we:

  • Cached Message resources upon transaction submission
  • Made typegen API more straightforward and ergonomic
  • Reduced required roundtrips & bandwidth for submitting TXs
  • Made ContractFactory.deployAsBlobTx a non-blocking call
  • Upgraded forc to v0.63.0 & v0.63.1
  • Added support for the new ABI spec (#596, #599)
  • Improved the bytecode compression for Typegen, making files 40%+ smaller
  • Improved the type handling for () and Option<T> types
  • Upgraded fuel-core to v0.32.1
  • Implemented deploying large contracts using blob transactions
  • Fixed forc and fuel-core version reporting on typegen-generated files
  • Fixed getInputFromAssetId so it returns the correct InputCoin and InputMessage
  • Upgraded fuel-core to v0.33.0
  • Added createAssetId function to create a native AssetId type
  • Added validation for max. input limit exceeded, as per the consensus parameters
  • Removed FUEL_NETWORK_URL and LOCAL_NETWORK_URL constants
  • Removed generateTestWallet, seedTestWallet and launchNodeAndGetWallets utilities
  • Renamed testing class AssetId to TestAssetId

Breaking


Features

Fixes

Chores


Migration Notes

Features

#2872 - Consider message on resources cache

The provider option flag cacheUtxo was renamed to resourceCacheTTL

// before
const provider = await Provider.create(FUEL_NETWORK_URL, {
  cacheUtxo: 5000,
});


using launched = await launchTestNode({
  providerOptions: {
    cacheUtxo: 5000,
  },
});
// after
const provider = await Provider.create(FUEL_NETWORK_URL, {
  resourceCacheTTL: 5000,
});

using launched = await launchTestNode({
  providerOptions: {
    resourceCacheTTL: 5000,
  },
});

#2824 - Prettify typegen api

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();

Typegen 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>
  • Method <Name>Factory.deployContract() renamed to <Name>Factory.deploy()
  • You may need to remove the previously generated <typegenDir>/contracts/factories directory
// before
import { TestContractAbi, TestContract__factory } from './typegen'
import testContractBytecode from './typegen/contracts/TestContract.hex'

const instance = 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();

Typegen Predicate template

  • Removed Abi__factory suffix from class names
  • Started accepting a single param object in constructor
  • You may need to remove the previously generated <typegenDir>/predicates/factories directory
// before
import { TestPredicateAbi__factory } from './typegen'

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

const predicate = new TestPredicate({ provider });

Typegen Script template

  • Removed Abi__factory suffix from class names
  • You may need to remove the previously generated <typegenDir>/scripts/factories directory
// before
import { TestPredicateAbi__factory } from './typegen'

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

const script = new TestScript(wallet);

#2962 - Read malleable fields from transaction status on subscription

Removed TransactionResult.gqlTransaction. You can use the TransactionResult.transaction field and other fields on the response instead, which have all the data that TransactionResult.gqlTransaction has.

// before
const { gqlTransaction } = await new TransactionResponse('your-tx-id').waitForResult();
// after
const { transaction, id, fee, ...rest } = await new TransactionResponse('your-tx-id').waitForResult();

#2929 - Non-blocking blob deployment

The transaction ID from a contract deployment is now returned as a promise.

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

const factory = new ContractFactory(bytecode, abi, wallet);
const { waitForResult, contractId, transactionId } = await factory.deploy();
console.log(transactionId); // 0x123....
// after
import { ContractFactory } from 'fuels'; 

const factory = new ContractFactory(bytecode, abi, wallet);
const { waitForResult, contractId, waitForTransactionId } = await factory.deploy();
const transactionId = await waitForTransactionId();
console.log(transactionId); // 0x123....

#2856 - Adding abi transpiler

New ABI spec

The SDK now adheres to the new specs introduced via:

Check these out to understand all its changes.

AbiCoder is no longer available to import

The class AbiCoder is no longer exported, and the way to do encoding and decoding of specific types is now via the Interface.encodeType and Interface.decodeType methods:

// before
const abi = yourAbi;
const functionArg = abi.functions.inputs[0];

const encoded = AbiCoder.encode(abi, functionArg, valueToEncode);
const decoded = AbiCoder.decode(abi, functionArg, valueToDecode, 0);
// after
import { Interface } from 'fuels';

const abi = yourAbi;
const functionArg = abi.functions.inputs[0];

const abiInterface = new Interface(abi);

const encoded = abiInterface.encodeType(functionArg.concreteTypeId, valueToEncode);
const decoded = abiInterface.decodeType(functionArg.concreteTypeId, valueToDecode);

Interface.findTypeById has been removed

Previously, you could get a type from the ABI via the Interface.findTypeById. This method was removed after introducing the new abi specification because the concept of a type has been split into concrete and metadata types. If you want a specific type, you can get it directly from the ABI.

// before
const abiInterface = new Interface(abi);

// internally this method searched the abi types:
// abi.types.find(t => t.typeId === id);
const type = abiInterface.findTypeById(id);
// after
import { Interface } from 'fuels';

// search the types on the abi directly
const concreteType = abi.concreteTypes.find(ct => ct.concreteTypeId === id);
const metadataType = abiInterface.jsonAbi.metadataTypes.find(mt => mt.metadataTypeId === id);

JsonAbiArgument is no longer exported

The JsonAbiArgument type isn't part of the new ABI spec (#596, #599) as such so we stopped exporting it. Its closest equivalent now would be a concrete type because it fully defines a type.

// before
const arg: JsonAbiArgument = {...};
// after
import { Interface } from 'fuels';

type ConcreteType = JsonAbi["concreteTypes"][number]
const arg: ConcreteType = {...};

#2777 - Improve () and Option<T> type handling

  • () and Option<T> Sway types are now either required or optional, dependent on where the argument appears in the function arguments.

Given these Sway functions:

fn type_then_void_then_type(x: u8, y: (), z: u8) -> ()
fn type_then_void_then_void(x: u8, y: (), z: ()) -> ()

fn type_then_option_then_type(x: u8, y: Option<u8>, z: u8) -> ()
fn type_then_option_then_option(x: u8, y: Option<u8>, z: Option<u8>) -> ()

This is what changes:

// before
contract.functions.type_then_void_then_type(42, 43)
contract.functions.type_then_void_then_void(42) // Unchanged

contract.functions.type_then_option_then_type(42, undefined, 43)
contract.functions.type_then_option_then_option(42, undefined, undefined)
// after
contract.functions.type_then_void_then_type(42, undefined, 43)
contract.functions.type_then_void_then_void(42) // Unchanged 

contract.functions.type_then_option_then_type(42, undefined, 43)
contract.functions.type_then_option_then_option(42)

#2827 - [email protected] and large contract deployments

MAX_CONTRACT_SIZE is no longer exported, it should now be fetched from the chain.

// before
import { MAX_CONTRACT_SIZE } from 'fuels';
// after
import { Provider, FUEL_NETWORK_URL } from 'fuels'; 

const provider = await Provider.create(FUEL_NETWORK_URL);
const { consensusParameters } = provider.getChain();
const maxContractSize = consensusParameters.contractParameters.contractMaxSize.toNumber();

Fixes

#2963 - Assembly process for account transfer operation

The getTransferOperations helper function now requires an additional baseAssetId parameter.

// before
const transferOperations = getTransferOperations({ inputs, outputs, receipts })
// after
const transferOperations = getTransferOperations({ inputs, outputs, receipts, baseAssetId })

Chores

#2915 - Deprecate FUEL_NETWORK_URL and LOCAL_NETWORK_URL

Removed FUEL_NETWORK_URL constant.

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

const provider = await Provider.create(FUEL_NETWORK_URL);
// after
const provider = await Provider.create('https://127.0.0.1:4000/v1/graphql');

Removed LOCAL_NETWORK_URL constant.

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

const provider = await Provider.create(LOCAL_NETWORK_URL);
// after
const provider = await Provider.create('https://127.0.0.1:4000/v1/graphql');

#2811 - Integrate launchTestNode in remaining packages

Removed generateTestWallet and seedTestWallet utilities.

// before
import { bn } from "@fuel-ts/math";
import {
  seedTestWallet,
  generateTestWallet,
} from "@fuel-ts/account/test-utils";

const provider = await Provider.create("http://127.0.0.1:4000/v1/graphql");

// seeding
const walletA = Wallet.fromPrivateKey("0x...", provider);
const baseAssetId = provider.getBaseAssetId();
seedTestWallet(wallet, [{ assetId: baseAssetId, amount: bn(100_000) }]);

// generating
const walletB = await generateTestWallet(provider, [[1_000, baseAssetId]]);
// after
import { launchTestNode } from 'fuels/test-utils';

// create two wallets seeded with 100_000 units of the base asset
using launched = await launchTestNode({
  walletsConfig: {
    count: 2,
    amountPerCoin: 100_000,
  },
});

const {
  wallets: [walletA, walletB]
} = launched;

const balance = await walletA.getBalance() // 100_000

Removed launchNodeAndGetWallets utility.

// before
import { launchNodeAndGetWallets } from 'fuels/test-utils';

const { provider, wallets } = await launchNodeAndGetWallets();
// after
import { launchTestNode } from 'fuels/test-utils';

using launched = await launchTestNode();

const { provider, wallets } = launched;

#2964 - Wrap subscriptions in promise

// before
const subscription = provider.operations.statusChange({ transactionId });
for await (const response of subscription) { ... }

const submittedTxSubscription = this.operations.submitAndAwait({ encodedTransaction: '0x' });
// after
const subscription = await provider.operations.statusChange({ transactionId });
for await (const response of subscription) { ... }

const submittedTxSubscription = await this.operations.submitAndAwait({ encodedTransaction: '0x' });

#2905 - Renamed AssetId to TestAssetId

Renamed testing class AssetId to TestAssetId.

// before
import { AssetId } from 'fuels/test-utils';

const [assetA] = AssetId.random();
// after
import { TestAssetId } from 'fuels/test-utils';

const [assetA] = TestAssetId.random();