|
| 1 | +import { Suite } from 'mocha'; |
| 2 | +import { MockttpServer } from 'mockttp'; |
| 3 | +import { |
| 4 | + logInWithBalanceValidation, |
| 5 | + openActionMenuAndStartSendFlow, |
| 6 | + withFixtures, |
| 7 | +} from '../../helpers'; |
| 8 | +import FixtureBuilder from '../../fixture-builder'; |
| 9 | +import HeaderNavbar from '../../page-objects/pages/header-navbar'; |
| 10 | +import SettingsPage from '../../page-objects/pages/settings/settings-page'; |
| 11 | +import AdvancedSettings from '../../page-objects/pages/settings/advanced-settings'; |
| 12 | +import HomePage from '../../page-objects/pages/home/homepage'; |
| 13 | +import { DEFAULT_FIXTURE_ACCOUNT } from '../../constants'; |
| 14 | +import { NATIVE_TOKEN_SYMBOL, SwapSendPage } from './swap-send-test-utils'; |
| 15 | + |
| 16 | +async function mockSwapQuotes(mockServer: MockttpServer) { |
| 17 | + return [ |
| 18 | + await mockServer |
| 19 | + .forGet('https://swap.api.cx.metamask.io/token/1') |
| 20 | + .thenCallback(() => ({ |
| 21 | + statusCode: 200, |
| 22 | + json: { |
| 23 | + symbol: 'WETH', |
| 24 | + type: 'erc20', |
| 25 | + aggregators: [ |
| 26 | + 'metamask', |
| 27 | + 'aave', |
| 28 | + 'coinGecko', |
| 29 | + 'oneInch', |
| 30 | + 'pmm', |
| 31 | + 'zerion', |
| 32 | + 'lifi', |
| 33 | + 'socket', |
| 34 | + 'squid', |
| 35 | + 'sonarwatch', |
| 36 | + 'uniswapLabs', |
| 37 | + 'coinmarketcap', |
| 38 | + 'rango', |
| 39 | + ], |
| 40 | + occurrences: 13, |
| 41 | + iconUrl: |
| 42 | + 'https://raw.githubusercontent.com/MetaMask/contract-metadata/master/images/weth.svg', |
| 43 | + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', |
| 44 | + name: 'Wrapped Ether', |
| 45 | + decimals: 18, |
| 46 | + }, |
| 47 | + })), |
| 48 | + await mockServer |
| 49 | + .forPost('https://transaction.api.cx.metamask.io/networks/1/getFees') |
| 50 | + .thenCallback(() => ({ |
| 51 | + statusCode: 200, |
| 52 | + json: { |
| 53 | + blockNumber: 22017409, |
| 54 | + id: 'b6d9c5f3-4fee-4470-be1b-6c574fe61315', |
| 55 | + txs: [ |
| 56 | + { |
| 57 | + cancelFees: [], |
| 58 | + return: '0x', |
| 59 | + status: 1, |
| 60 | + gasUsed: 188186, |
| 61 | + gasLimit: 241302, |
| 62 | + fees: [ |
| 63 | + { |
| 64 | + maxFeePerGas: 6393950816, |
| 65 | + maxPriorityFeePerGas: 1000000004, |
| 66 | + gas: 241302, |
| 67 | + balanceNeeded: 1542873120043734, |
| 68 | + currentBalance: 30009434625664560, |
| 69 | + error: '', |
| 70 | + }, |
| 71 | + ], |
| 72 | + feeEstimate: 821886724082654, |
| 73 | + baseFeePerGas: 3367416938, |
| 74 | + maxFeeEstimate: 1542873119802432, |
| 75 | + }, |
| 76 | + ], |
| 77 | + }, |
| 78 | + })), |
| 79 | + |
| 80 | + await mockServer |
| 81 | + .forGet('https://swap.api.cx.metamask.io/v2/networks/1/quotes') |
| 82 | + .thenCallback(() => ({ |
| 83 | + statusCode: 200, |
| 84 | + json: [ |
| 85 | + { |
| 86 | + aggregator: 'WETH', |
| 87 | + aggregatorType: 'CONTRACT', |
| 88 | + destinationToken: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', |
| 89 | + sourceToken: '0x0000000000000000000000000000000000000000', |
| 90 | + sourceAmount: '10000000000000000000', |
| 91 | + destinationAmount: '10000000000000000000', |
| 92 | + trade: { |
| 93 | + data: '0xd0e30db0', |
| 94 | + from: '0x5CfE73b6021E818B776b421B1c4Db2474086a7e1', |
| 95 | + to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', |
| 96 | + value: '10000000000000000000', |
| 97 | + }, |
| 98 | + sender: '0x5CfE73b6021E818B776b421B1c4Db2474086a7e1', |
| 99 | + recipient: '0x5CfE73b6021E818B776b421B1c4Db2474086a7e1', |
| 100 | + error: null, |
| 101 | + gasParams: { |
| 102 | + maxGas: 500000, |
| 103 | + averageGas: 300000, |
| 104 | + estimatedRefund: 0, |
| 105 | + gasMultiplier: 1, |
| 106 | + }, |
| 107 | + fee: 0, |
| 108 | + approvalNeeded: null, |
| 109 | + priceSlippage: null, |
| 110 | + sourceTokenRate: 1, |
| 111 | + destinationTokenRate: 0.9999285710414016, |
| 112 | + }, |
| 113 | + ], |
| 114 | + })), |
| 115 | + |
| 116 | + await mockServer |
| 117 | + .forGet('https://swap.api.cx.metamask.io/networks/1') |
| 118 | + .thenCallback(() => ({ |
| 119 | + statusCode: 200, |
| 120 | + json: { |
| 121 | + active: true, |
| 122 | + networkId: 1, |
| 123 | + chainId: 1, |
| 124 | + chainName: 'Ethereum Mainnet', |
| 125 | + nativeCurrency: { |
| 126 | + name: 'Ether', |
| 127 | + symbol: 'ETH', |
| 128 | + decimals: 18, |
| 129 | + address: '0x0000000000000000000000000000000000000000', |
| 130 | + }, |
| 131 | + iconUrl: 'https://s3.amazonaws.com/airswap-token-images/ETH.png', |
| 132 | + blockExplorerUrl: 'https://etherscan.io', |
| 133 | + networkType: 'L1', |
| 134 | + aggregators: [ |
| 135 | + 'airswapV3', |
| 136 | + 'airswapV4', |
| 137 | + 'oneInchV4', |
| 138 | + 'oneInchV5', |
| 139 | + 'paraswap', |
| 140 | + 'pmm', |
| 141 | + 'zeroEx', |
| 142 | + 'openOcean', |
| 143 | + 'hashFlow', |
| 144 | + 'wrappedNative', |
| 145 | + 'kyberSwap', |
| 146 | + 'airSwapV4_3', |
| 147 | + 'hashFlowV3', |
| 148 | + ], |
| 149 | + refreshRates: { |
| 150 | + quotes: 30, |
| 151 | + quotesPrefetching: 30, |
| 152 | + stxGetTransactions: 10, |
| 153 | + stxBatchStatus: 1, |
| 154 | + stxStatusDeadline: 160, |
| 155 | + stxMaxFeeMultiplier: 2, |
| 156 | + }, |
| 157 | + parameters: { |
| 158 | + refreshRates: { |
| 159 | + quotes: 30, |
| 160 | + quotesPrefetching: 30, |
| 161 | + stxGetTransactions: 10, |
| 162 | + stxBatchStatus: 1, |
| 163 | + }, |
| 164 | + stxStatusDeadline: 160, |
| 165 | + stxMaxFeeMultiplier: 2, |
| 166 | + }, |
| 167 | + }, |
| 168 | + })), |
| 169 | + ]; |
| 170 | +} |
| 171 | + |
| 172 | +describe('Swap-Send ETH', function () { |
| 173 | + describe('to non-contract address with data that matches swap data signature', function (this: Suite) { |
| 174 | + it('submits a transaction successfully with max amount', async function () { |
| 175 | + await withFixtures( |
| 176 | + { |
| 177 | + fixtures: new FixtureBuilder() |
| 178 | + .withNetworkControllerOnMainnet() |
| 179 | + .withTokensController({ |
| 180 | + allTokens: { |
| 181 | + '0x1': { |
| 182 | + '0x5cfe73b6021e818b776b421b1c4db2474086a7e1': [ |
| 183 | + { |
| 184 | + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', |
| 185 | + symbol: 'WETH', |
| 186 | + decimals: 18, |
| 187 | + isERC721: false, |
| 188 | + aggregators: [], |
| 189 | + }, |
| 190 | + ], |
| 191 | + }, |
| 192 | + }, |
| 193 | + }) |
| 194 | + .build(), |
| 195 | + title: this.test?.fullTitle(), |
| 196 | + testSpecificMock: mockSwapQuotes, |
| 197 | + localNodeOptions: [ |
| 198 | + { |
| 199 | + type: 'anvil', |
| 200 | + options: { |
| 201 | + chainId: 1, |
| 202 | + hardfork: 'london', |
| 203 | + loadState: |
| 204 | + './test/e2e/seeder/network-states/swap-state/withSwapContracts.json', |
| 205 | + }, |
| 206 | + }, |
| 207 | + ], |
| 208 | + }, |
| 209 | + async ({ driver }) => { |
| 210 | + const swapSendPage = new SwapSendPage(driver); |
| 211 | + await logInWithBalanceValidation(driver); |
| 212 | + |
| 213 | + const homePage = new HomePage(driver); |
| 214 | + await homePage.check_pageIsLoaded(); |
| 215 | + await homePage.check_expectedTokenBalanceIsDisplayed('50', 'WETH'); |
| 216 | + await homePage.check_expectedTokenBalanceIsDisplayed('25', 'ETH'); |
| 217 | + |
| 218 | + // disable smart transactions |
| 219 | + const headerNavbar = new HeaderNavbar(driver); |
| 220 | + await headerNavbar.check_pageIsLoaded(); |
| 221 | + await headerNavbar.openSettingsPage(); |
| 222 | + |
| 223 | + const settingsPage = new SettingsPage(driver); |
| 224 | + await settingsPage.check_pageIsLoaded(); |
| 225 | + await settingsPage.clickAdvancedTab(); |
| 226 | + const advancedSettingsPage = new AdvancedSettings(driver); |
| 227 | + await advancedSettingsPage.check_pageIsLoaded(); |
| 228 | + await advancedSettingsPage.toggleSmartTransactions(); |
| 229 | + await settingsPage.closeSettingsPage(); |
| 230 | + |
| 231 | + // START SWAP AND SEND FLOW |
| 232 | + await openActionMenuAndStartSendFlow(driver); |
| 233 | + |
| 234 | + await swapSendPage.fillRecipientAddressInput(DEFAULT_FIXTURE_ACCOUNT); |
| 235 | + await swapSendPage.fillAmountInput('1'); |
| 236 | + |
| 237 | + await swapSendPage.verifyMaxButtonClick( |
| 238 | + ['ETH', 'ETH'], |
| 239 | + ['24.99945808355143', '24.99945808355143'], |
| 240 | + ); |
| 241 | + |
| 242 | + await swapSendPage.fillAmountInput('10'); |
| 243 | + await swapSendPage.verifyAssetSymbolsAndAmounts( |
| 244 | + [NATIVE_TOKEN_SYMBOL, NATIVE_TOKEN_SYMBOL], |
| 245 | + ['10', '10'], |
| 246 | + ); |
| 247 | + |
| 248 | + await swapSendPage.fillAmountInput('10'); |
| 249 | + |
| 250 | + const ETH_WETH_TOKEN_INPUTS = [ |
| 251 | + [NATIVE_TOKEN_SYMBOL, 'WETH'], |
| 252 | + ['10', '10'], |
| 253 | + ]; |
| 254 | + const ETH_WETH_FIAT_INPUTS = [ |
| 255 | + ['USD', 'USD'], |
| 256 | + ['1,700.00', '1,701.09'], |
| 257 | + ]; |
| 258 | + |
| 259 | + await swapSendPage.clickOnAsset('WETH', 'dest'); |
| 260 | + await swapSendPage.verifyAssetSymbolsAndAmounts( |
| 261 | + ETH_WETH_TOKEN_INPUTS[0], |
| 262 | + ETH_WETH_TOKEN_INPUTS[1], |
| 263 | + ); |
| 264 | + |
| 265 | + await swapSendPage.verifySwitchPrimaryCurrency( |
| 266 | + ETH_WETH_TOKEN_INPUTS, |
| 267 | + ETH_WETH_FIAT_INPUTS, |
| 268 | + ); |
| 269 | + |
| 270 | + await swapSendPage.verifyQuoteDisplay( |
| 271 | + '1 ETH = 1 WETH', |
| 272 | + '0.0129028 ETH', |
| 273 | + '≈ $21.93', |
| 274 | + ); |
| 275 | + |
| 276 | + await swapSendPage.submitSwap(); |
| 277 | + await swapSendPage.verifyHistoryEntry( |
| 278 | + 'Send ETH as WETH', |
| 279 | + 'Confirmed', |
| 280 | + '-10 ETH', |
| 281 | + '', |
| 282 | + ); |
| 283 | + |
| 284 | + await homePage.goToTokensTab(); |
| 285 | + await homePage.check_expectedTokenBalanceIsDisplayed('60', 'WETH'); |
| 286 | + // https://github.com/MetaMask/metamask-extension/issues/31427 |
| 287 | + // await homePage.check_expectedTokenBalanceIsDisplayed( |
| 288 | + // '14.99994', |
| 289 | + // 'ETH', |
| 290 | + // ); |
| 291 | + |
| 292 | + driver.summarizeErrorsAndExceptions(); |
| 293 | + }, |
| 294 | + ); |
| 295 | + }); |
| 296 | + }); |
| 297 | +}); |
0 commit comments