Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 1 addition & 60 deletions src/composables/fungibleTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type {
AccountAddress,
AssetContractId,
AssetList,
BigNumberPublic,
IToken,
ITokenBalance,
ITransaction,
Expand All @@ -17,12 +16,10 @@ import type {
Dictionary,
ITx,
} from '@/types';
import { PROTOCOLS, STORAGE_KEYS, TX_DIRECTION } from '@/constants';
import { PROTOCOLS, STORAGE_KEYS } from '@/constants';
import { ProtocolAdapterFactory } from '@/lib/ProtocolAdapterFactory';

import FungibleTokenFullInterfaceACI from '@/protocols/aeternity/aci/FungibleTokenFullInterfaceACI.json';
import { AE_COIN_PRECISION } from '@/protocols/aeternity/config';
import { aettosToAe, categorizeContractCallTxObject } from '@/protocols/aeternity/helpers';

import { uniqBy } from 'lodash-es';
import { useAccounts } from './accounts';
Expand Down Expand Up @@ -232,61 +229,6 @@ export function useFungibleTokens() {
: protocolTokens[tx.contractId]?.symbol;
}

/**
* TODO move this function to utilities and make it not dependant on token list
*/
function getTxAmountTotal(
transaction: ITransaction,
direction: string = TX_DIRECTION.sent,
) {
const isReceived = direction === TX_DIRECTION.received;
const { protocol, tx } = transaction || {};

// This is out of place but since we are treating new protocols as fungible tokens
// it is better to have it here than in the protocol specific helper file
if (protocol && protocol !== PROTOCOLS.aeternity) {
return new BigNumber(tx?.amount || 0)
.plus(isReceived || !isAssetCoin(tx.contractId) ? 0 : tx?.fee || 0)
.toNumber();
}

const contractCallData = transaction?.tx && categorizeContractCallTxObject(transaction);

const tokenData = protocol
&& getProtocolAvailableTokens(protocol)[contractCallData?.assetContractId!];

if (contractCallData && tokenData) {
return +toShiftedBigNumber(
contractCallData.amount || 0,
-(tokenData.decimals || AE_COIN_PRECISION), // TODO possibility of temporary wrong precision
);
}

const claimTipAmount = (tx.function === 'claim') ? tx.log?.[0]?.topics[2] : null;

const rawAmount = (
tx?.amount
|| (tx?.tx?.tx as any)?.amount
|| tx?.nameFee
|| claimTipAmount
|| 0
);

const amount: BigNumberPublic = (typeof rawAmount === 'object')
? rawAmount
: new BigNumber(Number(rawAmount));

let gasCost = new BigNumber(0);
if (tx?.gasPrice && tx?.gasUsed) {
gasCost = new BigNumber(tx.gasPrice).multipliedBy(tx.gasUsed);
}

return +aettosToAe(amount
.plus(isReceived ? 0 : tx?.fee || 0)
.plus(isReceived ? 0 : tx?.tx?.tx?.fee || 0)
.plus(isReceived ? 0 : gasCost));
}

availableTokensPooling(() => loadAvailableTokens());
tokenBalancesPooling(() => loadTokenBalances());

Expand Down Expand Up @@ -325,7 +267,6 @@ export function useFungibleTokens() {
getAccountTokenBalances,
getProtocolAvailableTokens,
getTxAssetSymbol,
getTxAmountTotal,
loadTokenBalances,
loadAvailableTokens,
};
Expand Down
104 changes: 81 additions & 23 deletions src/composables/transactionData.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import BigNumber from 'bignumber.js';
import { computed, Ref } from 'vue';
import { Tag } from '@aeternity/aepp-sdk';
import type {
AccountAddress,
BigNumberPublic,
ITokenResolved,
ITransaction,
ObjectValues,
Expand All @@ -24,9 +26,11 @@ import {
TX_FUNCTIONS,
TX_FUNCTIONS_MULTISIG,
TX_FUNCTIONS_TYPE_DEX,
AE_COIN_PRECISION,
} from '@/protocols/aeternity/config';
import {
aettosToAe,
categorizeContractCallTxObject,
getInnerTransaction,
getOwnershipStatus,
getTransactionTokenInfoResolver,
Expand Down Expand Up @@ -63,7 +67,7 @@ export function useTransactionData({
const { dexContracts } = useAeSdk();
const { accounts, activeAccount } = useAccounts();
const { tippingContractAddresses } = useTippingContracts();
const { getProtocolAvailableTokens, getTxAmountTotal, getTxAssetSymbol } = useFungibleTokens();
const { getProtocolAvailableTokens, getTxAssetSymbol } = useFungibleTokens();

const protocol = computed(() => transaction.value?.protocol || PROTOCOLS.aeternity);
const outerTx = computed(() => transaction.value?.tx);
Expand All @@ -74,6 +78,8 @@ export function useTransactionData({
const txFunctionParsed = computed(() => getTxFunctionParsed(innerTx.value?.function));
const txFunctionRaw = computed(() => getTxFunctionRaw(innerTx.value?.function));

const fee = computed((): number => outerTx.value?.fee || 0);

/**
* Transaction TX type value converted into human readable label
* displayed on the transaction details page.
Expand Down Expand Up @@ -185,11 +191,65 @@ export function useTransactionData({
);

/**
* Amount and fee calculated based on the direction.
* TODO most of the following calculations should be done right after fetching the transaction
*/
const amountTotal = computed(
(): number => (transaction.value) ? getTxAmountTotal(transaction.value, direction.value) : 0,
);
function getAmountFromAeTx(isReceived: boolean = false): number {
if (isDexAllowance.value) {
return toShiftedBigNumber(fee.value, -AE_COIN_PRECISION).toNumber();
}

const contractCallData = transaction.value?.tx
&& categorizeContractCallTxObject(transaction.value);

const tokenData = contractCallData
&& getProtocolAvailableTokens(PROTOCOLS.aeternity)[contractCallData.assetContractId!];

if (contractCallData && tokenData) {
return +toShiftedBigNumber(
contractCallData.amount || 0,
-(tokenData.decimals || AE_COIN_PRECISION), // TODO possibility of wrong precision
);
}

const claimTipAmount = (outerTx.value?.function === 'claim') ? outerTx.value?.log?.[0]?.topics[2] : null;
const rawAmount = innerTx.value.amount || innerTx.value?.nameFee || claimTipAmount || 0;
const amount: BigNumberPublic = (typeof rawAmount === 'object')
? rawAmount
: new BigNumber(Number(rawAmount));
const gasCost = (outerTx.value?.gasPrice && outerTx.value?.gasUsed)
? new BigNumber(outerTx.value.gasPrice).multipliedBy(outerTx.value.gasUsed)
: 0;

return +aettosToAe(
amount
.plus(isReceived ? 0 : outerTx.value?.fee || 0)
.plus(isReceived ? 0 : innerTx.value?.fee || 0)
.plus(isReceived ? 0 : gasCost),
);
}

function getAmountFromCommonTx(isReceived: boolean = false): number {
return new BigNumber(outerTx.value?.amount || 0)
.plus(isReceived ? 0 : fee.value)
.toNumber();
}

/**
* Amount without fee
*/
const amount = computed((): number => (protocol.value === PROTOCOLS.aeternity)
? getAmountFromAeTx()
: getAmountFromCommonTx());

/**
* Amount with the fee added when receiving the assets
*/
const amountTotal = computed((): number => {
const isReceived = direction.value === TX_DIRECTION.received;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isReceived could be a computed property and be used throughout the composable. It could also be exported from the composable and used in other places like TransactionDetails

return (protocol.value === PROTOCOLS.aeternity)
? getAmountFromAeTx(isReceived)
: getAmountFromCommonTx(isReceived);
});

/**
* List of assets used within the transaction.
Expand All @@ -204,6 +264,7 @@ export function useTransactionData({

const adapter = ProtocolAdapterFactory.getAdapter(protocol.value);
const protocolTokens = getProtocolAvailableTokens(protocol.value);
const contractIdToken = protocolTokens[outerTx.value?.contractId!];

/**
* Fake token to represent the fee in the transaction.
Expand All @@ -229,11 +290,11 @@ export function useTransactionData({
return functionResolver({ tx: outerTx.value } as ITransaction, protocolTokens)
.tokens
.map(({
amount,
amount: txAmount,
decimals,
...otherAssetData
}) => ({
amount: +toShiftedBigNumber(amount!, -decimals!),
amount: +toShiftedBigNumber(txAmount!, -decimals!),
...otherAssetData,
}));
}
Expand All @@ -246,31 +307,26 @@ export function useTransactionData({
}
}

const amount = (isDexAllowance.value)
? toShiftedBigNumber(innerTx.value?.fee || 0, -adapter.coinPrecision).toNumber()
: amountTotal.value;
const isReceived = direction.value === TX_DIRECTION.received;
const coinAssetData: ITokenResolved = {
...innerTx.value || {}, // TODO consider removing this line
...adapter.getDefaultCoin(),
amount: amount.value,
assetType: ASSET_TYPES.coin,
isReceived,
};

if (isTransactionCoin.value || isDexAllowance.value || isMultisig.value || convertToCoin) {
return [{
...innerTx.value || {},
...adapter.getDefaultCoin(),
amount,
assetType: ASSET_TYPES.coin,
isReceived,
}];
return [coinAssetData];
}

const token = protocolTokens[outerTx.value!.contractId];

return [{
...innerTx.value || {},
...token || {},
amount,
...innerTx.value || {}, // TODO consider removing this line
...contractIdToken || {},
amount: amount.value,
assetType: ASSET_TYPES.token,
contractId: outerTx.value?.contractId,
isReceived,
name: token?.name,
protocol,
symbol: getTxAssetSymbol(transaction.value),
}].concat(isReceived || hideFeeFromAssets ? [] : [feeToken]);
Expand All @@ -293,7 +349,9 @@ export function useTransactionData({
}

return {
amount,
amountTotal,
fee,
outerTxTag,
innerTxTag,
innerTx,
Expand Down
10 changes: 2 additions & 8 deletions src/protocols/aeternity/views/TransactionDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ import {
} from '@/utils';
import {
useAccounts,
useFungibleTokens,
useMultisigAccounts,
useTransactionData,
useTransactionList,
Expand Down Expand Up @@ -243,7 +242,6 @@ export default defineComponent({
const { activeMultisigAccountId } = useMultisigAccounts({ pollOnce: true });
const { activeAccount, isLocalAccountAddress } = useAccounts();
const { setLoaderVisible } = useUi();
const { getTxAmountTotal } = useFungibleTokens();

const hash = route.params.hash as string;
const transactionOwner = route.params.transactionOwner as Encoded.AccountAddress;
Expand All @@ -265,6 +263,8 @@ export default defineComponent({
const multisigContractId = ref<string>();

const {
amount,
amountTotal,
direction,
isAex9,
isErrorTransaction,
Expand All @@ -280,12 +280,6 @@ export default defineComponent({
showDetailedAllowanceInfo: true,
});

const amount = computed((): number => transaction.value
? getTxAmountTotal(transaction.value, TX_DIRECTION.received)
: 0);
const amountTotal = computed((): number => transaction.value
? getTxAmountTotal(transaction.value, direction.value)
: 0);
const tipUrl = computed(() => transaction.value ? getTransactionTipUrl(transaction.value) : '');
const tipLink = computed(() => /^http[s]*:\/\//.test(tipUrl.value) ? tipUrl.value : `http://${tipUrl.value}`);

Expand Down
10 changes: 0 additions & 10 deletions src/protocols/bitcoin/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import BigNumber from 'bignumber.js';
import type { ITransaction } from '@/types';
import { PROTOCOLS } from '@/constants';
import { BTC_COIN_PRECISION, BTC_CONTRACT_ID } from '../config';
Expand All @@ -7,15 +6,6 @@ export function satoshiToBtc(amount: number) {
return amount / 10 ** BTC_COIN_PRECISION;
}

// TODO Duplicate in fungibleTokens.ts composable
export function getTxAmountTotal(transaction: ITransaction, isReceived: boolean): number {
return new BigNumber(
transaction.tx?.amount || 0,
)
.plus(isReceived ? 0 : transaction.tx?.fee || 0)
.toNumber();
}

export function normalizeTransactionStructure(
transaction: any,
transactionOwner?: string,
Expand Down
14 changes: 7 additions & 7 deletions src/protocols/bitcoin/views/TransactionDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ import { IonContent, IonPage } from '@ionic/vue';

import type { ITokenResolved, ITransaction } from '@/types';
import { TX_DIRECTION, PROTOCOLS } from '@/constants';
import { useUi } from '@/composables';
import { useTransactionData, useUi } from '@/composables';
import { ProtocolAdapterFactory } from '@/lib/ProtocolAdapterFactory';
import { ROUTE_NOT_FOUND } from '@/popup/router/routeNames';
import { BTC_PROTOCOL_NAME, BTC_SYMBOL } from '@/protocols/bitcoin/config';
import { getTxAmountTotal } from '@/protocols/bitcoin/helpers';

import TransactionDetailsBase from '@/popup/components/TransactionDetailsBase.vue';
import TransactionAssetRows from '@/popup/components/TransactionAssetRows.vue';
Expand All @@ -68,12 +67,13 @@ export default defineComponent({

const transaction = ref<ITransaction>();

const {
amount,
amountTotal,
fee,
} = useTransactionData({ transaction });

const isReceived = computed(() => transaction.value?.tx?.senderId !== transactionOwner);
const fee = computed((): number => transaction.value?.tx?.fee || 0);
const amount = computed((): number => transaction.value?.tx?.amount || 0);
const amountTotal = computed((): number => transaction.value?.tx
? getTxAmountTotal(transaction.value, isReceived.value)
: 0);

const direction = computed(() => isReceived.value ? TX_DIRECTION.received : TX_DIRECTION.sent);

Expand Down
7 changes: 2 additions & 5 deletions src/protocols/ethereum/views/TransactionDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@

<script lang="ts">
import {
computed,
defineComponent,
onMounted,
ref,
Expand Down Expand Up @@ -106,7 +105,9 @@ export default defineComponent({
const { activeAccount } = useAccounts();
const { accountsTransactionsPending } = useLatestTransactionList();
const {
amount,
amountTotal,
fee,
transactionAssets,
isTransactionCoin,
} = useTransactionData({
Expand All @@ -119,10 +120,6 @@ export default defineComponent({
protocol: PROTOCOLS.ethereum,
});

// TODO move these calculations to base component after unifying ITransaction AE values
const fee = computed((): number => transaction.value?.tx?.fee || 0);
const amount = computed((): number => transaction.value?.tx?.amount || 0);

watch(
transaction,
(value) => {
Expand Down