From dc3b6009921fbc4457f4ff80b5a216f60776f52a Mon Sep 17 00:00:00 2001 From: cpl121 Date: Tue, 23 Apr 2024 17:10:06 +0200 Subject: [PATCH 01/13] fix: displayed mana in tx details WIP --- .../GenericActivityInformation.svelte | 8 ++-- .../shared/lib/core/wallet/utils/index.ts | 2 +- .../utils/isOutputOfSelectedWalletAddress.ts | 16 -------- .../wallet/utils/isOutputUnlockedByAddress.ts | 12 ++++++ .../outputs/preprocessOutgoingTransaction.ts | 37 ++++++++++++++++--- 5 files changed, 48 insertions(+), 27 deletions(-) delete mode 100644 packages/shared/lib/core/wallet/utils/isOutputOfSelectedWalletAddress.ts create mode 100644 packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts diff --git a/packages/shared/components/activity-info/GenericActivityInformation.svelte b/packages/shared/components/activity-info/GenericActivityInformation.svelte index 531a78da616..513a0a4cabe 100644 --- a/packages/shared/components/activity-info/GenericActivityInformation.svelte +++ b/packages/shared/components/activity-info/GenericActivityInformation.svelte @@ -2,7 +2,7 @@ import { KeyValueBox } from '@ui' import { getFormattedTimeStamp, localize } from '@core/i18n' import { activeProfile, getBaseToken } from '@core/profile' - import { Activity, ActivityDirection, formatTokenAmountBestMatch, formatTokenAmountPrecise } from '@core/wallet' + import { Activity, formatTokenAmountBestMatch, formatTokenAmountPrecise } from '@core/wallet' import { DEFAULT_MANA, ExplorerEndpoint } from '@core/network' import { getOfficialExplorerUrl } from '@core/network/utils' import { openUrlInBrowser } from '@core/app' @@ -28,9 +28,9 @@ $: formattedGiftedStorageDeposit = formatTokenAmountPrecise(activity?.giftedStorageDeposit ?? 0, getBaseToken()) $: formattedSurplus = formatTokenAmountPrecise(activity?.surplus ?? 0, getBaseToken()) $: formattedGasFee = formatTokenAmountPrecise(Number(gasFee ?? 0), getBaseToken()) - $: formattedManaPrefix = - activity.direction === ActivityDirection.Incoming || Number(activity?.mana) === 0 ? '' : '- ' - $: formattedMana = formattedManaPrefix + formatTokenAmountBestMatch(Number(activity?.mana ?? 0), DEFAULT_MANA) + $: formattedManaPrefix = Number(activity?.mana) >= 0 ? '' : '- ' + $: formattedMana = + formattedManaPrefix + formatTokenAmountBestMatch(Math.abs(Number(activity?.mana ?? 0)), DEFAULT_MANA) let transactionDetailsList: IKeyValueBoxList $: transactionDetailsList = { diff --git a/packages/shared/lib/core/wallet/utils/index.ts b/packages/shared/lib/core/wallet/utils/index.ts index c86c91b015b..9eec5acbbd9 100644 --- a/packages/shared/lib/core/wallet/utils/index.ts +++ b/packages/shared/lib/core/wallet/utils/index.ts @@ -39,7 +39,7 @@ export * from './syncWalletsInParallel' export * from './validateWalletName' export * from './isVisibleAsset' export * from './isVisibleActivity' -export * from './isOutputOfSelectedWalletAddress' +export * from './isOutputUnlockedByAddress' export * from './hasWalletMainAccountNegativeBIC' // Folders diff --git a/packages/shared/lib/core/wallet/utils/isOutputOfSelectedWalletAddress.ts b/packages/shared/lib/core/wallet/utils/isOutputOfSelectedWalletAddress.ts deleted file mode 100644 index 0beb20fb6e4..00000000000 --- a/packages/shared/lib/core/wallet/utils/isOutputOfSelectedWalletAddress.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { CommonOutput, UnlockConditionType, OutputData, AddressUnlockCondition } from '@iota/sdk/out/types' -import { selectedWallet } from '../stores' -import { get } from 'svelte/store' -import { AddressConverter } from './AddressConverter' - -export async function isOutputOfSelectedWalletAddress(outputData: OutputData): Promise { - const output = outputData.output as CommonOutput - const walletAddress = await get(selectedWallet)?.address() - const address = ( - output.unlockConditions.find( - (unlockCondition) => unlockCondition.type === UnlockConditionType.Address - ) as AddressUnlockCondition - ).address - const bech32Address = AddressConverter.addressToBech32(address) - return bech32Address === walletAddress -} diff --git a/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts b/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts new file mode 100644 index 00000000000..a0810a1ba1c --- /dev/null +++ b/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts @@ -0,0 +1,12 @@ +import { CommonOutput, UnlockConditionType, AddressUnlockCondition } from '@iota/sdk/out/types' +import { AddressConverter } from './AddressConverter' + +export function isOutputUnlockedByAddress(output: CommonOutput, address: string): boolean { + const outputAddress = ( + output.unlockConditions.find( + (unlockCondition) => unlockCondition.type === UnlockConditionType.Address + ) as AddressUnlockCondition + ).address + const bech32Address = AddressConverter.addressToBech32(outputAddress) + return bech32Address === address +} diff --git a/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts b/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts index 07e679d52b2..56696be971c 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts @@ -1,8 +1,10 @@ import { IProcessedTransaction, IWrappedOutput } from '../../interfaces' import { + AccountAddress, AccountOutput, AnchorOutput, BasicOutput, + CommonOutput, NftOutput, Output, OutputType, @@ -18,9 +20,9 @@ import { getPassiveManaForOutput } from '@core/network' import { MILLISECONDS_PER_SECOND } from '@core/utils' import { getUnixTimestampFromNodeInfoAndSlotIndex, nodeInfoProtocolParameters } from '@core/network' import { get } from 'svelte/store' -import { isImplicitAccountOutput } from '../isImplicitAccountOutput' -import { isOutputOfSelectedWalletAddress } from '../isOutputOfSelectedWalletAddress' +import { isOutputUnlockedByAddress } from '../isOutputUnlockedByAddress' import { isAccountOutput } from '../isAccountOutput' +import { AddressConverter } from '../AddressConverter' export async function preprocessOutgoingTransaction( transaction: TransactionWithMetadata, @@ -29,13 +31,15 @@ export async function preprocessOutgoingTransaction( const regularTransactionEssence = transaction.payload.transaction const transactionId = transaction?.transactionId?.toString() const nodeProtocolParameters = get(nodeInfoProtocolParameters) + const walletAddress = await wallet.address() + const implicitAddress = await wallet.implicitAccountCreationAddress() const slotUnixTimestamp = nodeProtocolParameters ? getUnixTimestampFromNodeInfoAndSlotIndex(nodeProtocolParameters, regularTransactionEssence.creationSlot) : 0 const outputs = convertTransactionsOutputTypesToWrappedOutputs(transactionId, regularTransactionEssence.outputs) - const direction = getDirectionFromOutgoingTransaction(regularTransactionEssence.outputs, await wallet.address()) + const direction = getDirectionFromOutgoingTransaction(regularTransactionEssence.outputs, walletAddress) const utxoInputs = regularTransactionEssence.inputs.map((i) => i as UTXOInput) const inputIds = utxoInputs.map((input) => { const transactionId = input.transactionId @@ -45,15 +49,36 @@ export async function preprocessOutgoingTransaction( const inputs = await Promise.all(inputIds.map((inputId) => wallet.getOutput(inputId))) - const inputsToConsiderWhenCalculatingMana = inputs.filter( - (input) => isAccountOutput(input) || isImplicitAccountOutput(input) || isOutputOfSelectedWalletAddress(input) + const addressToConsiderWhenCalculatingMana = [ + ...inputs + .filter(isAccountOutput) + .map((accountInput) => + AddressConverter.addressToBech32( + new AccountAddress((accountInput.output as unknown as AccountOutput).accountId) + ) + ), + implicitAddress, + walletAddress, + ] + + const inputsToConsiderWhenCalculatingMana = inputs.filter((input) => + addressToConsiderWhenCalculatingMana.find((address) => + isOutputUnlockedByAddress(input.output as CommonOutput, address) + ) + ) + + const outputsToConsiderWhenCalculatingMana = outputs.filter((output) => + addressToConsiderWhenCalculatingMana.find((address) => + isOutputUnlockedByAddress(output.output as CommonOutput, address) + ) ) + const prevManaCost = inputsToConsiderWhenCalculatingMana.reduce( (acc, input) => acc + (getPassiveManaForOutput(input) ?? 0), 0 ) - const postManaCost = outputs.reduce( + const postManaCost = outputsToConsiderWhenCalculatingMana.reduce( (acc, output) => acc + Number((output.output as BasicOutput | AccountOutput | AnchorOutput | NftOutput).mana ?? 0), 0 From 2b93b94ed7c9926371204b5f21cf4756af75b08e Mon Sep 17 00:00:00 2001 From: cpl121 Date: Thu, 25 Apr 2024 17:19:02 +0200 Subject: [PATCH 02/13] fix: improvements --- .../network/utils/getPassiveManaForOutput.ts | 17 ++-- .../preprocessTransactionsForWallet.ts | 2 +- .../utils/outputs/getTotalTransactionMana.ts | 90 +++++++++++++++++++ .../lib/core/wallet/utils/outputs/index.ts | 1 + .../outputs/preprocessIncomingTransaction.ts | 40 ++++----- .../outputs/preprocessOutgoingTransaction.ts | 67 +++----------- 6 files changed, 132 insertions(+), 85 deletions(-) create mode 100644 packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts diff --git a/packages/shared/lib/core/network/utils/getPassiveManaForOutput.ts b/packages/shared/lib/core/network/utils/getPassiveManaForOutput.ts index 5a614f6823f..b85323c0d59 100644 --- a/packages/shared/lib/core/network/utils/getPassiveManaForOutput.ts +++ b/packages/shared/lib/core/network/utils/getPassiveManaForOutput.ts @@ -7,20 +7,23 @@ import { getManaBalance } from './getManaBalance' /** * Get the passive mana for an output, it does not include BIC nor staking/delegation rewards * @param output The output to get the mana for. + * @param slotIndex The slot number up to where calculate the mana. * @returns The passive mana for the output. */ -export function getPassiveManaForOutput(output: OutputData): number | undefined { +export function getPassiveManaForOutput(output: OutputData, slotIndex?: number): number | undefined { const _nodeInfo = get(nodeInfo) if (!_nodeInfo || !_nodeInfo.protocolParameters?.[0]?.parameters || !output) return - const isOutputSpent = output.metadata.spent !== undefined - const spentOrLatestSlotIndex = isOutputSpent - ? output.metadata?.spent?.slot - : _nodeInfo.status?.latestConfirmedBlockSlot ?? undefined - if (spentOrLatestSlotIndex === undefined) return + if (!slotIndex) { + const isOutputSpent = output.metadata.spent !== undefined + slotIndex = isOutputSpent + ? output.metadata?.spent?.slot + : _nodeInfo.status?.latestConfirmedBlockSlot ?? undefined + } + if (slotIndex === undefined) return const decayedMana = api.outputManaWithDecay( output.output, output.metadata.included.slot, - spentOrLatestSlotIndex, + slotIndex, _nodeInfo.protocolParameters[0].parameters ) return getManaBalance(decayedMana) diff --git a/packages/shared/lib/core/wallet/actions/activities/preprocessTransactionsForWallet.ts b/packages/shared/lib/core/wallet/actions/activities/preprocessTransactionsForWallet.ts index f1ff39c8341..90efa58c419 100644 --- a/packages/shared/lib/core/wallet/actions/activities/preprocessTransactionsForWallet.ts +++ b/packages/shared/lib/core/wallet/actions/activities/preprocessTransactionsForWallet.ts @@ -17,7 +17,7 @@ export async function preprocessTransactionsForWallet(wallet: IWalletState): Pro const incomingTransactions = await wallet.incomingTransactions() for (const incomingTransaction of incomingTransactions) { try { - const processedTransaction = preprocessIncomingTransaction(incomingTransaction) + const processedTransaction = await preprocessIncomingTransaction(incomingTransaction, wallet) processedTransactions.push(processedTransaction) } catch (err) { console.error(err) diff --git a/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts b/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts new file mode 100644 index 00000000000..b5ac326ea9a --- /dev/null +++ b/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts @@ -0,0 +1,90 @@ +import { IWrappedOutput } from '../../interfaces' +import { + AccountAddress, + AccountOutput, + AnchorOutput, + BasicOutput, + CommonOutput, + ExpirationUnlockCondition, + NftOutput, + UnlockConditionType, +} from '@iota/sdk/out/types' +import { IWalletState } from '@core/wallet/interfaces' +import { getPassiveManaForOutput } from '@core/network' +import { isOutputUnlockedByAddress } from '../isOutputUnlockedByAddress' +import { AddressConverter } from '../AddressConverter' +import { getExpirationDateFromOutput } from './getExpirationDateFromOutput' + +export async function getTotalTransactionMana( + inputs: IWrappedOutput[], + outputs: IWrappedOutput[], + wallet: IWalletState, + transactionSlot: number, + transactionTimestamp: number +): Promise { + const walletAddress = await wallet.address() + const implicitAddress = await wallet.implicitAccountCreationAddress() + // We are ignoring accounts that the wallet may have had in the past + const currentAccountsAddresses = (await wallet.accounts()).map((accountInput) => + AddressConverter.addressToBech32( + new AccountAddress((accountInput.output as unknown as AccountOutput).accountId) + ) + ) + + const addressToConsiderWhenCalculatingMana = [...currentAccountsAddresses, implicitAddress, walletAddress] + + const inputsToConsiderWhenCalculatingMana = inputs.filter((input) => { + const commonInput = input.output as CommonOutput + const ownTransaction = addressToConsiderWhenCalculatingMana.find((address) => + isOutputUnlockedByAddress(commonInput, address) + ) + + return ( + !!ownTransaction || + hasOwnedOutputWithExpirationTimeExpired( + commonInput, + new Date(transactionTimestamp), + addressToConsiderWhenCalculatingMana, + !!ownTransaction + ) + ) + }) + + const outputsToConsiderWhenCalculatingMana = outputs.filter((output) => + addressToConsiderWhenCalculatingMana.find((address) => + isOutputUnlockedByAddress(output.output as CommonOutput, address) + ) + ) + + const prevManaCost = inputsToConsiderWhenCalculatingMana.reduce( + (acc, input) => acc + (getPassiveManaForOutput(input, transactionSlot) ?? 0), + 0 + ) + + const postManaCost = outputsToConsiderWhenCalculatingMana.reduce( + (acc, output) => + acc + Number((output.output as BasicOutput | AccountOutput | AnchorOutput | NftOutput).mana ?? 0), + 0 + ) + + return postManaCost - prevManaCost +} + +function hasOwnedOutputWithExpirationTimeExpired( + output: CommonOutput, + transactionTimestamp: Date, + ownAdresses: string[], + ownTransaction: boolean +): boolean { + const expirationDate = getExpirationDateFromOutput(output) + if (!expirationDate) return false + + const expirationUnlockCondition = output.unlockConditions.find( + (uc) => uc.type === UnlockConditionType.Expiration + ) as ExpirationUnlockCondition + const addressExpireUnlockCondition = AddressConverter.addressToBech32(expirationUnlockCondition.returnAddress) + const isOwnAddress = ownAdresses.includes(addressExpireUnlockCondition) + const isExpired = expirationDate.getTime() < transactionTimestamp.getTime() + + return (isOwnAddress && !isExpired) || (!isOwnAddress && isExpired && ownTransaction) +} diff --git a/packages/shared/lib/core/wallet/utils/outputs/index.ts b/packages/shared/lib/core/wallet/utils/outputs/index.ts index 7a54875b54e..f0d2abc06f5 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/index.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/index.ts @@ -21,3 +21,4 @@ export * from './getOutputIdFromTransactionIdAndIndex' export * from './getRequiredStorageDepositForMinimalBasicOutput' export * from './getSerialNumberFromAccountAddress' export * from './preprocessIncomingTransaction' +export * from './getTotalTransactionMana' diff --git a/packages/shared/lib/core/wallet/utils/outputs/preprocessIncomingTransaction.ts b/packages/shared/lib/core/wallet/utils/outputs/preprocessIncomingTransaction.ts index 15a6bea087f..4b7b42a3aad 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/preprocessIncomingTransaction.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/preprocessIncomingTransaction.ts @@ -1,27 +1,23 @@ -import { IProcessedTransaction, IWrappedOutput } from '../../interfaces' -import { - AccountOutput, - AnchorOutput, - BasicOutput, - NftOutput, - Output, - OutputType, - TransactionWithMetadata, - UTXOInput, -} from '@iota/sdk/out/types' +import { IProcessedTransaction, IWalletState, IWrappedOutput } from '../../interfaces' +import { Output, OutputType, TransactionWithMetadata, UTXOInput } from '@iota/sdk/out/types' import { getOutputIdFromTransactionIdAndIndex } from './getOutputIdFromTransactionIdAndIndex' import { ActivityDirection } from '../../enums' import { getUnixTimestampFromNodeInfoAndSlotIndex, nodeInfoProtocolParameters } from '@core/network' import { get } from 'svelte/store' import { MILLISECONDS_PER_SECOND } from '@core/utils' +import { getTotalTransactionMana } from './getTotalTransactionMana' -export function preprocessIncomingTransaction(transaction: TransactionWithMetadata): IProcessedTransaction { +export async function preprocessIncomingTransaction( + transaction: TransactionWithMetadata, + wallet: IWalletState +): Promise { const regularTransactionEssence = transaction.payload.transaction const transactionId = transaction?.transactionId?.toString() const nodeProtocolParameters = get(nodeInfoProtocolParameters) - const slotUnixTimestamp = nodeProtocolParameters + const createTransactionUnixTimestamp = nodeProtocolParameters ? getUnixTimestampFromNodeInfoAndSlotIndex(nodeProtocolParameters, regularTransactionEssence.creationSlot) : 0 + const createTransactionTimestamp = createTransactionUnixTimestamp * MILLISECONDS_PER_SECOND const outputs = convertTransactionsOutputTypesToWrappedOutputs(transactionId, regularTransactionEssence.outputs) @@ -33,22 +29,22 @@ export function preprocessIncomingTransaction(transaction: TransactionWithMetada remainder: true, })) - const manaCost = outputs - .filter((output) => !output.remainder) - .reduce( - (acc, output) => - acc + Number((output.output as BasicOutput | AccountOutput | AnchorOutput | NftOutput).mana ?? 0), - 0 - ) + const totalTransactionMana = await getTotalTransactionMana( + inputs, + outputs, + wallet, + regularTransactionEssence.creationSlot, + createTransactionTimestamp + ) return { outputs, transactionId, direction: ActivityDirection.Incoming, - time: new Date(slotUnixTimestamp * MILLISECONDS_PER_SECOND), + time: new Date(createTransactionTimestamp), inclusionState: transaction.inclusionState, wrappedInputs: inputs, - mana: manaCost, + mana: totalTransactionMana, utxoInputs, } } diff --git a/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts b/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts index 56696be971c..0dadda7e7e3 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts @@ -1,28 +1,13 @@ import { IProcessedTransaction, IWrappedOutput } from '../../interfaces' -import { - AccountAddress, - AccountOutput, - AnchorOutput, - BasicOutput, - CommonOutput, - NftOutput, - Output, - OutputType, - OutputWithMetadata, - TransactionWithMetadata, - UTXOInput, -} from '@iota/sdk/out/types' +import { Output, OutputType, OutputWithMetadata, TransactionWithMetadata, UTXOInput } from '@iota/sdk/out/types' import { computeOutputId } from './computeOutputId' import { getOutputIdFromTransactionIdAndIndex } from './getOutputIdFromTransactionIdAndIndex' import { getDirectionFromOutgoingTransaction } from '../transactions' import { IWalletState } from '@core/wallet/interfaces' -import { getPassiveManaForOutput } from '@core/network' import { MILLISECONDS_PER_SECOND } from '@core/utils' import { getUnixTimestampFromNodeInfoAndSlotIndex, nodeInfoProtocolParameters } from '@core/network' import { get } from 'svelte/store' -import { isOutputUnlockedByAddress } from '../isOutputUnlockedByAddress' -import { isAccountOutput } from '../isAccountOutput' -import { AddressConverter } from '../AddressConverter' +import { getTotalTransactionMana } from './getTotalTransactionMana' export async function preprocessOutgoingTransaction( transaction: TransactionWithMetadata, @@ -32,10 +17,10 @@ export async function preprocessOutgoingTransaction( const transactionId = transaction?.transactionId?.toString() const nodeProtocolParameters = get(nodeInfoProtocolParameters) const walletAddress = await wallet.address() - const implicitAddress = await wallet.implicitAccountCreationAddress() - const slotUnixTimestamp = nodeProtocolParameters + const createTransactionUnixTimestamp = nodeProtocolParameters ? getUnixTimestampFromNodeInfoAndSlotIndex(nodeProtocolParameters, regularTransactionEssence.creationSlot) : 0 + const createTransactionTimestamp = createTransactionUnixTimestamp * MILLISECONDS_PER_SECOND const outputs = convertTransactionsOutputTypesToWrappedOutputs(transactionId, regularTransactionEssence.outputs) @@ -48,49 +33,21 @@ export async function preprocessOutgoingTransaction( }) const inputs = await Promise.all(inputIds.map((inputId) => wallet.getOutput(inputId))) - - const addressToConsiderWhenCalculatingMana = [ - ...inputs - .filter(isAccountOutput) - .map((accountInput) => - AddressConverter.addressToBech32( - new AccountAddress((accountInput.output as unknown as AccountOutput).accountId) - ) - ), - implicitAddress, - walletAddress, - ] - - const inputsToConsiderWhenCalculatingMana = inputs.filter((input) => - addressToConsiderWhenCalculatingMana.find((address) => - isOutputUnlockedByAddress(input.output as CommonOutput, address) - ) - ) - - const outputsToConsiderWhenCalculatingMana = outputs.filter((output) => - addressToConsiderWhenCalculatingMana.find((address) => - isOutputUnlockedByAddress(output.output as CommonOutput, address) - ) - ) - - const prevManaCost = inputsToConsiderWhenCalculatingMana.reduce( - (acc, input) => acc + (getPassiveManaForOutput(input) ?? 0), - 0 - ) - - const postManaCost = outputsToConsiderWhenCalculatingMana.reduce( - (acc, output) => - acc + Number((output.output as BasicOutput | AccountOutput | AnchorOutput | NftOutput).mana ?? 0), - 0 + const totalTransactionMana = await getTotalTransactionMana( + inputs, + outputs, + wallet, + regularTransactionEssence.creationSlot, + createTransactionTimestamp ) return { outputs: outputs, transactionId, direction, - time: new Date(slotUnixTimestamp * MILLISECONDS_PER_SECOND), + time: new Date(createTransactionTimestamp), inclusionState: transaction.inclusionState, - mana: prevManaCost - postManaCost, + mana: totalTransactionMana, wrappedInputs: inputs, utxoInputs, } From d1cdc37fa04df471d6f8529a00473c7f44757d4c Mon Sep 17 00:00:00 2001 From: cpl121 Date: Thu, 25 Apr 2024 17:25:10 +0200 Subject: [PATCH 03/13] fix: check type --- .../lib/core/wallet/utils/outputs/getTotalTransactionMana.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts b/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts index b5ac326ea9a..46da3e32a37 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts @@ -7,6 +7,7 @@ import { CommonOutput, ExpirationUnlockCondition, NftOutput, + OutputData, UnlockConditionType, } from '@iota/sdk/out/types' import { IWalletState } from '@core/wallet/interfaces' @@ -57,7 +58,7 @@ export async function getTotalTransactionMana( ) const prevManaCost = inputsToConsiderWhenCalculatingMana.reduce( - (acc, input) => acc + (getPassiveManaForOutput(input, transactionSlot) ?? 0), + (acc, input) => acc + (getPassiveManaForOutput(input as OutputData, transactionSlot) ?? 0), 0 ) From f8c2dc3cb7a773e827ec535a25022a19b78e07ce Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 26 Apr 2024 15:29:24 +0200 Subject: [PATCH 04/13] fixes and improvements --- .../components/AccountManagementDetails.svelte | 2 +- .../events-handlers/handleNewOutputEvent.ts | 2 +- .../generateActivitiesFromBasicOutputs.ts | 8 ++++++-- .../core/wallet/utils/getInvolvedAddresses.ts | 16 ++++++++++++++++ packages/shared/lib/core/wallet/utils/index.ts | 1 + .../core/wallet/utils/isImplicitAccountOutput.ts | 6 +++--- .../wallet/utils/isOutputUnlockedByAddress.ts | 16 +++++++--------- .../outputs/getRecipientAddressFromOutput.ts | 6 +++--- .../utils/outputs/getTotalTransactionMana.ts | 13 ++----------- .../outputs/preprocessOutgoingTransaction.ts | 5 +++-- .../getDirectionFromOutgoingTransaction.ts | 4 ++-- 11 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts diff --git a/packages/desktop/components/AccountManagementDetails.svelte b/packages/desktop/components/AccountManagementDetails.svelte index 6ba3ac9d36f..a66628d2c6f 100644 --- a/packages/desktop/components/AccountManagementDetails.svelte +++ b/packages/desktop/components/AccountManagementDetails.svelte @@ -51,7 +51,7 @@ const explorerUrl = getOfficialExplorerUrl($activeProfile?.network?.id) - $: isImplicitAccount = isImplicitAccountOutput(selectedOutput) + $: isImplicitAccount = isImplicitAccountOutput(selectedOutput.output) $: accountId = isAccountOutput(selectedOutput) ? (selectedOutput.output as AccountOutput)?.accountId : null $: address = accountId ? AddressConverter.addressToBech32(new AccountAddress(accountId)) : null $: isMainAccount = accountId && accountId === $selectedWalletMainAccountId diff --git a/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts b/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts index 5e6ea9b6dca..0a1c42c00ef 100644 --- a/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts +++ b/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts @@ -61,7 +61,7 @@ export async function handleNewOutputEventInternal(walletId: string, payload: Ne await generateAndStoreActivitiesForWallet(wallet) } - if (isImplicitAccountOutput(outputData)) { + if (isImplicitAccountOutput(outputData.output)) { await syncBalance(wallet.id, true) const implicitAccountOutputs = await wallet.implicitAccounts() updateActiveWallet(wallet.id, { implicitAccountOutputs }) diff --git a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts index 9f5fdd9fb89..69323bf74b3 100644 --- a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts +++ b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts @@ -8,6 +8,8 @@ import { getBasicOrAccountOutputsFromTransaction, IProcessedTransaction, IWrappedOutput, + getInvolvedAddresses, + isImplicitAccountOutput, } from '@core/wallet' import { Activity } from '@core/wallet/types' import { generateSingleBasicActivity } from './generateSingleBasicActivity' @@ -21,15 +23,17 @@ export async function generateActivitiesFromBasicOutputs( ): Promise { const activities = [] + const involvedAddresses = await getInvolvedAddresses(wallet) + const basicOrAccountInputs = getBasicOrAccountOutputsFromTransaction( processedTransaction.wrappedInputs, - [await wallet.address(), await wallet.implicitAccountCreationAddress()], + involvedAddresses, processedTransaction.direction ) const basicOrAccountOutputs = getBasicOrAccountOutputsFromTransaction( processedTransaction.outputs, - [await wallet.address(), await wallet.implicitAccountCreationAddress()], + involvedAddresses, processedTransaction.direction ) const burnedNftInputs = getBurnedNftInputs(processedTransaction) diff --git a/packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts b/packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts new file mode 100644 index 00000000000..ef75736c797 --- /dev/null +++ b/packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts @@ -0,0 +1,16 @@ +import { AccountAddress, AccountOutput } from "@iota/sdk/out/types" +import { IWallet } from "../../profile" +import { AddressConverter } from "./AddressConverter" + +export async function getInvolvedAddresses(wallet: IWallet): Promise { + const walletAddress = await wallet.address() + const implicitAddress = await wallet.implicitAccountCreationAddress() + // We are ignoring accounts that the wallet may have had in the past + const currentAccountsAddresses = (await wallet.accounts()).map((accountInput) => + AddressConverter.addressToBech32( + new AccountAddress((accountInput.output as unknown as AccountOutput).accountId) + ) + ) + + return [...currentAccountsAddresses, implicitAddress, walletAddress] +} \ No newline at end of file diff --git a/packages/shared/lib/core/wallet/utils/index.ts b/packages/shared/lib/core/wallet/utils/index.ts index 9eec5acbbd9..49f34ec89c7 100644 --- a/packages/shared/lib/core/wallet/utils/index.ts +++ b/packages/shared/lib/core/wallet/utils/index.ts @@ -41,6 +41,7 @@ export * from './isVisibleAsset' export * from './isVisibleActivity' export * from './isOutputUnlockedByAddress' export * from './hasWalletMainAccountNegativeBIC' +export * from './getInvolvedAddresses' // Folders export * from './generateActivity' diff --git a/packages/shared/lib/core/wallet/utils/isImplicitAccountOutput.ts b/packages/shared/lib/core/wallet/utils/isImplicitAccountOutput.ts index d1511069f51..b3342c36254 100644 --- a/packages/shared/lib/core/wallet/utils/isImplicitAccountOutput.ts +++ b/packages/shared/lib/core/wallet/utils/isImplicitAccountOutput.ts @@ -4,11 +4,11 @@ import { UnlockConditionType, AddressUnlockCondition, AddressType, - OutputData, + Output, } from '@iota/sdk/out/types' -export function isImplicitAccountOutput(outputData: OutputData): boolean { - const output = outputData.output as CommonOutput +export function isImplicitAccountOutput(_output: Output): boolean { + const output = _output as CommonOutput return ( output?.type === OutputType.Basic && output.unlockConditions.length === 1 && diff --git a/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts b/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts index a0810a1ba1c..18eb8cc8b87 100644 --- a/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts +++ b/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts @@ -1,12 +1,10 @@ -import { CommonOutput, UnlockConditionType, AddressUnlockCondition } from '@iota/sdk/out/types' -import { AddressConverter } from './AddressConverter' +import { CommonOutput } from '@iota/sdk/out/types' +import { getRecipientAddressFromOutput } from './outputs' export function isOutputUnlockedByAddress(output: CommonOutput, address: string): boolean { - const outputAddress = ( - output.unlockConditions.find( - (unlockCondition) => unlockCondition.type === UnlockConditionType.Address - ) as AddressUnlockCondition - ).address - const bech32Address = AddressConverter.addressToBech32(outputAddress) - return bech32Address === address + const outputAddress = getRecipientAddressFromOutput(output) + if(!outputAddress) { + return false + } + return outputAddress === address } diff --git a/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts b/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts index 06b00270248..d6d6699e7b4 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts @@ -1,10 +1,10 @@ -import { AddressUnlockCondition, CommonOutput, UnlockConditionType } from '@iota/sdk/out/types' +import { AddressUnlockCondition, CommonOutput, ImmutableAccountAddressUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types' import { AddressConverter } from '../AddressConverter' export function getRecipientAddressFromOutput(output: CommonOutput): string | undefined { for (const unlockCondition of output.unlockConditions) { - if (unlockCondition.type === UnlockConditionType.Address) { - const addressUnlockCondition = unlockCondition as AddressUnlockCondition + if ([UnlockConditionType.Address, UnlockConditionType.ImmutableAccountAddress].includes(unlockCondition.type)) { + const addressUnlockCondition = unlockCondition as AddressUnlockCondition | ImmutableAccountAddressUnlockCondition return AddressConverter.addressToBech32(addressUnlockCondition.address) } } diff --git a/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts b/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts index 46da3e32a37..868799c06d4 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/getTotalTransactionMana.ts @@ -1,6 +1,5 @@ import { IWrappedOutput } from '../../interfaces' import { - AccountAddress, AccountOutput, AnchorOutput, BasicOutput, @@ -15,6 +14,7 @@ import { getPassiveManaForOutput } from '@core/network' import { isOutputUnlockedByAddress } from '../isOutputUnlockedByAddress' import { AddressConverter } from '../AddressConverter' import { getExpirationDateFromOutput } from './getExpirationDateFromOutput' +import { getInvolvedAddresses } from '../getInvolvedAddresses' export async function getTotalTransactionMana( inputs: IWrappedOutput[], @@ -23,16 +23,7 @@ export async function getTotalTransactionMana( transactionSlot: number, transactionTimestamp: number ): Promise { - const walletAddress = await wallet.address() - const implicitAddress = await wallet.implicitAccountCreationAddress() - // We are ignoring accounts that the wallet may have had in the past - const currentAccountsAddresses = (await wallet.accounts()).map((accountInput) => - AddressConverter.addressToBech32( - new AccountAddress((accountInput.output as unknown as AccountOutput).accountId) - ) - ) - - const addressToConsiderWhenCalculatingMana = [...currentAccountsAddresses, implicitAddress, walletAddress] + const addressToConsiderWhenCalculatingMana = await getInvolvedAddresses(wallet) const inputsToConsiderWhenCalculatingMana = inputs.filter((input) => { const commonInput = input.output as CommonOutput diff --git a/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts b/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts index 14536f30869..39f4c2d9c6d 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/preprocessOutgoingTransaction.ts @@ -8,6 +8,7 @@ import { MILLISECONDS_PER_SECOND } from '@core/utils' import { getUnixTimestampFromNodeInfoAndSlotIndex, nodeInfoProtocolParameters } from '@core/network' import { get } from 'svelte/store' import { getTotalTransactionMana } from './getTotalTransactionMana' +import { getInvolvedAddresses } from '../getInvolvedAddresses' export async function preprocessOutgoingTransaction( transaction: TransactionWithMetadata, @@ -16,7 +17,7 @@ export async function preprocessOutgoingTransaction( const regularTransactionEssence = transaction.payload.transaction const transactionId = transaction?.transactionId?.toString() const nodeProtocolParameters = get(nodeInfoProtocolParameters) - const walletAddress = await wallet.address() + const involvedAddresses = await getInvolvedAddresses(wallet) const createTransactionUnixTimestamp = nodeProtocolParameters ? getUnixTimestampFromNodeInfoAndSlotIndex(nodeProtocolParameters, regularTransactionEssence.creationSlot) : 0 @@ -24,7 +25,7 @@ export async function preprocessOutgoingTransaction( const outputs = convertTransactionsOutputTypesToWrappedOutputs(transactionId, regularTransactionEssence.outputs) - const direction = getDirectionFromOutgoingTransaction(regularTransactionEssence.outputs, walletAddress) + const direction = getDirectionFromOutgoingTransaction(regularTransactionEssence.outputs, involvedAddresses) const utxoInputs = regularTransactionEssence.inputs.map((i) => i as UTXOInput) const inputIds = utxoInputs.map((input) => { const transactionId = input.transactionId diff --git a/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts b/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts index 094bd920052..bbba14d842c 100644 --- a/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts +++ b/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts @@ -4,12 +4,12 @@ import { CommonOutput, Output } from '@iota/sdk/out/types' export function getDirectionFromOutgoingTransaction( outputs: Output[], - walletDepositAddress: string + involvedAddresses: string[] ): ActivityDirection { // Check if any output is not destined for the wallet const containsNonWalletRecipient = outputs.some((output) => { const outputRecipient = getRecipientAddressFromOutput(output as CommonOutput) - return walletDepositAddress !== outputRecipient + return !involvedAddresses.includes(outputRecipient) }) // If there is any output not destined for the wallet, it's an outgoing transaction. From 9a419f7bbda5f3e0093e90fff93e76f413f1e38d Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 26 Apr 2024 15:31:02 +0200 Subject: [PATCH 05/13] fix --- .../lib/core/wallet/utils/getInvolvedAddresses.ts | 8 ++++---- .../core/wallet/utils/isOutputUnlockedByAddress.ts | 2 +- .../utils/outputs/getRecipientAddressFromOutput.ts | 11 +++++++++-- .../getDirectionFromOutgoingTransaction.ts | 5 +---- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts b/packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts index ef75736c797..5a333d43043 100644 --- a/packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts +++ b/packages/shared/lib/core/wallet/utils/getInvolvedAddresses.ts @@ -1,6 +1,6 @@ -import { AccountAddress, AccountOutput } from "@iota/sdk/out/types" -import { IWallet } from "../../profile" -import { AddressConverter } from "./AddressConverter" +import { AccountAddress, AccountOutput } from '@iota/sdk/out/types' +import { IWallet } from '../../profile' +import { AddressConverter } from './AddressConverter' export async function getInvolvedAddresses(wallet: IWallet): Promise { const walletAddress = await wallet.address() @@ -13,4 +13,4 @@ export async function getInvolvedAddresses(wallet: IWallet): Promise { ) return [...currentAccountsAddresses, implicitAddress, walletAddress] -} \ No newline at end of file +} diff --git a/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts b/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts index 18eb8cc8b87..b29f2b51eb6 100644 --- a/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts +++ b/packages/shared/lib/core/wallet/utils/isOutputUnlockedByAddress.ts @@ -3,7 +3,7 @@ import { getRecipientAddressFromOutput } from './outputs' export function isOutputUnlockedByAddress(output: CommonOutput, address: string): boolean { const outputAddress = getRecipientAddressFromOutput(output) - if(!outputAddress) { + if (!outputAddress) { return false } return outputAddress === address diff --git a/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts b/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts index d6d6699e7b4..71662bc5b3a 100644 --- a/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts +++ b/packages/shared/lib/core/wallet/utils/outputs/getRecipientAddressFromOutput.ts @@ -1,10 +1,17 @@ -import { AddressUnlockCondition, CommonOutput, ImmutableAccountAddressUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types' +import { + AddressUnlockCondition, + CommonOutput, + ImmutableAccountAddressUnlockCondition, + UnlockConditionType, +} from '@iota/sdk/out/types' import { AddressConverter } from '../AddressConverter' export function getRecipientAddressFromOutput(output: CommonOutput): string | undefined { for (const unlockCondition of output.unlockConditions) { if ([UnlockConditionType.Address, UnlockConditionType.ImmutableAccountAddress].includes(unlockCondition.type)) { - const addressUnlockCondition = unlockCondition as AddressUnlockCondition | ImmutableAccountAddressUnlockCondition + const addressUnlockCondition = unlockCondition as + | AddressUnlockCondition + | ImmutableAccountAddressUnlockCondition return AddressConverter.addressToBech32(addressUnlockCondition.address) } } diff --git a/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts b/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts index bbba14d842c..16b1299476c 100644 --- a/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts +++ b/packages/shared/lib/core/wallet/utils/transactions/getDirectionFromOutgoingTransaction.ts @@ -2,10 +2,7 @@ import { getRecipientAddressFromOutput } from '../outputs/getRecipientAddressFro import { ActivityDirection } from '@core/wallet/enums' import { CommonOutput, Output } from '@iota/sdk/out/types' -export function getDirectionFromOutgoingTransaction( - outputs: Output[], - involvedAddresses: string[] -): ActivityDirection { +export function getDirectionFromOutgoingTransaction(outputs: Output[], involvedAddresses: string[]): ActivityDirection { // Check if any output is not destined for the wallet const containsNonWalletRecipient = outputs.some((output) => { const outputRecipient = getRecipientAddressFromOutput(output as CommonOutput) From 0b496122469677926ddce24c12327d37fccda3f9 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 26 Apr 2024 15:32:20 +0200 Subject: [PATCH 06/13] fix: Consolidation activities --- .../generateActivitiesFromBasicOutputs.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts index 69323bf74b3..62094a8c272 100644 --- a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts +++ b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts @@ -185,11 +185,21 @@ function getAllNativeTokensFromOutputs(outputs: IWrappedOutput[]): { [key: strin } function isConsolidation(output: IWrappedOutput, processedTransaction: IProcessedTransaction): boolean { - const allBasicInputs = processedTransaction.wrappedInputs.every((input) => input.output.type === OutputType.Basic) + const consolidatedInputs = processedTransaction.wrappedInputs.filter((input) => { + const isBasic = input.output.type === OutputType.Basic; + const isAccount = input.output.type === OutputType.Account; + const isImplicitAccountFeature = isImplicitAccountOutput(input.output) + return (isBasic || isAccount) && !isImplicitAccountFeature + }) + const inputsOfSameType = consolidatedInputs.filter(op => { + return op.output.type === output.output.type + }); const isSelfTransaction = processedTransaction.direction === ActivityDirection.SelfTransaction const isSameAmount = - processedTransaction.wrappedInputs.reduce((sum, input) => sum + Number(input.output.amount), 0) === + inputsOfSameType.reduce((sum, input) => sum + Number(input.output.amount), 0) === Number(output.output.amount) - return allBasicInputs && isSelfTransaction && isSameAmount + const allBasicNonImplicitAccountOrAccountsInputs = consolidatedInputs.length === processedTransaction.wrappedInputs.length; + + return allBasicNonImplicitAccountOrAccountsInputs && isSelfTransaction && isSameAmount } From 587e0b8ae19d9205ae62810479fbfd323e952c71 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 26 Apr 2024 15:33:29 +0200 Subject: [PATCH 07/13] fmt --- .../generateActivitiesFromBasicOutputs.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts index 62094a8c272..9ea3aef73b5 100644 --- a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts +++ b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts @@ -186,20 +186,18 @@ function getAllNativeTokensFromOutputs(outputs: IWrappedOutput[]): { [key: strin function isConsolidation(output: IWrappedOutput, processedTransaction: IProcessedTransaction): boolean { const consolidatedInputs = processedTransaction.wrappedInputs.filter((input) => { - const isBasic = input.output.type === OutputType.Basic; - const isAccount = input.output.type === OutputType.Account; + const isBasic = input.output.type === OutputType.Basic + const isAccount = input.output.type === OutputType.Account const isImplicitAccountFeature = isImplicitAccountOutput(input.output) return (isBasic || isAccount) && !isImplicitAccountFeature }) - const inputsOfSameType = consolidatedInputs.filter(op => { - return op.output.type === output.output.type - }); + const inputsOfSameType = consolidatedInputs.filter((op) => op.output.type === output.output.type) const isSelfTransaction = processedTransaction.direction === ActivityDirection.SelfTransaction const isSameAmount = - inputsOfSameType.reduce((sum, input) => sum + Number(input.output.amount), 0) === - Number(output.output.amount) + inputsOfSameType.reduce((sum, input) => sum + Number(input.output.amount), 0) === Number(output.output.amount) - const allBasicNonImplicitAccountOrAccountsInputs = consolidatedInputs.length === processedTransaction.wrappedInputs.length; + const allBasicNonImplicitAccountOrAccountsInputs = + consolidatedInputs.length === processedTransaction.wrappedInputs.length return allBasicNonImplicitAccountOrAccountsInputs && isSelfTransaction && isSameAmount } From de2e505c4c7513e0daad49ef49125f128924366b Mon Sep 17 00:00:00 2001 From: evavirseda Date: Fri, 26 Apr 2024 15:38:25 +0200 Subject: [PATCH 08/13] fix linter --- .../utils/generateActivity/generateActivitiesFromBasicOutputs.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts index 69323bf74b3..50b40b4a479 100644 --- a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts +++ b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts @@ -9,7 +9,6 @@ import { IProcessedTransaction, IWrappedOutput, getInvolvedAddresses, - isImplicitAccountOutput, } from '@core/wallet' import { Activity } from '@core/wallet/types' import { generateSingleBasicActivity } from './generateSingleBasicActivity' From 1216212fe7ebd6919b4514552bf6ab51a606e52b Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 26 Apr 2024 16:04:28 +0200 Subject: [PATCH 09/13] fix --- .../utils/generateActivity/generateActivitiesFromBasicOutputs.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts index 00f1364aaa7..9ea3aef73b5 100644 --- a/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts +++ b/packages/shared/lib/core/wallet/utils/generateActivity/generateActivitiesFromBasicOutputs.ts @@ -9,6 +9,7 @@ import { IProcessedTransaction, IWrappedOutput, getInvolvedAddresses, + isImplicitAccountOutput, } from '@core/wallet' import { Activity } from '@core/wallet/types' import { generateSingleBasicActivity } from './generateSingleBasicActivity' From 84a4e45f78d2a61e9d512ed63a702e82e5731f3d Mon Sep 17 00:00:00 2001 From: marc2332 Date: Tue, 30 Apr 2024 15:20:46 +0200 Subject: [PATCH 10/13] fix: Claim to account --- .../popups/ActivityDetailsPopup.svelte | 6 +++++- .../components/popups/AllotManaPopup.svelte | 4 ++-- .../lib/core/wallet/actions/claimActivity.ts | 3 ++- .../utils/getAccountTransactionOptions.ts | 17 +++++++++++++++++ .../utils/getDefaultTransactionOptions.ts | 6 +----- packages/shared/lib/core/wallet/utils/index.ts | 1 + 6 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 packages/shared/lib/core/wallet/utils/getAccountTransactionOptions.ts diff --git a/packages/desktop/components/popups/ActivityDetailsPopup.svelte b/packages/desktop/components/popups/ActivityDetailsPopup.svelte index 8e67ac01dfb..ad912b5c4bb 100644 --- a/packages/desktop/components/popups/ActivityDetailsPopup.svelte +++ b/packages/desktop/components/popups/ActivityDetailsPopup.svelte @@ -11,6 +11,7 @@ ActivityDirection, ActivityType, claimActivity, + getAccountTransactionOptions, hasWalletMainAccountNegativeBIC, ignoreActivity, selectedWallet, @@ -81,7 +82,10 @@ async function prepareClaimOutput(): Promise { try { - transactionInfo.preparedTransaction = await $selectedWallet?.prepareClaimOutputs([activity.outputId]) + transactionInfo.preparedTransaction = await $selectedWallet?.prepareClaimOutputs( + [activity.outputId], + getAccountTransactionOptions() + ) } catch (error) { transactionInfo.preparedTransactionError = error } diff --git a/packages/desktop/components/popups/AllotManaPopup.svelte b/packages/desktop/components/popups/AllotManaPopup.svelte index 88d5f764dce..53ed9616ca3 100644 --- a/packages/desktop/components/popups/AllotManaPopup.svelte +++ b/packages/desktop/components/popups/AllotManaPopup.svelte @@ -77,7 +77,7 @@ getDefaultTransactionOptions() ) transactionInfo.preparedTransaction = await $selectedWallet.prepareSendOutputs([prepareOutput], { - ...getDefaultTransactionOptions(accountId), + ...getDefaultTransactionOptions(), manaAllotments: { [accountId]: Number(rawAmount) }, }) } catch (error) { @@ -94,7 +94,7 @@ getDefaultTransactionOptions() ) await $selectedWallet.sendOutputs([prepareOutput], { - ...getDefaultTransactionOptions(accountId), + ...getDefaultTransactionOptions(), manaAllotments: { [accountId]: Number(rawAmount) }, // if manaAllotments amount passed as bigint it is transformed to string in the sdk }) closePopup() diff --git a/packages/shared/lib/core/wallet/actions/claimActivity.ts b/packages/shared/lib/core/wallet/actions/claimActivity.ts index 49805bde032..a891d71bc81 100644 --- a/packages/shared/lib/core/wallet/actions/claimActivity.ts +++ b/packages/shared/lib/core/wallet/actions/claimActivity.ts @@ -7,6 +7,7 @@ import { updateAsyncDataByActivityId, } from '../stores' import { Activity } from '../types' +import { getAccountTransactionOptions } from '../utils' export async function claimActivity(activity: Activity): Promise { const wallet = getSelectedWallet() @@ -17,7 +18,7 @@ export async function claimActivity(activity: Activity): Promise { } updateAsyncDataByActivityId(wallet.id, activity.id, { isClaiming: true }) - const result = await wallet.claimOutputs([activity.outputId]) + const result = await wallet.claimOutputs([activity.outputId], getAccountTransactionOptions()) const transactionId = result.transactionId updateAsyncDataByActivityId(wallet.id, activity.id, { claimingTransactionId: transactionId }) } catch (err) { diff --git a/packages/shared/lib/core/wallet/utils/getAccountTransactionOptions.ts b/packages/shared/lib/core/wallet/utils/getAccountTransactionOptions.ts new file mode 100644 index 00000000000..f01ac322693 --- /dev/null +++ b/packages/shared/lib/core/wallet/utils/getAccountTransactionOptions.ts @@ -0,0 +1,17 @@ +import { AccountAddress, TransactionOptions } from '@iota/sdk/out/types' +import { getSelectedWallet } from '../stores' + +export function getAccountTransactionOptions( + accountId: string | undefined = getSelectedWallet()?.mainAccountId +): TransactionOptions | undefined { + if (!accountId) return + return { + remainderValueStrategy: { + /** The name of the strategy. */ + strategy: 'CustomAddress', + /** Only required for `CustomAddress`. */ + value: new AccountAddress(accountId), + }, + allowMicroAmount: true, + } +} diff --git a/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts b/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts index 29ff3c0cd02..ba3c3972761 100644 --- a/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts +++ b/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts @@ -1,10 +1,6 @@ import { TransactionOptions } from '@iota/sdk/out/types' -import { getSelectedWallet } from '../stores' -export function getDefaultTransactionOptions( - accountId: string | undefined = getSelectedWallet()?.mainAccountId -): TransactionOptions | undefined { - if (!accountId) return +export function getDefaultTransactionOptions(): TransactionOptions | undefined { return { remainderValueStrategy: { /** The name of the strategy. */ diff --git a/packages/shared/lib/core/wallet/utils/index.ts b/packages/shared/lib/core/wallet/utils/index.ts index 49f34ec89c7..aa5d5011adf 100644 --- a/packages/shared/lib/core/wallet/utils/index.ts +++ b/packages/shared/lib/core/wallet/utils/index.ts @@ -42,6 +42,7 @@ export * from './isVisibleActivity' export * from './isOutputUnlockedByAddress' export * from './hasWalletMainAccountNegativeBIC' export * from './getInvolvedAddresses' +export * from './getAccountTransactionOptions' // Folders export * from './generateActivity' From 9ae924d26c2a8e2ff55518be21ac9b3e0f034d1f Mon Sep 17 00:00:00 2001 From: marc2332 Date: Thu, 2 May 2024 16:07:53 +0200 Subject: [PATCH 11/13] chore: alpha 9 --- packages/shared/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/shared/package.json b/packages/shared/package.json index 178524f0ad8..dde2822b9a0 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -5,7 +5,7 @@ "license": "Apache-2.0", "dependencies": { "@iota/crypto.js": "^1.8.6", - "@iota/sdk": "2.0.0-alpha.8", + "@iota/sdk": "2.0.0-alpha.9", "@iota/unit-converter": "^1.0.0-beta.30", "@iota/util.js": "^2.0.0-rc.1", "@sveltejs/svelte-virtual-list": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index 6c46db325c3..938b230f657 100644 --- a/yarn.lock +++ b/yarn.lock @@ -712,10 +712,10 @@ "@iota/util.js" "^1.8.6" big-integer "^1.6.51" -"@iota/sdk@2.0.0-alpha.8": - version "2.0.0-alpha.8" - resolved "https://registry.yarnpkg.com/@iota/sdk/-/sdk-2.0.0-alpha.8.tgz#f93504179a170b6c13a1e188a73087514e3a4160" - integrity sha512-slvpu3l/r4SllE+c0EQOZwNEX4LkxKS/mihNtVVeV8vK8ppetAx0gOKjInrZoDBAQk4uZgHgD7+PhTnOBg1reQ== +"@iota/sdk@2.0.0-alpha.9": + version "2.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@iota/sdk/-/sdk-2.0.0-alpha.9.tgz#79d44f851b25d43fddf33fdffe634e8e434a8827" + integrity sha512-0ovOJ3q6EQ12ZhEVsNKng7bWCA66+qsat3Y+mH4RnoQYnHQQ65DsOvkgJkpiMxorsn9IjrQGCSrk0/tHRhFvEA== dependencies: class-transformer "^0.5.1" prebuild-install "^7.1.1" From c1a106a278be9a33cd3868fc15cc8b9ca0c2d6c2 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 3 May 2024 09:41:55 +0200 Subject: [PATCH 12/13] clean up --- .../actions/events-handlers/handleNewOutputEvent.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts b/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts index 0a1c42c00ef..6978b148cba 100644 --- a/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts +++ b/packages/shared/lib/core/wallet/actions/events-handlers/handleNewOutputEvent.ts @@ -43,16 +43,9 @@ export async function handleNewOutputEventInternal(walletId: string, payload: Ne const isNftOutput = output.type === OutputType.Nft const _isDelegationOutput = isDelegationOutput(outputData) - const address = outputData.address ? AddressConverter.addressToBech32(outputData.address) : undefined - // The basic outputs of the faucet dont have an address const isBasicOutput = output.type === OutputType.Basic - if ( - (address && wallet?.depositAddress === address && !outputData?.remainder) || - isAccountOutput(outputData) || - isDelegationOutput(outputData) || - isBasicOutput - ) { + if (!outputData?.remainder || isAccountOutput(outputData) || isDelegationOutput(outputData) || isBasicOutput) { await syncBalance(wallet.id, true) const walletOutputs = await wallet.outputs() const walletUnspentOutputs = await wallet.unspentOutputs() From e4c70429087b948f512968c49f49ab1975538f3c Mon Sep 17 00:00:00 2001 From: cpl121 Date: Fri, 3 May 2024 14:37:30 +0200 Subject: [PATCH 13/13] fix: clean up --- .../lib/core/wallet/utils/getDefaultTransactionOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts b/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts index ba3c3972761..39b919f0fc3 100644 --- a/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts +++ b/packages/shared/lib/core/wallet/utils/getDefaultTransactionOptions.ts @@ -1,6 +1,6 @@ import { TransactionOptions } from '@iota/sdk/out/types' -export function getDefaultTransactionOptions(): TransactionOptions | undefined { +export function getDefaultTransactionOptions(): TransactionOptions { return { remainderValueStrategy: { /** The name of the strategy. */