Skip to content

Commit

Permalink
Merge branch 'master' into st/docs/migrate-types-snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
Torres-ssf authored Oct 21, 2024
2 parents 5599c6a + bf47c3d commit d70b34b
Show file tree
Hide file tree
Showing 37 changed files with 635 additions and 232 deletions.
4 changes: 4 additions & 0 deletions .changeset/happy-kiwis-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

ci(deps): bump thollander/actions-comment-pull-request from 2 to 3
5 changes: 5 additions & 0 deletions .changeset/honest-jobs-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-fuels": patch
---

build(deps): bump typescript-eslint from 8.5.0 to 8.8.0
4 changes: 4 additions & 0 deletions .changeset/loud-hotels-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

build(deps): bump memfs from 4.11.1 to 4.14.0
8 changes: 8 additions & 0 deletions .changeset/lucky-avocados-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@internal/fuel-core": patch
"@fuel-ts/versions": patch
"@fuel-ts/account": patch
"@fuel-ts/errors": patch
---

chore: upgrading `fuel-core` to `0.40.0`
5 changes: 5 additions & 0 deletions .changeset/popular-seals-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/account": patch
---

feat: implement batch transfer to contracts
5 changes: 5 additions & 0 deletions .changeset/proud-donuts-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-fuels": patch
---

chore: exclude `node_modules` in template tests
4 changes: 4 additions & 0 deletions .changeset/rare-drinks-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

chore: increase benchmark iterations
3 changes: 3 additions & 0 deletions .changeset/selfish-weeks-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
---
ci: add optimized graphql query e2e tests
2 changes: 2 additions & 0 deletions .changeset/thick-geckos-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
10 changes: 5 additions & 5 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ jobs:
run: pnpm test:coverage-diff

- name: Report Coverage
uses: thollander/actions-comment-pull-request@v2
uses: thollander/actions-comment-pull-request@v3
if: ${{ steps.findPr.outputs.number }}
with:
filePath: coverage/report/coverage-diff.txt
pr_number: ${{ (steps.findPr.outputs.number) }}
comment_tag: diff
file-path: coverage/report/coverage-diff.txt
pr-number: ${{ (steps.findPr.outputs.number) }}
comment-tag: diff
mode: recreate
create_if_not_exists: true
create-if-not-exists: true
2 changes: 1 addition & 1 deletion apps/create-fuels-counter-guide/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"postcss": "^8.4.47",
"tailwindcss": "^3.4.12",
"typescript": "~5.6.2",
"typescript-eslint": "^8.5.0",
"typescript-eslint": "^8.8.0",
"vite": "^5.4.8",
"vitest": "~2.0.5"
}
Expand Down
68 changes: 58 additions & 10 deletions apps/docs-snippets/src/guide/cookbook/transferring-assets.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Address, BN, Wallet } from 'fuels';
import { launchTestNode } from 'fuels/test-utils';
import type { ContractTransferParams, ReceiptTransfer } from 'fuels';
import { BN, ReceiptType, Wallet } from 'fuels';
import { launchTestNode, TestAssetId } from 'fuels/test-utils';

import { CounterFactory } from '../../../test/typegen';
import { CounterFactory, TokenFactory } from '../../../test/typegen';

/**
* @group node
Expand Down Expand Up @@ -111,7 +112,7 @@ describe('Transferring Assets', () => {
// #endregion transferring-assets-3
});

it('should successfully prepare transfer transaction request', async () => {
it('should successfully transfer to contract', async () => {
using launched = await launchTestNode({
contractsConfigs: [
{
Expand All @@ -124,25 +125,72 @@ describe('Transferring Assets', () => {
wallets: [sender],
contracts: [deployedContract],
} = launched;
const contractId = Address.fromAddressOrString(deployedContract.id);
// #region transferring-assets-4
// #import { Wallet, BN };

// #context const senderWallet = Wallet.fromPrivateKey('...');
// #context const sender = Wallet.fromPrivateKey('...');

const amountToTransfer = 400;
const assetId = provider.getBaseAssetId();
// #context const contractId = Address.fromAddressOrString('0x123...');
const contractId = deployedContract.id;

const contractBalance = await deployedContract.getBalance(assetId);

const tx = await sender.transferToContract(contractId, amountToTransfer, assetId);
await tx.waitForResult();
expect(new BN(contractBalance).toNumber()).toBe(0);

await tx.waitForResult();

expect(new BN(contractBalance).toNumber()).toBe(0);
expect(new BN(await deployedContract.getBalance(assetId)).toNumber()).toBe(amountToTransfer);
// #endregion transferring-assets-4
});

it('should successfully batch transfer to contracts', async () => {
using launched = await launchTestNode({
contractsConfigs: [
{
factory: CounterFactory,
},
{
factory: TokenFactory,
},
],
});
const {
provider,
wallets: [sender],
contracts: [contract1, contract2],
} = launched;

// #region transferring-assets-5
const baseAssetId = provider.getBaseAssetId();
const assetA = TestAssetId.A.value;

const contractTransferParams: ContractTransferParams[] = [
{
contractId: contract1.id,
amount: 999,
assetId: baseAssetId,
},
{
contractId: contract1.id,
amount: 550,
assetId: assetA,
},
{
contractId: contract2.id,
amount: 200,
assetId: assetA,
},
];

const submit = await sender.batchTransferToContracts(contractTransferParams);
const txResult = await submit.waitForResult();
// #endregion transferring-assets-5

const transferReceipts = txResult.receipts.filter(
(receipt) => receipt.type === ReceiptType.Transfer
) as ReceiptTransfer[];

expect(transferReceipts.length).toBe(contractTransferParams.length);
});
});
57 changes: 57 additions & 0 deletions apps/docs-snippets2/src/cookbook/combining-utxos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// #region combining-utxos
import { Provider, Wallet } from 'fuels';

import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../env';

const provider = await Provider.create(LOCAL_NETWORK_URL);
const fundingWallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider);

const wallet = Wallet.generate({ provider });

// First, lets fund a wallet with 10_000 of the base asset. But as we are doing this across 10 transactions,
// we will end up with 10 UTXOs.
for (let i = 0; i < 10; i++) {
const initTx = await fundingWallet.transfer(
wallet.address,
1000,
provider.getBaseAssetId()
);
await initTx.waitForResult();
}

// We can fetch the coins to see how many UTXOs we have, and confirm it is 10.
const { coins: initialCoins } = await wallet.getCoins(
provider.getBaseAssetId()
);
console.log('Initial Coins Length', initialCoins.length);
// 10

// But we can also confirm the total balance of the base asset for this account is 10_000.
const initialBalance = await wallet.getBalance(provider.getBaseAssetId());
console.log('Initial Balance', initialBalance.toNumber());
// 10_000

// Now we can combine the UTXOs into a single UTXO by performing a single transfer for the
// majority of the balance. Of course, we will still need some funds for the transaction fees.
const combineTx = await wallet.transfer(
wallet.address,
9500,
provider.getBaseAssetId()
);
await combineTx.wait();

// Now we can perform the same validations and see we have less UTXOs.
// We have 2 in this instance, as we have performed the transfer in the base asset:
// a UTXO for our transfer, and another for what is left after paying the fees.
const { coins: combinedCoins } = await wallet.getCoins(
provider.getBaseAssetId()
);
console.log('Combined Coins Length', combinedCoins.length);
// 2

// And we can also confirm the final balance of the base asset for this account is 9_998,
// so the cost of combining is also minimal.
const combinedBalance = await wallet.getBalance(provider.getBaseAssetId());
console.log('Combined Balance', combinedBalance.toNumber());
// 9_998
// #endregion combining-utxos
4 changes: 4 additions & 0 deletions apps/docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ export default defineConfig({
text: 'Resubmitting Failed Transactions',
link: '/guide/cookbook/resubmitting-failed-transactions',
},
{
text: 'Combining UTXOs',
link: '/guide/cookbook/combining-utxos',
},
],
},
{
Expand Down
11 changes: 11 additions & 0 deletions apps/docs/src/guide/cookbook/combining-utxos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Combining UTXOs

When performing a funding operation or calling `getResourcesToSpend`, you may encounter the `MAX_COINS_REACHED` error if the number of coins fetched per asset exceeds the maximum limit allowed by the chain.

You may also want to do this if you want to reduce the number of inputs in your transaction, which can be useful if you are trying to reduce the size of your transaction or you are receiving the `MAX_INPUTS_EXCEEDED` error.

One way to avoid these errors is to combine your UTXOs. This can be done by performing a transfer that combines multiple UTXOs into a single UTXO, where the transaction has multiple inputs for the asset, but a smaller number of outputs.

> **Note:** You will not be able to have a single UTXO for the base asset after combining, as one output will be for the transfer, and you will have another for the fees.
<<< @/../../docs-snippets2/src/cookbook/combining-utxos.ts#combining-utxos{ts:line-numbers}
6 changes: 6 additions & 0 deletions apps/docs/src/guide/errors/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,9 @@ When the number of transaction inputs exceeds the maximum limit allowed by the b
### `MAX_OUTPUTS_EXCEEDED`

When the number of transaction outputs exceeds the maximum limit allowed by the blockchain.

### `MAX_COINS_REACHED`

When performing a funding operation, or calling `getResourcesToSpend`, this error can be thrown if the number of coins fetched per asset exceeds the maximum limit allowed by the blockchain.

This can be avoided by paginating the results of the `getCoins` method to fund your transaction, or by reducing the number of UTXOs for your account. This can be done by performing a transfer that amalgamates your UTXOs, as demonstrated in [this cookbook](../cookbook/combining-utxos.md).
18 changes: 13 additions & 5 deletions apps/docs/src/guide/wallets/wallet-transferring.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ This method also creates a `ScriptTransactionRequest` and populates it with the
<<< @/../../docs-snippets/src/guide/cookbook/transferring-assets.test.ts#transferring-assets-3{ts:line-numbers}

## Transferring Assets To Multiple Wallets

To transfer assets to multiple wallets, use the `Account.batchTransfer` method:

<<< @/../../docs-snippets/src/guide/wallets/wallet-transferring.test.ts#wallet-transferring-6{ts:line-numbers}

## Transferring Assets To Contracts

When transferring assets to a deployed contract, we use the `transferToContract` method, which shares a similar parameter structure with the `transfer` method.
Expand All @@ -42,15 +48,17 @@ Here's an example demonstrating how to use `transferToContract`:

<<< @/../../docs-snippets/src/guide/cookbook/transferring-assets.test.ts#transferring-assets-4{ts:line-numbers}

Always remember to call the `waitForResult()` function on the transaction response. That ensures the transaction has been mined successfully before proceeding.
_Note: Use `transferToContract` exclusively for transfers to a contract. For transfers to an account address, use `transfer` instead._

## Transferring Assets To Multiple Wallets
## Transferring Assets To Multiple Contracts

To transfer assets to multiple wallets, use the `Account.batchTransfer` method:
Similar to the `Account.batchTransfer` method, you can transfer multiple assets to multiple contracts using the `Account.batchTransferToContracts` method. Here's how it works:

<<< @/../../docs-snippets/src/guide/wallets/wallet-transferring.test.ts#wallet-transferring-6{ts:line-numbers}
<<< @/../../docs-snippets/src/guide/cookbook/transferring-assets.test.ts#transferring-assets-5{ts:line-numbers}

Always remember to call the `waitForResult()` function on the transaction response. That ensures the transaction has been mined successfully before proceeding.

This section demonstrates additional examples of transferring assets between wallets and to contracts.
_Note: Use `batchTransferToContracts` solely for transferring assets to contracts. Do not use account addresses with this method. For multiple account transfers, use `batchTransfer` instead._

## Checking Balances

Expand Down
2 changes: 1 addition & 1 deletion internal/benchmarks/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { bench } from 'vitest';

export const isDevnet = process.env.DEVNET_WALLET_PVT_KEY !== undefined;

const iterations = isDevnet ? 1 : 10;
const iterations = isDevnet ? 1 : 20;

export const runBenchmark = (name: string, benchmarkFn: () => Promise<void>) => {
bench(
Expand Down
2 changes: 1 addition & 1 deletion internal/fuel-core/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.39.0
0.40.0
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
"eslint-plugin-tsdoc": "^0.3.0",
"glob": "^10.4.5",
"knip": "^5.30.6",
"memfs": "^4.11.1",
"memfs": "^4.14.0",
"nodemon": "^3.1.7",
"npm-run-all": "^4.1.5",
"nyc": "^17.1.0",
Expand Down
6 changes: 4 additions & 2 deletions packages/account/src/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ describe('Account', () => {
vi.restoreAllMocks();
});

it('should validate max number of inputs when funding the TX', async () => {
it('throws when funding with more than 255 coins for an input', async () => {
using launched = await setupTestProviderAndWallets({
walletsConfig: {
amountPerCoin: 100,
Expand All @@ -920,7 +920,9 @@ describe('Account', () => {
request.maxFee = txCost.maxFee;

await expectToThrowFuelError(() => wallet.fund(request, txCost), {
code: ErrorCode.MAX_INPUTS_EXCEEDED,
code: ErrorCode.MAX_COINS_REACHED,
message:
'The account retrieving coins has exceeded the maximum number of coins per asset. Please consider combining your coins into a single UTXO.',
});
});

Expand Down
Loading

0 comments on commit d70b34b

Please sign in to comment.