From c5049e5b18e9c12eb0d6ef55ebad0461524b14ca Mon Sep 17 00:00:00 2001 From: chad Date: Wed, 17 Jul 2024 16:15:03 -0500 Subject: [PATCH 01/13] fix: ensure correct message input is returned based on spec --- .../providers/transaction-summary/input.test.ts | 17 ++++++++++++++++- .../src/providers/transaction-summary/input.ts | 5 +---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/account/src/providers/transaction-summary/input.test.ts b/packages/account/src/providers/transaction-summary/input.test.ts index 591ea4113f8..79f97a1a9f2 100644 --- a/packages/account/src/providers/transaction-summary/input.test.ts +++ b/packages/account/src/providers/transaction-summary/input.test.ts @@ -1,5 +1,6 @@ import { ZeroBytes32 } from '@fuel-ts/address/configs'; -import type { InputCoin } from '@fuel-ts/transactions'; +import { bn } from '@fuel-ts/math'; +import type { InputCoin, InputMessage } from '@fuel-ts/transactions'; import { ASSET_A } from '@fuel-ts/utils/test-utils'; import { @@ -120,4 +121,18 @@ describe('transaction-summary/input', () => { MOCK_INPUT_MESSAGE ); }); + + it('should ensure getInputFromAssetId returns input message if the coin input amount is 0', () => { + const inputMessage: InputMessage = { + ...MOCK_INPUT_MESSAGE, + amount: bn(100), + }; + + const coinInput: InputCoin = { + ...MOCK_INPUT_COIN, + amount: bn(0), + }; + + expect(getInputFromAssetId([inputMessage, coinInput], ASSET_A)).toEqual(inputMessage); + }); }); diff --git a/packages/account/src/providers/transaction-summary/input.ts b/packages/account/src/providers/transaction-summary/input.ts index 6acb9ece782..96b5b12e6c7 100644 --- a/packages/account/src/providers/transaction-summary/input.ts +++ b/packages/account/src/providers/transaction-summary/input.ts @@ -37,10 +37,7 @@ export function getInputFromAssetId(inputs: Input[], assetId: string) { const coinInputs = getInputsCoin(inputs); const messageInputs = getInputsMessage(inputs); const coinInput = coinInputs.find((i) => i.assetId === assetId); - // TODO: should include assetId in InputMessage as well. for now we're mocking ETH - const messageInput = messageInputs.find( - (_) => assetId === '0x0000000000000000000000000000000000000000000000000000000000000000' - ); + const messageInput = messageInputs.find(({ amount }) => !!amount && amount.gt(0)); return coinInput || messageInput; } From 201fa2f52a73301a8e5f04500d8a3ded27c00840 Mon Sep 17 00:00:00 2001 From: chad Date: Wed, 17 Jul 2024 16:17:50 -0500 Subject: [PATCH 02/13] docs: add changeset --- .changeset/thin-pumpkins-sell.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/thin-pumpkins-sell.md diff --git a/.changeset/thin-pumpkins-sell.md b/.changeset/thin-pumpkins-sell.md new file mode 100644 index 00000000000..2bd029fa3c7 --- /dev/null +++ b/.changeset/thin-pumpkins-sell.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/account": patch +--- + +fix: ensure `getInputFromAssetId` returns correct `InputMessage` From f92c0c53d2c67ecffaed900fd4c90440b56a840c Mon Sep 17 00:00:00 2001 From: chad Date: Tue, 23 Jul 2024 09:19:28 -0500 Subject: [PATCH 03/13] test: temp release to npm --- .github/workflows/pr-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-release.yaml b/.github/workflows/pr-release.yaml index 6eeca1f3f04..593d7fce145 100644 --- a/.github/workflows/pr-release.yaml +++ b/.github/workflows/pr-release.yaml @@ -8,7 +8,7 @@ jobs: name: "Release PR to npm" runs-on: ubuntu-latest # comment out if:false to enable release PR to npm - if: false + # if: false permissions: write-all steps: - name: Checkout From c65969176d25368f72a4e849e68c892ff9868b5a Mon Sep 17 00:00:00 2001 From: chad Date: Wed, 24 Jul 2024 12:35:24 -0500 Subject: [PATCH 04/13] fix: use amounts to determine what message should be returned --- packages/account/src/providers/transaction-summary/input.ts | 4 ++-- .../account/src/providers/transaction-summary/operations.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/account/src/providers/transaction-summary/input.ts b/packages/account/src/providers/transaction-summary/input.ts index 96b5b12e6c7..f9084efdf13 100644 --- a/packages/account/src/providers/transaction-summary/input.ts +++ b/packages/account/src/providers/transaction-summary/input.ts @@ -33,10 +33,10 @@ export function getInputsContract(inputs: Input[]) { } /** @hidden */ -export function getInputFromAssetId(inputs: Input[], assetId: string) { +export function getRelevantInputs(inputs: Input[]) { const coinInputs = getInputsCoin(inputs); const messageInputs = getInputsMessage(inputs); - const coinInput = coinInputs.find((i) => i.assetId === assetId); + const coinInput = coinInputs.find((i) => i.amount.gt(0)); const messageInput = messageInputs.find(({ amount }) => !!amount && amount.gt(0)); return coinInput || messageInput; diff --git a/packages/account/src/providers/transaction-summary/operations.ts b/packages/account/src/providers/transaction-summary/operations.ts index 17e4f677302..c8d7cc840ce 100644 --- a/packages/account/src/providers/transaction-summary/operations.ts +++ b/packages/account/src/providers/transaction-summary/operations.ts @@ -14,7 +14,7 @@ import type { import { getFunctionCall } from './call'; import { - getInputFromAssetId, + getRelevantInputs, getInputAccountAddress, getInputContractFromIndex, getInputsContract, @@ -198,7 +198,7 @@ export function getWithdrawFromFuelOperations({ const withdrawFromFuelOperations = messageOutReceipts.reduce( (prevWithdrawFromFuelOps, receipt) => { - const input = getInputFromAssetId(inputs, baseAssetId); + const input = getRelevantInputs(inputs); if (input) { const inputAddress = getInputAccountAddress(input); const newWithdrawFromFuelOps = addOperation(prevWithdrawFromFuelOps, { @@ -252,7 +252,7 @@ export function getContractCallOperations({ if (contractInput) { const newCallOps = contractCallReceipts.reduce((prevContractCallOps, receipt) => { if (receipt.to === contractInput.contractID) { - const input = getInputFromAssetId(inputs, receipt.assetId); + const input = getRelevantInputs(inputs); if (input) { const inputAddress = getInputAccountAddress(input); const calls = []; From 63e827df7cf85317ae9a9017edbe7d22fe54c845 Mon Sep 17 00:00:00 2001 From: chad Date: Wed, 24 Jul 2024 15:22:46 -0500 Subject: [PATCH 05/13] fix: return correct coinInput and InputMessage operations --- .../transaction-summary/input.test.ts | 33 ++++++++++++------- .../providers/transaction-summary/input.ts | 17 ++++++++-- .../transaction-summary/operations.ts | 14 ++++++-- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/packages/account/src/providers/transaction-summary/input.test.ts b/packages/account/src/providers/transaction-summary/input.test.ts index 79f97a1a9f2..27d6e167a3c 100644 --- a/packages/account/src/providers/transaction-summary/input.test.ts +++ b/packages/account/src/providers/transaction-summary/input.test.ts @@ -1,7 +1,7 @@ import { ZeroBytes32 } from '@fuel-ts/address/configs'; import { bn } from '@fuel-ts/math'; import type { InputCoin, InputMessage } from '@fuel-ts/transactions'; -import { ASSET_A } from '@fuel-ts/utils/test-utils'; +import { ASSET_A, ASSET_B } from '@fuel-ts/utils/test-utils'; import { MOCK_INPUT_COIN, @@ -13,7 +13,7 @@ import { import { getInputAccountAddress, getInputContractFromIndex, - getInputFromAssetId, + getRelevantInputs, getInputsCoin, getInputsContract, getInputsMessage, @@ -114,25 +114,34 @@ describe('transaction-summary/input', () => { assetId: ASSET_A, }; - expect(getInputFromAssetId([inputCoin1, inputCoin2], ZeroBytes32)).toStrictEqual(inputCoin1); - expect(getInputFromAssetId([inputCoin1, inputCoin2], ASSET_A)).toStrictEqual(inputCoin2); + expect(getRelevantInputs([inputCoin1, inputCoin2], ZeroBytes32)).toStrictEqual(inputCoin1); + expect(getRelevantInputs([inputCoin1, inputCoin2], ASSET_A)).toStrictEqual(inputCoin2); - expect(getInputFromAssetId([MOCK_INPUT_MESSAGE], ZeroBytes32)).toStrictEqual( - MOCK_INPUT_MESSAGE - ); + expect(getRelevantInputs([MOCK_INPUT_MESSAGE], ZeroBytes32)).toStrictEqual(MOCK_INPUT_MESSAGE); }); - it('should ensure getInputFromAssetId returns input message if the coin input amount is 0', () => { - const inputMessage: InputMessage = { - ...MOCK_INPUT_MESSAGE, + it('should ensure getRelevantInputs returns the correct coinInput thats greater than 0 for default assetId', () => { + const coinInput1: InputCoin = { + ...MOCK_INPUT_COIN, amount: bn(100), + assetId: ZeroBytes32, }; - const coinInput: InputCoin = { + const coinInput2: InputCoin = { ...MOCK_INPUT_COIN, amount: bn(0), + assetId: ZeroBytes32, + }; + + expect(getRelevantInputs([coinInput1, coinInput2])).toEqual(coinInput1); + }); + + it('Should return the correct input message for withdrawals', () => { + const inputMessage: InputMessage = { + ...MOCK_INPUT_MESSAGE, + amount: bn(100), }; - expect(getInputFromAssetId([inputMessage, coinInput], ASSET_A)).toEqual(inputMessage); + expect(getRelevantInputs([inputMessage])).toEqual(inputMessage); }); }); diff --git a/packages/account/src/providers/transaction-summary/input.ts b/packages/account/src/providers/transaction-summary/input.ts index f9084efdf13..ae776b2e2c3 100644 --- a/packages/account/src/providers/transaction-summary/input.ts +++ b/packages/account/src/providers/transaction-summary/input.ts @@ -1,3 +1,4 @@ +import { ZeroBytes32 } from '@fuel-ts/address/configs'; import { ErrorCode, FuelError } from '@fuel-ts/errors'; import type { Input, InputCoin, InputContract, InputMessage } from '@fuel-ts/transactions'; import { InputType } from '@fuel-ts/transactions'; @@ -33,13 +34,23 @@ export function getInputsContract(inputs: Input[]) { } /** @hidden */ -export function getRelevantInputs(inputs: Input[]) { +export function getRelevantInputs(inputs: Input[], assetId: string = ZeroBytes32) { const coinInputs = getInputsCoin(inputs); const messageInputs = getInputsMessage(inputs); - const coinInput = coinInputs.find((i) => i.amount.gt(0)); + let coinInput = coinInputs.find((i) => i.assetId === assetId); + // #TODO: There are times when the ReceiptCall's baseAssetId doesn't match the CoinInput's assetId + // In this case, we should return the last input in the CoinInput array + if (!coinInput && coinInputs.length > 0) { + coinInput = coinInputs[coinInputs.length - 1]; + } + const messageInput = messageInputs.find(({ amount }) => !!amount && amount.gt(0)); - return coinInput || messageInput; + if (coinInput) { + return coinInput; + } + + return messageInput; } /** @hidden */ diff --git a/packages/account/src/providers/transaction-summary/operations.ts b/packages/account/src/providers/transaction-summary/operations.ts index c8d7cc840ce..c7cf845a319 100644 --- a/packages/account/src/providers/transaction-summary/operations.ts +++ b/packages/account/src/providers/transaction-summary/operations.ts @@ -198,7 +198,12 @@ export function getWithdrawFromFuelOperations({ const withdrawFromFuelOperations = messageOutReceipts.reduce( (prevWithdrawFromFuelOps, receipt) => { - const input = getRelevantInputs(inputs); + let input; + if (baseAssetId !== ZeroBytes32) { + input = getRelevantInputs(inputs, baseAssetId); + } else { + input = getRelevantInputs(inputs); + } if (input) { const inputAddress = getInputAccountAddress(input); const newWithdrawFromFuelOps = addOperation(prevWithdrawFromFuelOps, { @@ -252,7 +257,12 @@ export function getContractCallOperations({ if (contractInput) { const newCallOps = contractCallReceipts.reduce((prevContractCallOps, receipt) => { if (receipt.to === contractInput.contractID) { - const input = getRelevantInputs(inputs); + let input; + if (receipt.assetId !== ZeroBytes32) { + input = getRelevantInputs(inputs, receipt.assetId); + } else { + input = getRelevantInputs(inputs); + } if (input) { const inputAddress = getInputAccountAddress(input); const calls = []; From a9cb0521cc414be8e7104ed5163fea48a3796e08 Mon Sep 17 00:00:00 2001 From: chad Date: Wed, 24 Jul 2024 15:24:33 -0500 Subject: [PATCH 06/13] docs: update changeset --- .changeset/thin-pumpkins-sell.md | 2 +- .../account/src/providers/transaction-summary/input.test.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.changeset/thin-pumpkins-sell.md b/.changeset/thin-pumpkins-sell.md index 2bd029fa3c7..eb363c6d5ba 100644 --- a/.changeset/thin-pumpkins-sell.md +++ b/.changeset/thin-pumpkins-sell.md @@ -2,4 +2,4 @@ "@fuel-ts/account": patch --- -fix: ensure `getInputFromAssetId` returns correct `InputMessage` +fix: return correct operations from `coinInput` and `InputMessage` inputs \ No newline at end of file diff --git a/packages/account/src/providers/transaction-summary/input.test.ts b/packages/account/src/providers/transaction-summary/input.test.ts index 27d6e167a3c..a621cf0a9fa 100644 --- a/packages/account/src/providers/transaction-summary/input.test.ts +++ b/packages/account/src/providers/transaction-summary/input.test.ts @@ -143,5 +143,6 @@ describe('transaction-summary/input', () => { }; expect(getRelevantInputs([inputMessage])).toEqual(inputMessage); + expect(getRelevantInputs([inputMessage])?.amount).toEqual(bn(100)); }); }); From d126fcb5bfe84a4cdd102f61f91477a2d2c55628 Mon Sep 17 00:00:00 2001 From: chad Date: Wed, 24 Jul 2024 15:32:33 -0500 Subject: [PATCH 07/13] docs: update changeset --- .changeset/thin-pumpkins-sell.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/thin-pumpkins-sell.md b/.changeset/thin-pumpkins-sell.md index eb363c6d5ba..bfa20d2ff25 100644 --- a/.changeset/thin-pumpkins-sell.md +++ b/.changeset/thin-pumpkins-sell.md @@ -2,4 +2,4 @@ "@fuel-ts/account": patch --- -fix: return correct operations from `coinInput` and `InputMessage` inputs \ No newline at end of file +fix: return correct operations from coin and message inputs \ No newline at end of file From 3818684d204c6cd2c37c9bce9955d7f67b26bc6c Mon Sep 17 00:00:00 2001 From: chad Date: Wed, 24 Jul 2024 15:45:25 -0500 Subject: [PATCH 08/13] lint: resolve linting issues --- .../account/src/providers/transaction-summary/input.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/account/src/providers/transaction-summary/input.test.ts b/packages/account/src/providers/transaction-summary/input.test.ts index a621cf0a9fa..3036375f35e 100644 --- a/packages/account/src/providers/transaction-summary/input.test.ts +++ b/packages/account/src/providers/transaction-summary/input.test.ts @@ -1,7 +1,7 @@ import { ZeroBytes32 } from '@fuel-ts/address/configs'; import { bn } from '@fuel-ts/math'; import type { InputCoin, InputMessage } from '@fuel-ts/transactions'; -import { ASSET_A, ASSET_B } from '@fuel-ts/utils/test-utils'; +import { ASSET_A } from '@fuel-ts/utils/test-utils'; import { MOCK_INPUT_COIN, From 7004319a614f9118b284c1c76fa76ab4a7e73bf4 Mon Sep 17 00:00:00 2001 From: chad Date: Thu, 25 Jul 2024 15:16:06 -0500 Subject: [PATCH 09/13] fix: return correct input based on receipt assetId and baseAssetId --- .github/workflows/pr-release.yaml | 2 +- .../transaction-summary/input.test.ts | 21 +++++++----- .../providers/transaction-summary/input.ts | 34 ++++++++++++------- .../transaction-summary/operations.test.ts | 3 ++ .../transaction-summary/operations.ts | 23 +++++-------- 5 files changed, 46 insertions(+), 37 deletions(-) diff --git a/.github/workflows/pr-release.yaml b/.github/workflows/pr-release.yaml index 593d7fce145..6eeca1f3f04 100644 --- a/.github/workflows/pr-release.yaml +++ b/.github/workflows/pr-release.yaml @@ -8,7 +8,7 @@ jobs: name: "Release PR to npm" runs-on: ubuntu-latest # comment out if:false to enable release PR to npm - # if: false + if: false permissions: write-all steps: - name: Checkout diff --git a/packages/account/src/providers/transaction-summary/input.test.ts b/packages/account/src/providers/transaction-summary/input.test.ts index 3036375f35e..64593abaa51 100644 --- a/packages/account/src/providers/transaction-summary/input.test.ts +++ b/packages/account/src/providers/transaction-summary/input.test.ts @@ -13,7 +13,7 @@ import { import { getInputAccountAddress, getInputContractFromIndex, - getRelevantInputs, + getInputFromAssetId, getInputsCoin, getInputsContract, getInputsMessage, @@ -103,7 +103,7 @@ describe('transaction-summary/input', () => { expect(address).toEqual(''); }); - it('should ensure getInputFromAssetId return correct input to pay for that assetId', () => { + it.only('should ensure getInputFromAssetId return correct input to pay for that assetId', () => { const inputCoin1: InputCoin = { ...MOCK_INPUT_COIN, assetId: ZeroBytes32, @@ -114,13 +114,17 @@ describe('transaction-summary/input', () => { assetId: ASSET_A, }; - expect(getRelevantInputs([inputCoin1, inputCoin2], ZeroBytes32)).toStrictEqual(inputCoin1); - expect(getRelevantInputs([inputCoin1, inputCoin2], ASSET_A)).toStrictEqual(inputCoin2); + expect(getInputFromAssetId([inputCoin1, inputCoin2], ZeroBytes32, false)).toStrictEqual( + inputCoin1 + ); + expect(getInputFromAssetId([inputCoin1, inputCoin2], ASSET_A, false)).toStrictEqual(inputCoin2); - expect(getRelevantInputs([MOCK_INPUT_MESSAGE], ZeroBytes32)).toStrictEqual(MOCK_INPUT_MESSAGE); + expect(getInputFromAssetId([MOCK_INPUT_MESSAGE], ZeroBytes32, true)).toStrictEqual( + MOCK_INPUT_MESSAGE + ); }); - it('should ensure getRelevantInputs returns the correct coinInput thats greater than 0 for default assetId', () => { + it('should ensure getInputFromAssetId returns the correct coinInput thats greater than 0 for default assetId', () => { const coinInput1: InputCoin = { ...MOCK_INPUT_COIN, amount: bn(100), @@ -133,7 +137,7 @@ describe('transaction-summary/input', () => { assetId: ZeroBytes32, }; - expect(getRelevantInputs([coinInput1, coinInput2])).toEqual(coinInput1); + expect(getInputFromAssetId([coinInput1, coinInput2], ZeroBytes32)).toEqual(coinInput1); }); it('Should return the correct input message for withdrawals', () => { @@ -142,7 +146,6 @@ describe('transaction-summary/input', () => { amount: bn(100), }; - expect(getRelevantInputs([inputMessage])).toEqual(inputMessage); - expect(getRelevantInputs([inputMessage])?.amount).toEqual(bn(100)); + expect(getInputFromAssetId([inputMessage], ZeroBytes32, true)).toEqual(inputMessage); }); }); diff --git a/packages/account/src/providers/transaction-summary/input.ts b/packages/account/src/providers/transaction-summary/input.ts index ae776b2e2c3..ac08c85e502 100644 --- a/packages/account/src/providers/transaction-summary/input.ts +++ b/packages/account/src/providers/transaction-summary/input.ts @@ -1,4 +1,3 @@ -import { ZeroBytes32 } from '@fuel-ts/address/configs'; import { ErrorCode, FuelError } from '@fuel-ts/errors'; import type { Input, InputCoin, InputContract, InputMessage } from '@fuel-ts/transactions'; import { InputType } from '@fuel-ts/transactions'; @@ -14,7 +13,7 @@ export function getInputsByType(inputs: Input[], type: InputType) { } /** @hidden */ -export function getInputsCoin(inputs: Input[]) { +export function getInputsCoin(inputs: Input[]): InputCoin[] { return getInputsByType(inputs, InputType.Coin); } @@ -34,23 +33,32 @@ export function getInputsContract(inputs: Input[]) { } /** @hidden */ -export function getRelevantInputs(inputs: Input[], assetId: string = ZeroBytes32) { +function findCoinInput(inputs: Input[], assetId: string): InputCoin | undefined { const coinInputs = getInputsCoin(inputs); - const messageInputs = getInputsMessage(inputs); - let coinInput = coinInputs.find((i) => i.assetId === assetId); - // #TODO: There are times when the ReceiptCall's baseAssetId doesn't match the CoinInput's assetId - // In this case, we should return the last input in the CoinInput array - if (!coinInput && coinInputs.length > 0) { - coinInput = coinInputs[coinInputs.length - 1]; - } - - const messageInput = messageInputs.find(({ amount }) => !!amount && amount.gt(0)); + return coinInputs.find((i) => i.assetId === assetId); +} +/** @hidden */ +function findMessageInput(inputs: Input[]): InputMessage | undefined { + return getInputsMessage(inputs)?.[0]; +} +/** @hidden */ +export function getInputFromAssetId( + inputs: Input[], + assetId: string, + isBaseAsset = false +): InputCoin | InputMessage | undefined { + const coinInput = findCoinInput(inputs, assetId); if (coinInput) { return coinInput; } - return messageInput; + if (isBaseAsset) { + return findMessageInput(inputs); + } + + // #TODO: we should throw an error here if we are unable to return a valid input + return undefined; } /** @hidden */ diff --git a/packages/account/src/providers/transaction-summary/operations.test.ts b/packages/account/src/providers/transaction-summary/operations.test.ts index cf20482aca0..32337158047 100644 --- a/packages/account/src/providers/transaction-summary/operations.test.ts +++ b/packages/account/src/providers/transaction-summary/operations.test.ts @@ -87,6 +87,7 @@ describe('operations', () => { outputs: [MOCK_OUTPUT_CONTRACT, MOCK_OUTPUT_VARIABLE, MOCK_OUTPUT_CHANGE], receipts, maxInputs: bn(255), + baseAssetId: ZeroBytes32, }); expect(operations.length).toEqual(1); @@ -150,6 +151,7 @@ describe('operations', () => { }, rawPayload: MOCK_TRANSACTION_RAWPAYLOAD, maxInputs: bn(255), + baseAssetId: ZeroBytes32, }); expect(operations.length).toEqual(1); @@ -162,6 +164,7 @@ describe('operations', () => { outputs: [MOCK_OUTPUT_COIN, MOCK_OUTPUT_CHANGE], receipts: [MOCK_RECEIPT_RETURN, MOCK_RECEIPT_SCRIPT_RESULT], maxInputs: bn(255), + baseAssetId: ZeroBytes32, }); expect(operations.length).toEqual(0); diff --git a/packages/account/src/providers/transaction-summary/operations.ts b/packages/account/src/providers/transaction-summary/operations.ts index c7cf845a319..237c3937845 100644 --- a/packages/account/src/providers/transaction-summary/operations.ts +++ b/packages/account/src/providers/transaction-summary/operations.ts @@ -14,7 +14,7 @@ import type { import { getFunctionCall } from './call'; import { - getRelevantInputs, + getInputFromAssetId, getInputAccountAddress, getInputContractFromIndex, getInputsContract, @@ -198,12 +198,7 @@ export function getWithdrawFromFuelOperations({ const withdrawFromFuelOperations = messageOutReceipts.reduce( (prevWithdrawFromFuelOps, receipt) => { - let input; - if (baseAssetId !== ZeroBytes32) { - input = getRelevantInputs(inputs, baseAssetId); - } else { - input = getRelevantInputs(inputs); - } + const input = getInputFromAssetId(inputs, baseAssetId, true); if (input) { const inputAddress = getInputAccountAddress(input); const newWithdrawFromFuelOps = addOperation(prevWithdrawFromFuelOps, { @@ -244,9 +239,10 @@ export function getContractCallOperations({ abiMap, rawPayload, maxInputs, + baseAssetId, }: InputOutputParam & ReceiptParam & - Pick & + Pick & RawPayloadParam): Operation[] { const contractCallReceipts = getReceiptsCall(receipts); const contractOutputs = getOutputsContract(outputs); @@ -257,12 +253,10 @@ export function getContractCallOperations({ if (contractInput) { const newCallOps = contractCallReceipts.reduce((prevContractCallOps, receipt) => { if (receipt.to === contractInput.contractID) { - let input; - if (receipt.assetId !== ZeroBytes32) { - input = getRelevantInputs(inputs, receipt.assetId); - } else { - input = getRelevantInputs(inputs); - } + // # TODO: This is a temporary fix to ensure that the base assetId is used when the assetId is ZeroBytes32 + // The assetId is returned as ZeroBytes32 if the contract call has no assets in it (see https://github.com/FuelLabs/fuel-core/issues/1941) + const assetId = receipt.assetId === ZeroBytes32 ? baseAssetId : receipt.assetId; + const input = getInputFromAssetId(inputs, assetId, assetId === baseAssetId); if (input) { const inputAddress = getInputAccountAddress(input); const calls = []; @@ -507,6 +501,7 @@ export function getOperations({ abiMap, rawPayload, maxInputs, + baseAssetId, }), ...getWithdrawFromFuelOperations({ inputs, receipts, baseAssetId }), ]; From b69a225a66a64c569124ca376fe4a1bfdc3c0d69 Mon Sep 17 00:00:00 2001 From: chad Date: Thu, 25 Jul 2024 15:22:08 -0500 Subject: [PATCH 10/13] test: remove unnecessary only from test --- .../account/src/providers/transaction-summary/input.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/account/src/providers/transaction-summary/input.test.ts b/packages/account/src/providers/transaction-summary/input.test.ts index 64593abaa51..8161e067fd5 100644 --- a/packages/account/src/providers/transaction-summary/input.test.ts +++ b/packages/account/src/providers/transaction-summary/input.test.ts @@ -103,7 +103,7 @@ describe('transaction-summary/input', () => { expect(address).toEqual(''); }); - it.only('should ensure getInputFromAssetId return correct input to pay for that assetId', () => { + it('should ensure getInputFromAssetId return correct input to pay for that assetId', () => { const inputCoin1: InputCoin = { ...MOCK_INPUT_COIN, assetId: ZeroBytes32, From 12248627d1844bd9657e554cc35d91034ec20f21 Mon Sep 17 00:00:00 2001 From: chad Date: Thu, 25 Jul 2024 15:23:28 -0500 Subject: [PATCH 11/13] test: remove unnecessary parameter from test --- .../account/src/providers/transaction-summary/input.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/account/src/providers/transaction-summary/input.test.ts b/packages/account/src/providers/transaction-summary/input.test.ts index 8161e067fd5..8489f019b59 100644 --- a/packages/account/src/providers/transaction-summary/input.test.ts +++ b/packages/account/src/providers/transaction-summary/input.test.ts @@ -114,10 +114,8 @@ describe('transaction-summary/input', () => { assetId: ASSET_A, }; - expect(getInputFromAssetId([inputCoin1, inputCoin2], ZeroBytes32, false)).toStrictEqual( - inputCoin1 - ); - expect(getInputFromAssetId([inputCoin1, inputCoin2], ASSET_A, false)).toStrictEqual(inputCoin2); + expect(getInputFromAssetId([inputCoin1, inputCoin2], ZeroBytes32)).toStrictEqual(inputCoin1); + expect(getInputFromAssetId([inputCoin1, inputCoin2], ASSET_A)).toStrictEqual(inputCoin2); expect(getInputFromAssetId([MOCK_INPUT_MESSAGE], ZeroBytes32, true)).toStrictEqual( MOCK_INPUT_MESSAGE From 2a5abeae11ac0ed071f5750d2c292af04b82b123 Mon Sep 17 00:00:00 2001 From: chad Date: Fri, 26 Jul 2024 12:20:54 -0500 Subject: [PATCH 12/13] test: add a fuel-gauge test for MessageInput --- .../src/test-utils/wallet-config.test.ts | 10 +---- .../account/src/test-utils/wallet-config.ts | 4 +- .../src/transaction-summary.test.ts | 42 ++++++++++++++++++- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/packages/account/src/test-utils/wallet-config.test.ts b/packages/account/src/test-utils/wallet-config.test.ts index 86598f10562..0c292bf4ffb 100644 --- a/packages/account/src/test-utils/wallet-config.test.ts +++ b/packages/account/src/test-utils/wallet-config.test.ts @@ -84,15 +84,7 @@ describe('WalletsConfig', () => { () => new WalletsConfig(hexlify(randomBytes(32)), { ...configOptions, amountPerCoin: -1 }), new FuelError( FuelError.CODES.INVALID_INPUT_PARAMETERS, - 'Amount per coin must be greater than zero.' - ) - ); - - await expectToThrowFuelError( - () => new WalletsConfig(hexlify(randomBytes(32)), { ...configOptions, amountPerCoin: 0 }), - new FuelError( - FuelError.CODES.INVALID_INPUT_PARAMETERS, - 'Amount per coin must be greater than zero.' + 'Amount per coin must be greater than or equal to zero.' ) ); }); diff --git a/packages/account/src/test-utils/wallet-config.ts b/packages/account/src/test-utils/wallet-config.ts index 334226be0e6..7b76326eb22 100644 --- a/packages/account/src/test-utils/wallet-config.ts +++ b/packages/account/src/test-utils/wallet-config.ts @@ -167,10 +167,10 @@ export class WalletsConfig { 'Number of coins per asset must be greater than zero.' ); } - if (amountPerCoin <= 0) { + if (amountPerCoin < 0) { throw new FuelError( FuelError.CODES.INVALID_INPUT_PARAMETERS, - 'Amount per coin must be greater than zero.' + 'Amount per coin must be greater than or equal to zero.' ); } } diff --git a/packages/fuel-gauge/src/transaction-summary.test.ts b/packages/fuel-gauge/src/transaction-summary.test.ts index 691f7435b71..fa91d285afb 100644 --- a/packages/fuel-gauge/src/transaction-summary.test.ts +++ b/packages/fuel-gauge/src/transaction-summary.test.ts @@ -16,7 +16,7 @@ import { AddressType, OperationName, } from 'fuels'; -import { ASSET_A, ASSET_B, launchTestNode } from 'fuels/test-utils'; +import { ASSET_A, ASSET_B, launchTestNode, TestMessage } from 'fuels/test-utils'; import { MultiTokenContractAbi__factory, TokenContractAbi__factory } from '../test/typegen'; import MultiTokenContractAbiHex from '../test/typegen/contracts/MultiTokenContractAbi.hex'; @@ -591,5 +591,45 @@ describe('TransactionSummary', () => { recipients: allRecipients, }); }); + + it.only('should ensure that transfer operations are assembled correctly if only seeded with a MessageInput (SPENDABLE MESSAGE)', async () => { + const testMessage = new TestMessage({ amount: 1000000, data: '' }); + + using launched = await launchTestNode({ + contractsConfigs: [ + { + deployer: MultiTokenContractAbi__factory, + bytecode: MultiTokenContractAbiHex, + }, + ], + walletsConfig: { + amountPerCoin: 0, + messages: [testMessage], + }, + }); + const { + contracts: [contract], + provider, + wallets: [wallet], + } = launched; + + const amount = 100; + + const tx1 = await wallet.transferToContract(contract.id, amount); + + const { operations } = await tx1.waitForResult(); + + expect(operations).toHaveLength(1); + + validateTransferOperation({ + operations, + sender: wallet.address, + fromType: AddressType.account, + toType: AddressType.contract, + recipients: [ + { address: contract.id, quantities: [{ amount, assetId: provider.getBaseAssetId() }] }, + ], + }); + }); }); }); From 3114f11068ef6ad6f2b120524ca9b6090903b22c Mon Sep 17 00:00:00 2001 From: Chad Nehemiah Date: Fri, 26 Jul 2024 13:53:50 -0400 Subject: [PATCH 13/13] remove unnecessary only Co-authored-by: Peter Smith --- packages/fuel-gauge/src/transaction-summary.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuel-gauge/src/transaction-summary.test.ts b/packages/fuel-gauge/src/transaction-summary.test.ts index fa91d285afb..4c47df9aef1 100644 --- a/packages/fuel-gauge/src/transaction-summary.test.ts +++ b/packages/fuel-gauge/src/transaction-summary.test.ts @@ -592,7 +592,7 @@ describe('TransactionSummary', () => { }); }); - it.only('should ensure that transfer operations are assembled correctly if only seeded with a MessageInput (SPENDABLE MESSAGE)', async () => { + it('should ensure that transfer operations are assembled correctly if only seeded with a MessageInput (SPENDABLE MESSAGE)', async () => { const testMessage = new TestMessage({ amount: 1000000, data: '' }); using launched = await launchTestNode({