mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-28 23:06:37 +01:00
Add support for swaps via a direct contract for wrapping and unwrapping (#11845)
* Update contract address validations in swaps for different networks * Add support for direct contract swaps for wrapping and unwrapping * Add WETH_RINKEBY_CONTRACT_ADDRESS
This commit is contained in:
parent
a35f22fcdf
commit
6f0d6b1693
@ -2131,6 +2131,9 @@
|
|||||||
"swapDecentralizedExchange": {
|
"swapDecentralizedExchange": {
|
||||||
"message": "Decentralized exchange"
|
"message": "Decentralized exchange"
|
||||||
},
|
},
|
||||||
|
"swapDirectContract": {
|
||||||
|
"message": "Direct contract"
|
||||||
|
},
|
||||||
"swapEditLimit": {
|
"swapEditLimit": {
|
||||||
"message": "Edit limit"
|
"message": "Edit limit"
|
||||||
},
|
},
|
||||||
|
@ -75,8 +75,14 @@ const BSC_CONTRACT_ADDRESS = '0x1a1ec25dc08e98e5e93f1104b5e5cdd298707d31';
|
|||||||
// It's the same as we use for BSC.
|
// It's the same as we use for BSC.
|
||||||
const POLYGON_CONTRACT_ADDRESS = '0x1a1ec25dc08e98e5e93f1104b5e5cdd298707d31';
|
const POLYGON_CONTRACT_ADDRESS = '0x1a1ec25dc08e98e5e93f1104b5e5cdd298707d31';
|
||||||
|
|
||||||
export const ETH_WETH_CONTRACT_ADDRESS =
|
export const WETH_CONTRACT_ADDRESS =
|
||||||
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
|
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
|
||||||
|
export const WETH_RINKEBY_CONTRACT_ADDRESS =
|
||||||
|
'0xc778417e063141139fce010982780140aa0cd5ab';
|
||||||
|
export const WBNB_CONTRACT_ADDRESS =
|
||||||
|
'0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c';
|
||||||
|
export const WMATIC_CONTRACT_ADDRESS =
|
||||||
|
'0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270';
|
||||||
|
|
||||||
const METASWAP_ETH_API_HOST = 'https://api.metaswap.codefi.network';
|
const METASWAP_ETH_API_HOST = 'https://api.metaswap.codefi.network';
|
||||||
|
|
||||||
@ -121,6 +127,37 @@ export const SWAPS_CHAINID_CONTRACT_ADDRESS_MAP = {
|
|||||||
[RINKEBY_CHAIN_ID]: TESTNET_CONTRACT_ADDRESS,
|
[RINKEBY_CHAIN_ID]: TESTNET_CONTRACT_ADDRESS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const SWAPS_WRAPPED_TOKENS_ADDRESSES = {
|
||||||
|
[MAINNET_CHAIN_ID]: WETH_CONTRACT_ADDRESS,
|
||||||
|
[SWAPS_TESTNET_CHAIN_ID]: WETH_CONTRACT_ADDRESS,
|
||||||
|
[BSC_CHAIN_ID]: WBNB_CONTRACT_ADDRESS,
|
||||||
|
[POLYGON_CHAIN_ID]: WMATIC_CONTRACT_ADDRESS,
|
||||||
|
[RINKEBY_CHAIN_ID]: WETH_RINKEBY_CONTRACT_ADDRESS,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ALLOWED_CONTRACT_ADDRESSES = {
|
||||||
|
[MAINNET_CHAIN_ID]: [
|
||||||
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[MAINNET_CHAIN_ID],
|
||||||
|
SWAPS_WRAPPED_TOKENS_ADDRESSES[MAINNET_CHAIN_ID],
|
||||||
|
],
|
||||||
|
[SWAPS_TESTNET_CHAIN_ID]: [
|
||||||
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[SWAPS_TESTNET_CHAIN_ID],
|
||||||
|
SWAPS_WRAPPED_TOKENS_ADDRESSES[SWAPS_TESTNET_CHAIN_ID],
|
||||||
|
],
|
||||||
|
[RINKEBY_CHAIN_ID]: [
|
||||||
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[RINKEBY_CHAIN_ID],
|
||||||
|
SWAPS_WRAPPED_TOKENS_ADDRESSES[RINKEBY_CHAIN_ID],
|
||||||
|
],
|
||||||
|
[BSC_CHAIN_ID]: [
|
||||||
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[BSC_CHAIN_ID],
|
||||||
|
SWAPS_WRAPPED_TOKENS_ADDRESSES[BSC_CHAIN_ID],
|
||||||
|
],
|
||||||
|
[POLYGON_CHAIN_ID]: [
|
||||||
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[POLYGON_CHAIN_ID],
|
||||||
|
SWAPS_WRAPPED_TOKENS_ADDRESSES[POLYGON_CHAIN_ID],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = {
|
export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = {
|
||||||
[MAINNET_CHAIN_ID]: ETH_SWAPS_TOKEN_OBJECT,
|
[MAINNET_CHAIN_ID]: ETH_SWAPS_TOKEN_OBJECT,
|
||||||
[SWAPS_TESTNET_CHAIN_ID]: TEST_ETH_SWAPS_TOKEN_OBJECT,
|
[SWAPS_TESTNET_CHAIN_ID]: TEST_ETH_SWAPS_TOKEN_OBJECT,
|
||||||
|
@ -779,7 +779,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
|||||||
sensitiveProperties: swapMetaData,
|
sensitiveProperties: swapMetaData,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isContractAddressValid(usedTradeTxParams.to, swapMetaData, chainId)) {
|
if (!isContractAddressValid(usedTradeTxParams.to, chainId)) {
|
||||||
captureMessage('Invalid contract address', {
|
captureMessage('Invalid contract address', {
|
||||||
extra: {
|
extra: {
|
||||||
token_from: swapMetaData.token_from,
|
token_from: swapMetaData.token_from,
|
||||||
|
@ -59,7 +59,11 @@ import {
|
|||||||
} from '../../../../shared/constants/swaps';
|
} from '../../../../shared/constants/swaps';
|
||||||
|
|
||||||
import { resetSwapsPostFetchState, removeToken } from '../../../store/actions';
|
import { resetSwapsPostFetchState, removeToken } from '../../../store/actions';
|
||||||
import { fetchTokenPrice, fetchTokenBalance } from '../swaps.util';
|
import {
|
||||||
|
fetchTokenPrice,
|
||||||
|
fetchTokenBalance,
|
||||||
|
shouldEnableDirectWrapping,
|
||||||
|
} from '../swaps.util';
|
||||||
import SwapsFooter from '../swaps-footer';
|
import SwapsFooter from '../swaps-footer';
|
||||||
|
|
||||||
const fuseSearchKeys = [
|
const fuseSearchKeys = [
|
||||||
@ -375,6 +379,12 @@ export default function BuildQuote({
|
|||||||
fromTokenSymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId]?.symbol || '',
|
fromTokenSymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId]?.symbol || '',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const isDirectWrappingEnabled = shouldEnableDirectWrapping(
|
||||||
|
chainId,
|
||||||
|
fromTokenAddress,
|
||||||
|
selectedToToken.address,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="build-quote">
|
<div className="build-quote">
|
||||||
<div className="build-quote__content">
|
<div className="build-quote__content">
|
||||||
@ -552,15 +562,17 @@ export default function BuildQuote({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div className="build-quote__slippage-buttons-container">
|
{!isDirectWrappingEnabled && (
|
||||||
<SlippageButtons
|
<div className="build-quote__slippage-buttons-container">
|
||||||
onSelect={(newSlippage) => {
|
<SlippageButtons
|
||||||
setMaxSlippage(newSlippage);
|
onSelect={(newSlippage) => {
|
||||||
}}
|
setMaxSlippage(newSlippage);
|
||||||
maxAllowedSlippage={MAX_ALLOWED_SLIPPAGE}
|
}}
|
||||||
currentSlippage={maxSlippage}
|
maxAllowedSlippage={MAX_ALLOWED_SLIPPAGE}
|
||||||
/>
|
currentSlippage={maxSlippage}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<SwapsFooter
|
<SwapsFooter
|
||||||
onSubmit={() => {
|
onSubmit={() => {
|
||||||
|
@ -82,17 +82,19 @@ export default function FeeCard({
|
|||||||
{bestQuoteText && (
|
{bestQuoteText && (
|
||||||
<p className="fee-card__savings-text">{bestQuoteText}</p>
|
<p className="fee-card__savings-text">{bestQuoteText}</p>
|
||||||
)}
|
)}
|
||||||
<div
|
{numberOfQuotes > 1 && (
|
||||||
className="fee-card__quote-link-container"
|
<div
|
||||||
onClick={onQuotesClick}
|
className="fee-card__quote-link-container"
|
||||||
>
|
onClick={onQuotesClick}
|
||||||
<p className="fee-card__quote-link-text">
|
>
|
||||||
{t('swapNQuotes', [numberOfQuotes])}
|
<p className="fee-card__quote-link-text">
|
||||||
</p>
|
{t('swapNQuotes', [numberOfQuotes])}
|
||||||
<div className="fee-card__caret-right">
|
</p>
|
||||||
<i className="fa fa-angle-up" />
|
<div className="fee-card__caret-right">
|
||||||
|
<i className="fa fa-angle-up" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="fee-card__main">
|
<div className="fee-card__main">
|
||||||
|
@ -4,8 +4,8 @@ import abi from 'human-standard-token-abi';
|
|||||||
import {
|
import {
|
||||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||||
METASWAP_CHAINID_API_HOST_MAP,
|
METASWAP_CHAINID_API_HOST_MAP,
|
||||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP,
|
ALLOWED_CONTRACT_ADDRESSES,
|
||||||
ETH_WETH_CONTRACT_ADDRESS,
|
SWAPS_WRAPPED_TOKENS_ADDRESSES,
|
||||||
ETHEREUM,
|
ETHEREUM,
|
||||||
POLYGON,
|
POLYGON,
|
||||||
BSC,
|
BSC,
|
||||||
@ -21,8 +21,6 @@ import {
|
|||||||
isSwapsDefaultTokenSymbol,
|
isSwapsDefaultTokenSymbol,
|
||||||
} from '../../../shared/modules/swaps.utils';
|
} from '../../../shared/modules/swaps.utils';
|
||||||
import {
|
import {
|
||||||
ETH_SYMBOL,
|
|
||||||
WETH_SYMBOL,
|
|
||||||
MAINNET_CHAIN_ID,
|
MAINNET_CHAIN_ID,
|
||||||
BSC_CHAIN_ID,
|
BSC_CHAIN_ID,
|
||||||
POLYGON_CHAIN_ID,
|
POLYGON_CHAIN_ID,
|
||||||
@ -267,6 +265,19 @@ function validateData(validators, object, urlUsed) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const shouldEnableDirectWrapping = (
|
||||||
|
chainId,
|
||||||
|
sourceToken,
|
||||||
|
destinationToken,
|
||||||
|
) => {
|
||||||
|
const wrappedToken = SWAPS_WRAPPED_TOKENS_ADDRESSES[chainId];
|
||||||
|
const nativeToken = SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId]?.address;
|
||||||
|
return (
|
||||||
|
(sourceToken === wrappedToken && destinationToken === nativeToken) ||
|
||||||
|
(sourceToken === nativeToken && destinationToken === wrappedToken)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export async function fetchTradesInfo(
|
export async function fetchTradesInfo(
|
||||||
{
|
{
|
||||||
slippage,
|
slippage,
|
||||||
@ -291,6 +302,9 @@ export async function fetchTradesInfo(
|
|||||||
if (exchangeList) {
|
if (exchangeList) {
|
||||||
urlParams.exchangeList = exchangeList;
|
urlParams.exchangeList = exchangeList;
|
||||||
}
|
}
|
||||||
|
if (shouldEnableDirectWrapping(chainId, sourceToken, destinationToken)) {
|
||||||
|
urlParams.enableDirectWrapping = true;
|
||||||
|
}
|
||||||
|
|
||||||
const queryString = new URLSearchParams(urlParams).toString();
|
const queryString = new URLSearchParams(urlParams).toString();
|
||||||
const tradeURL = `${getBaseApi(
|
const tradeURL = `${getBaseApi(
|
||||||
@ -628,6 +642,8 @@ export function quotesToRenderableData(
|
|||||||
renderedSlippage = 0;
|
renderedSlippage = 0;
|
||||||
} else if (aggType === 'DEX') {
|
} else if (aggType === 'DEX') {
|
||||||
liquiditySourceKey = 'swapDecentralizedExchange';
|
liquiditySourceKey = 'swapDecentralizedExchange';
|
||||||
|
} else if (aggType === 'CONTRACT') {
|
||||||
|
liquiditySourceKey = 'swapDirectContract';
|
||||||
} else {
|
} else {
|
||||||
liquiditySourceKey = 'swapUnknown';
|
liquiditySourceKey = 'swapUnknown';
|
||||||
}
|
}
|
||||||
@ -769,29 +785,16 @@ export function formatSwapsValueForDisplay(destinationAmount) {
|
|||||||
*/
|
*/
|
||||||
export const isContractAddressValid = (
|
export const isContractAddressValid = (
|
||||||
contractAddress,
|
contractAddress,
|
||||||
swapMetaData,
|
|
||||||
chainId = MAINNET_CHAIN_ID,
|
chainId = MAINNET_CHAIN_ID,
|
||||||
) => {
|
) => {
|
||||||
const contractAddressForChainId = SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[chainId];
|
if (!contractAddress || !ALLOWED_CONTRACT_ADDRESSES[chainId]) {
|
||||||
if (!contractAddress || !contractAddressForChainId) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (
|
return ALLOWED_CONTRACT_ADDRESSES[chainId].some(
|
||||||
(swapMetaData.token_from === ETH_SYMBOL &&
|
|
||||||
swapMetaData.token_to === WETH_SYMBOL) ||
|
|
||||||
(swapMetaData.token_from === WETH_SYMBOL &&
|
|
||||||
swapMetaData.token_to === ETH_SYMBOL)
|
|
||||||
) {
|
|
||||||
// Sometimes we get a contract address with a few upper-case chars and since addresses are
|
// Sometimes we get a contract address with a few upper-case chars and since addresses are
|
||||||
// case-insensitive, we compare uppercase versions for validity.
|
// case-insensitive, we compare lowercase versions for validity.
|
||||||
return (
|
(allowedContractAddress) =>
|
||||||
contractAddress.toUpperCase() ===
|
contractAddress.toLowerCase() === allowedContractAddress.toLowerCase(),
|
||||||
ETH_WETH_CONTRACT_ADDRESS.toUpperCase() ||
|
|
||||||
contractAddressForChainId.toUpperCase() === contractAddress.toUpperCase()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
contractAddressForChainId.toUpperCase() === contractAddress.toUpperCase()
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import nock from 'nock';
|
import nock from 'nock';
|
||||||
import { MOCKS } from '../../../test/jest';
|
import { MOCKS } from '../../../test/jest';
|
||||||
import {
|
import {
|
||||||
ETH_SYMBOL,
|
|
||||||
WETH_SYMBOL,
|
|
||||||
MAINNET_CHAIN_ID,
|
MAINNET_CHAIN_ID,
|
||||||
BSC_CHAIN_ID,
|
BSC_CHAIN_ID,
|
||||||
POLYGON_CHAIN_ID,
|
POLYGON_CHAIN_ID,
|
||||||
@ -12,7 +10,10 @@ import {
|
|||||||
} from '../../../shared/constants/network';
|
} from '../../../shared/constants/network';
|
||||||
import {
|
import {
|
||||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP,
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP,
|
||||||
ETH_WETH_CONTRACT_ADDRESS,
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||||
|
WETH_CONTRACT_ADDRESS,
|
||||||
|
WBNB_CONTRACT_ADDRESS,
|
||||||
|
WMATIC_CONTRACT_ADDRESS,
|
||||||
ETHEREUM,
|
ETHEREUM,
|
||||||
POLYGON,
|
POLYGON,
|
||||||
BSC,
|
BSC,
|
||||||
@ -34,6 +35,7 @@ import {
|
|||||||
getNetworkNameByChainId,
|
getNetworkNameByChainId,
|
||||||
getSwapsLivenessForNetwork,
|
getSwapsLivenessForNetwork,
|
||||||
countDecimals,
|
countDecimals,
|
||||||
|
shouldEnableDirectWrapping,
|
||||||
} from './swaps.util';
|
} from './swaps.util';
|
||||||
|
|
||||||
jest.mock('../../helpers/utils/storage-helpers.js', () => ({
|
jest.mock('../../helpers/utils/storage-helpers.js', () => ({
|
||||||
@ -188,197 +190,113 @@ describe('Swaps Util', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('isContractAddressValid', () => {
|
describe('isContractAddressValid', () => {
|
||||||
let swapMetaData;
|
|
||||||
let usedTradeTxParams;
|
let usedTradeTxParams;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
swapMetaData = {
|
|
||||||
available_quotes: undefined,
|
|
||||||
average_savings: undefined,
|
|
||||||
best_quote_source: 'paraswap',
|
|
||||||
custom_slippage: true,
|
|
||||||
estimated_gas: '134629',
|
|
||||||
fee_savings: undefined,
|
|
||||||
gas_fees: '47.411896',
|
|
||||||
median_metamask_fee: undefined,
|
|
||||||
other_quote_selected: false,
|
|
||||||
other_quote_selected_source: '',
|
|
||||||
performance_savings: undefined,
|
|
||||||
slippage: 5,
|
|
||||||
suggested_gas_price: '164',
|
|
||||||
token_from: ETH_SYMBOL,
|
|
||||||
token_from_amount: '1',
|
|
||||||
token_to: WETH_SYMBOL,
|
|
||||||
token_to_amount: '1.0000000',
|
|
||||||
used_gas_price: '164',
|
|
||||||
};
|
|
||||||
usedTradeTxParams = {
|
usedTradeTxParams = {
|
||||||
data: 'testData',
|
data: 'testData',
|
||||||
from: '0xe53a5bc256898bfa5673b20aceeb2b2152075d17',
|
from: '0xe53a5bc256898bfa5673b20aceeb2b2152075d17',
|
||||||
gas: '2427c',
|
gas: '2427c',
|
||||||
gasPrice: '27592f5a00',
|
gasPrice: '27592f5a00',
|
||||||
to: ETH_WETH_CONTRACT_ADDRESS,
|
to: WETH_CONTRACT_ADDRESS,
|
||||||
value: '0xde0b6b3a7640000',
|
value: '0xde0b6b3a7640000',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if "token_from" is ETH, "token_to" is WETH and "to" is ETH_WETH contract address', () => {
|
it('returns true if "to" is WETH contract address', () => {
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, MAINNET_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if "token_from" is WETH, "token_to" is ETH and "to" is ETH_WETH contract address', () => {
|
it('returns true if "to" is WETH contract address with some uppercase chars', () => {
|
||||||
swapMetaData.token_from = WETH_SYMBOL;
|
|
||||||
swapMetaData.token_to = ETH_SYMBOL;
|
|
||||||
expect(
|
|
||||||
isContractAddressValid(
|
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns true if "token_from" is ETH, "token_to" is WETH and "to" is ETH_WETH contract address with some uppercase chars', () => {
|
|
||||||
usedTradeTxParams.to = '0xc02AAA39B223fe8d0a0e5c4f27ead9083c756cc2';
|
usedTradeTxParams.to = '0xc02AAA39B223fe8d0a0e5c4f27ead9083c756cc2';
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, MAINNET_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if "token_from" is ETH, "token_to" is WETH and "to" is mainnet contract address', () => {
|
it('returns true if "to" is ETH mainnet contract address on ETH mainnet', () => {
|
||||||
usedTradeTxParams.to =
|
usedTradeTxParams.to =
|
||||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[MAINNET_CHAIN_ID];
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[MAINNET_CHAIN_ID];
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, MAINNET_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if "token_from" is WETH, "token_to" is ETH and "to" is mainnet contract address', () => {
|
it('returns true if "to" is WBNB contract address on BSC mainnet', () => {
|
||||||
swapMetaData.token_from = WETH_SYMBOL;
|
usedTradeTxParams.to = WBNB_CONTRACT_ADDRESS;
|
||||||
swapMetaData.token_to = ETH_SYMBOL;
|
expect(isContractAddressValid(usedTradeTxParams.to, BSC_CHAIN_ID)).toBe(
|
||||||
usedTradeTxParams.to =
|
true,
|
||||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[MAINNET_CHAIN_ID];
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if "to" is WMATIC contract address on Polygon mainnet', () => {
|
||||||
|
usedTradeTxParams.to = WMATIC_CONTRACT_ADDRESS;
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, POLYGON_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if "token_from" is ETH, "token_to" is WETH and "to" is BSC contract address', () => {
|
it('returns false if "to" is BSC contract address on ETH mainnet', () => {
|
||||||
usedTradeTxParams.to = SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[BSC_CHAIN_ID];
|
usedTradeTxParams.to = SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[BSC_CHAIN_ID];
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, MAINNET_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns false if "token_from" is WETH, "token_to" is ETH and "to" is BSC contract address', () => {
|
|
||||||
swapMetaData.token_from = WETH_SYMBOL;
|
|
||||||
swapMetaData.token_to = ETH_SYMBOL;
|
|
||||||
usedTradeTxParams.to = SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[BSC_CHAIN_ID];
|
|
||||||
expect(
|
|
||||||
isContractAddressValid(
|
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if contractAddress is null', () => {
|
it('returns false if contractAddress is null', () => {
|
||||||
expect(
|
expect(isContractAddressValid(null, LOCALHOST_CHAIN_ID)).toBe(false);
|
||||||
isContractAddressValid(null, swapMetaData, LOCALHOST_CHAIN_ID),
|
|
||||||
).toBe(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if chainId is incorrect', () => {
|
it('returns false if chainId is incorrect', () => {
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, 'incorrectChainId'),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
'incorrectChainId',
|
|
||||||
),
|
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if "token_from" is BAT and "to" is mainnet contract address', () => {
|
it('returns true if "to" is BSC contract address on BSC network', () => {
|
||||||
swapMetaData.token_from = 'BAT';
|
|
||||||
usedTradeTxParams.to =
|
|
||||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[MAINNET_CHAIN_ID];
|
|
||||||
expect(
|
|
||||||
isContractAddressValid(
|
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns true if "token_to" is BAT and "to" is BSC contract address', () => {
|
|
||||||
swapMetaData.token_to = 'BAT';
|
|
||||||
usedTradeTxParams.to = SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[BSC_CHAIN_ID];
|
usedTradeTxParams.to = SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[BSC_CHAIN_ID];
|
||||||
|
expect(isContractAddressValid(usedTradeTxParams.to, BSC_CHAIN_ID)).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if "to" is Polygon contract address on Polygon network', () => {
|
||||||
|
usedTradeTxParams.to =
|
||||||
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[POLYGON_CHAIN_ID];
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, POLYGON_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
BSC_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if "token_to" is BAT and "to" is testnet contract address', () => {
|
it('returns true if "to" is Rinkeby contract address on Rinkeby network', () => {
|
||||||
swapMetaData.token_to = 'BAT';
|
usedTradeTxParams.to =
|
||||||
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[RINKEBY_CHAIN_ID];
|
||||||
|
expect(
|
||||||
|
isContractAddressValid(usedTradeTxParams.to, RINKEBY_CHAIN_ID),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if "to" is testnet contract address', () => {
|
||||||
usedTradeTxParams.to =
|
usedTradeTxParams.to =
|
||||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[LOCALHOST_CHAIN_ID];
|
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[LOCALHOST_CHAIN_ID];
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, LOCALHOST_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
LOCALHOST_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if "token_to" is BAT and "to" is testnet contract address with some uppercase chars', () => {
|
it('returns true if "to" is testnet contract address with some uppercase chars', () => {
|
||||||
swapMetaData.token_to = 'BAT';
|
|
||||||
usedTradeTxParams.to = '0x881D40237659C251811CEC9c364ef91dC08D300C';
|
usedTradeTxParams.to = '0x881D40237659C251811CEC9c364ef91dC08D300C';
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, LOCALHOST_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
LOCALHOST_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if "token_to" is BAT and "to" has mismatch with current chainId', () => {
|
it('returns false if "to" has mismatch with current chainId', () => {
|
||||||
swapMetaData.token_to = 'BAT';
|
usedTradeTxParams.to = SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[BSC_CHAIN_ID];
|
||||||
expect(
|
expect(
|
||||||
isContractAddressValid(
|
isContractAddressValid(usedTradeTxParams.to, LOCALHOST_CHAIN_ID),
|
||||||
usedTradeTxParams.to,
|
|
||||||
swapMetaData,
|
|
||||||
LOCALHOST_CHAIN_ID,
|
|
||||||
),
|
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -492,4 +410,114 @@ describe('Swaps Util', () => {
|
|||||||
expect(countDecimals(1.123456789)).toBe(9);
|
expect(countDecimals(1.123456789)).toBe(9);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('shouldEnableDirectWrapping', () => {
|
||||||
|
const randomTokenAddress = '0x881d40237659c251811cec9c364ef91234567890';
|
||||||
|
|
||||||
|
it('returns true if swapping from ETH to WETH', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
MAINNET_CHAIN_ID,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[MAINNET_CHAIN_ID]?.address,
|
||||||
|
WETH_CONTRACT_ADDRESS,
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if swapping from WETH to ETH', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
MAINNET_CHAIN_ID,
|
||||||
|
WETH_CONTRACT_ADDRESS,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[MAINNET_CHAIN_ID]?.address,
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if swapping from ETH to a non-WETH token', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
MAINNET_CHAIN_ID,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[MAINNET_CHAIN_ID]?.address,
|
||||||
|
randomTokenAddress,
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if swapping from BNB to WBNB', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
BSC_CHAIN_ID,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[BSC_CHAIN_ID]?.address,
|
||||||
|
WBNB_CONTRACT_ADDRESS,
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if swapping from WBNB to BNB', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
BSC_CHAIN_ID,
|
||||||
|
WBNB_CONTRACT_ADDRESS,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[BSC_CHAIN_ID]?.address,
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if swapping from BNB to a non-WBNB token', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
BSC_CHAIN_ID,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[BSC_CHAIN_ID]?.address,
|
||||||
|
randomTokenAddress,
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if swapping from MATIC to WMATIC', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
POLYGON_CHAIN_ID,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[POLYGON_CHAIN_ID]?.address,
|
||||||
|
WMATIC_CONTRACT_ADDRESS,
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if swapping from WMATIC to MATIC', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
POLYGON_CHAIN_ID,
|
||||||
|
WMATIC_CONTRACT_ADDRESS,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[POLYGON_CHAIN_ID]?.address,
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if swapping from MATIC to a non-WMATIC token', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
POLYGON_CHAIN_ID,
|
||||||
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[POLYGON_CHAIN_ID]?.address,
|
||||||
|
randomTokenAddress,
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if a source token is undefined', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(
|
||||||
|
MAINNET_CHAIN_ID,
|
||||||
|
undefined,
|
||||||
|
WETH_CONTRACT_ADDRESS,
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if a destination token is undefined', () => {
|
||||||
|
expect(
|
||||||
|
shouldEnableDirectWrapping(MAINNET_CHAIN_ID, WETH_CONTRACT_ADDRESS),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user