mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Handle an RPC provider delay in Swaps (#14821)
* Return an estimated amount for a completed swap if an RPC provider has a delay * Create a recursive function for updating post tx balance * Add a few tests for the "getSwapsTokensReceivedFromTxMeta" fn * Trigger Build
This commit is contained in:
parent
4fa4930c8a
commit
b0557daa05
@ -41,6 +41,7 @@ import {
|
||||
PRIORITY_LEVELS,
|
||||
} from '../../../../shared/constants/gas';
|
||||
import { decGWEIToHexWEI } from '../../../../shared/modules/conversion.utils';
|
||||
import { isSwapsDefaultTokenAddress } from '../../../../shared/modules/swaps.utils';
|
||||
import { EVENT } from '../../../../shared/constants/metametrics';
|
||||
import {
|
||||
HARDFORKS,
|
||||
@ -60,6 +61,7 @@ import PendingTransactionTracker from './pending-tx-tracker';
|
||||
import * as txUtils from './lib/util';
|
||||
|
||||
const MAX_MEMSTORE_TX_LIST_SIZE = 100; // Number of transactions (by unique nonces) to keep in memory
|
||||
const UPDATE_POST_TX_BALANCE_TIMEOUT = 5000;
|
||||
|
||||
const SWAP_TRANSACTION_TYPES = [
|
||||
TRANSACTION_TYPES.SWAP,
|
||||
@ -1465,6 +1467,39 @@ export default class TransactionController extends EventEmitter {
|
||||
this._trackTransactionMetricsEvent(txMeta, TRANSACTION_EVENTS.SUBMITTED);
|
||||
}
|
||||
|
||||
async updatePostTxBalance({ txMeta, txId, numberOfAttempts = 6 }) {
|
||||
const postTxBalance = await this.query.getBalance(txMeta.txParams.from);
|
||||
const latestTxMeta = this.txStateManager.getTransaction(txId);
|
||||
const approvalTxMeta = latestTxMeta.approvalTxId
|
||||
? this.txStateManager.getTransaction(latestTxMeta.approvalTxId)
|
||||
: null;
|
||||
latestTxMeta.postTxBalance = postTxBalance.toString(16);
|
||||
const isDefaultTokenAddress = isSwapsDefaultTokenAddress(
|
||||
txMeta.destinationTokenAddress,
|
||||
txMeta.chainId,
|
||||
);
|
||||
if (
|
||||
isDefaultTokenAddress &&
|
||||
txMeta.preTxBalance === latestTxMeta.postTxBalance &&
|
||||
numberOfAttempts > 0
|
||||
) {
|
||||
setTimeout(() => {
|
||||
// If postTxBalance is the same as preTxBalance, try it again.
|
||||
this.updatePostTxBalance({
|
||||
txMeta,
|
||||
txId,
|
||||
numberOfAttempts: numberOfAttempts - 1,
|
||||
});
|
||||
}, UPDATE_POST_TX_BALANCE_TIMEOUT);
|
||||
} else {
|
||||
this.txStateManager.updateTransaction(
|
||||
latestTxMeta,
|
||||
'transactions#confirmTransaction - add postTxBalance',
|
||||
);
|
||||
this._trackSwapsMetrics(latestTxMeta, approvalTxMeta);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status of the transaction to confirmed and sets the status of nonce duplicates as
|
||||
* dropped if the txParams have data it will fetch the txReceipt
|
||||
@ -1528,21 +1563,10 @@ export default class TransactionController extends EventEmitter {
|
||||
);
|
||||
|
||||
if (txMeta.type === TRANSACTION_TYPES.SWAP) {
|
||||
const postTxBalance = await this.query.getBalance(txMeta.txParams.from);
|
||||
const latestTxMeta = this.txStateManager.getTransaction(txId);
|
||||
|
||||
const approvalTxMeta = latestTxMeta.approvalTxId
|
||||
? this.txStateManager.getTransaction(latestTxMeta.approvalTxId)
|
||||
: null;
|
||||
|
||||
latestTxMeta.postTxBalance = postTxBalance.toString(16);
|
||||
|
||||
this.txStateManager.updateTransaction(
|
||||
latestTxMeta,
|
||||
'transactions#confirmTransaction - add postTxBalance',
|
||||
);
|
||||
|
||||
this._trackSwapsMetrics(latestTxMeta, approvalTxMeta);
|
||||
await this.updatePostTxBalance({
|
||||
txMeta,
|
||||
txId,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
log.error(err);
|
||||
@ -1600,21 +1624,10 @@ export default class TransactionController extends EventEmitter {
|
||||
);
|
||||
|
||||
if (txMeta.type === TRANSACTION_TYPES.SWAP) {
|
||||
const postTxBalance = await this.query.getBalance(txMeta.txParams.from);
|
||||
const latestTxMeta = this.txStateManager.getTransaction(txId);
|
||||
|
||||
const approvalTxMeta = latestTxMeta.approvalTxId
|
||||
? this.txStateManager.getTransaction(latestTxMeta.approvalTxId)
|
||||
: null;
|
||||
|
||||
latestTxMeta.postTxBalance = postTxBalance.toString(16);
|
||||
|
||||
this.txStateManager.updateTransaction(
|
||||
latestTxMeta,
|
||||
'transactions#confirmTransaction - add postTxBalance',
|
||||
);
|
||||
|
||||
this._trackSwapsMetrics(latestTxMeta, approvalTxMeta);
|
||||
await this.updatePostTxBalance({
|
||||
txMeta,
|
||||
txId,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
log.error(err);
|
||||
|
@ -758,6 +758,12 @@ export function getSwapsTokensReceivedFromTxMeta(
|
||||
return null;
|
||||
}
|
||||
|
||||
if (txMeta.swapMetaData && txMeta.preTxBalance === txMeta.postTxBalance) {
|
||||
// If preTxBalance and postTxBalance are equal, postTxBalance hasn't been updated on time
|
||||
// because of the RPC provider delay, so we return an estimated receiving amount instead.
|
||||
return txMeta.swapMetaData.token_to_amount;
|
||||
}
|
||||
|
||||
let approvalTxGasCost = '0x0';
|
||||
if (approvalTxMeta && approvalTxMeta.txReceipt) {
|
||||
approvalTxGasCost = calcGasTotal(
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
RINKEBY_CHAIN_ID,
|
||||
KOVAN_CHAIN_ID,
|
||||
AVALANCHE_CHAIN_ID,
|
||||
ETH_SYMBOL,
|
||||
} from '../../../shared/constants/network';
|
||||
import {
|
||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP,
|
||||
@ -39,6 +40,7 @@ import {
|
||||
countDecimals,
|
||||
shouldEnableDirectWrapping,
|
||||
showRemainingTimeInMinAndSec,
|
||||
getSwapsTokensReceivedFromTxMeta,
|
||||
} from './swaps.util';
|
||||
|
||||
jest.mock('../../helpers/utils/storage-helpers.js', () => ({
|
||||
@ -567,4 +569,106 @@ describe('Swaps Util', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSwapsTokensReceivedFromTxMeta', () => {
|
||||
const createProps = () => {
|
||||
return {
|
||||
tokenSymbol: ETH_SYMBOL,
|
||||
txMeta: {
|
||||
swapMetaData: {
|
||||
token_to_amount: 5,
|
||||
},
|
||||
txReceipt: {
|
||||
status: '0x0',
|
||||
},
|
||||
preTxBalance: '8b11',
|
||||
postTxBalance: '8b11',
|
||||
},
|
||||
tokenAddress: '0x881d40237659c251811cec9c364ef91234567890',
|
||||
accountAddress: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f',
|
||||
tokenDecimals: 6,
|
||||
approvalTxMeta: null,
|
||||
chainId: MAINNET_CHAIN_ID,
|
||||
};
|
||||
};
|
||||
|
||||
it('returns an estimated amount if preTxBalance and postTxBalance are the same for ETH', () => {
|
||||
const props = createProps();
|
||||
expect(
|
||||
getSwapsTokensReceivedFromTxMeta(
|
||||
props.tokenSymbol,
|
||||
props.txMeta,
|
||||
props.tokenAddress,
|
||||
props.accountAddress,
|
||||
props.tokenDecimals,
|
||||
props.approvalTxMeta,
|
||||
props.chainId,
|
||||
),
|
||||
).toBe(props.txMeta.swapMetaData.token_to_amount);
|
||||
});
|
||||
|
||||
it('returns null if there is no txMeta', () => {
|
||||
const props = createProps();
|
||||
props.txMeta = undefined;
|
||||
expect(
|
||||
getSwapsTokensReceivedFromTxMeta(
|
||||
props.tokenSymbol,
|
||||
props.txMeta,
|
||||
props.tokenAddress,
|
||||
props.accountAddress,
|
||||
props.tokenDecimals,
|
||||
props.approvalTxMeta,
|
||||
props.chainId,
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if there is no txMeta.txReceipt', () => {
|
||||
const props = createProps();
|
||||
props.txMeta.txReceipt = undefined;
|
||||
expect(
|
||||
getSwapsTokensReceivedFromTxMeta(
|
||||
props.tokenSymbol,
|
||||
props.txMeta,
|
||||
props.tokenAddress,
|
||||
props.accountAddress,
|
||||
props.tokenDecimals,
|
||||
props.approvalTxMeta,
|
||||
props.chainId,
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if there is no txMeta.postTxBalance', () => {
|
||||
const props = createProps();
|
||||
props.txMeta.postTxBalance = undefined;
|
||||
expect(
|
||||
getSwapsTokensReceivedFromTxMeta(
|
||||
props.tokenSymbol,
|
||||
props.txMeta,
|
||||
props.tokenAddress,
|
||||
props.accountAddress,
|
||||
props.tokenDecimals,
|
||||
props.approvalTxMeta,
|
||||
props.chainId,
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if there is no txMeta.preTxBalance', () => {
|
||||
const props = createProps();
|
||||
props.txMeta.preTxBalance = undefined;
|
||||
expect(
|
||||
getSwapsTokensReceivedFromTxMeta(
|
||||
props.tokenSymbol,
|
||||
props.txMeta,
|
||||
props.tokenAddress,
|
||||
props.accountAddress,
|
||||
props.tokenDecimals,
|
||||
props.approvalTxMeta,
|
||||
props.chainId,
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user