index.vue 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554
  1. <template>
  2. <div>
  3. <div>
  4. <div class="swap">
  5. <div class="container">
  6. <div class="box">
  7. <van-row type="flex"
  8. justify="space-between"
  9. class="select_currency">
  10. <van-col class="currency_right">
  11. <div class="balance">{{$t('lang.swap20')}}</div>
  12. <div class="balance be"
  13. @click="handleToMax">{{ fromCur.balance ? $t('lang.swap22') : '' }} {{ significantDigits(fromCur.balance) }}</div>
  14. </van-col>
  15. </van-row>
  16. <van-row type="flex"
  17. justify="space-between"
  18. class="btRow">
  19. <van-col :span="15"
  20. class="title">
  21. <van-field type="number"
  22. v-model="fromInput"
  23. @input="hanldeInputFrom"
  24. placeholder="0.0"
  25. class="van-field"
  26. input-align="" />
  27. </van-col>
  28. <van-col :span="8">
  29. <div v-if="fromCur.name"
  30. class="selectedCurrency">
  31. <div class="tokenDetail"
  32. @click="handleGetCurrency('from')">
  33. <van-image round
  34. class="tokenImg"
  35. height="20px"
  36. :src="fromCur.logoUrl" />
  37. <div>{{ fromCur.symbol }}</div>
  38. <img class="arrows"
  39. src="@/assets/img/arrows.png" />
  40. </div>
  41. </div>
  42. <div v-else
  43. class="tokenSymbol"
  44. @click="handleGetCurrency('from')">{{ $t('lang.swap24') }}</div>
  45. </van-col>
  46. </van-row>
  47. <div class="maxWord">
  48. <span @click="handleToMax">MAX</span>
  49. </div>
  50. </div>
  51. <img src="@/assets/img/exchanges.png"
  52. @click="handleTurnAround"
  53. alt
  54. class="iconDown_img" />
  55. <div class="box">
  56. <van-row type="flex"
  57. justify="space-between"
  58. class="select_currency">
  59. <van-col class="currency_right">
  60. <div class="balance">{{$t('lang.swap25')}}</div>
  61. <div class="balance be">{{ fromCur.balance ? $t('lang.swap22') : '' }}{{ significantDigits(toCur.balance) }}</div>
  62. </van-col>
  63. </van-row>
  64. <van-row type="flex"
  65. justify="space-between"
  66. class="btRow">
  67. <van-col :span="15"
  68. class="title">
  69. <van-field type="number"
  70. v-model="toInput"
  71. @input="hanldeInputTo"
  72. placeholder="0.0"
  73. class="van-field"
  74. input-align="" />
  75. </van-col>
  76. <van-col :span="8"
  77. @click="handleGetCurrency('to')">
  78. <div v-if="toCur.name"
  79. class="selectedCurrency">
  80. <div class="tokenDetail">
  81. <van-image round
  82. class="tokenImg"
  83. height="20px"
  84. :src="toCur.logoUrl" />
  85. <div>{{ toCur.symbol }}</div>
  86. <img class="arrows"
  87. src="@/assets/img/arrows.png" />
  88. </div>
  89. </div>
  90. <div v-else
  91. class="tokenSymbol">{{ $t('lang.swap24') }}</div>
  92. </van-col>
  93. </van-row>
  94. </div>
  95. <!-- <van-row type="flex"
  96. justify="space-between">
  97. <div class="slipWrap">
  98. <div class="logo">
  99. <img src="@/assets/img/bnb.png"
  100. class="slipWrap_logo">
  101. <span>BNBD</span>
  102. </div>
  103. <div class="address">
  104. <span>{{ $t('lang.swap380') }} : {{getAccount}}</span>
  105. </div>
  106. </div>
  107. </van-row> -->
  108. <div class="button">
  109. <van-button type="primary"
  110. class="swapBtn"
  111. v-if="!account"
  112. @click="handleLogin">{{ $t('lang.swap26') }}</van-button>
  113. <van-button type="default"
  114. class="swapBtn"
  115. v-else-if="insufficientLiquidityShow"
  116. disabled>{{ $t('lang.swap27') }}</van-button>
  117. <van-button type="default"
  118. class="swapBtn"
  119. v-else-if="getNoInputBtnShow"
  120. disabled>{{ $t(lang.swap496) }}</van-button>
  121. <van-button type="default"
  122. class="swapBtn"
  123. v-else-if="getNoBalanceBtnShow"
  124. disabled>{{ $t('lang.swap29') }}</van-button>
  125. <van-button type="default"
  126. class="swapBtn"
  127. v-else-if="getNoSelectBtnShow"
  128. disabled>{{ $t('lang.swap30') }}</van-button>
  129. <van-button type="primary"
  130. class="swapBtn"
  131. :loading="approveLoading"
  132. loading-text="Approving..."
  133. v-else-if="allowanceToRouter"
  134. @click="handleApprove">{{ $t('lang.swap31') }}</van-button>
  135. <van-button type="primary"
  136. class="swapBtn"
  137. v-else-if="getWrap"
  138. @click="handleDeposit">{{ $t('lang.swap32') }}</van-button>
  139. <van-button type="primary"
  140. class="swapBtn"
  141. v-else-if="getWithdraw"
  142. @click="handleWithdraw">{{ $t('lang.swap33') }}</van-button>
  143. <van-button type="default"
  144. class="swapBtn"
  145. disabled
  146. v-else-if="portion >= 20 && !this.expert"
  147. @click="handleWithdraw">{{ $t('lang.swap34') }}</van-button>
  148. <van-button type="primary"
  149. class="swapBtn"
  150. :loading="swapLoading"
  151. loading-text="Waitting"
  152. v-else
  153. @click="flashRight">{{ $t('lang.swap35') }}</van-button>
  154. </div>
  155. </div>
  156. </div>
  157. </div>
  158. <van-popup v-if="tokenListShow"
  159. v-model="tokenListShow"
  160. round>
  161. <currency-list @listenClose="handleTokenListClose"
  162. @listenSelecteCurrency="handlerSelecteCurrency" />
  163. </van-popup>
  164. <van-popup v-model="settingShow"
  165. round>
  166. <SettingsModal @listenClose="handleSettingClose" />
  167. </van-popup>
  168. <van-popup v-model="swapDetailShow"
  169. :round="true"
  170. @closed="handleSwapDetailClosed">
  171. <swap-detail @listenClose="handleSwapDetailClose"
  172. @listenConfirm="handleConfirm"
  173. :fromCur="fromCur"
  174. :toCur="toCur"
  175. :swapDetail="swapDetail"
  176. :portion="portion" />
  177. </van-popup>
  178. <van-popup v-model="pendingDetailShow"
  179. round
  180. @closed="handlePendingSwapClosed">
  181. <pending-swap @listenClose="handlePendingSwapClose"
  182. :pendingDetail="pendingDetail"
  183. :fromCur="fromCur"
  184. :toCur="toCur" />
  185. </van-popup>
  186. <van-popup v-model="transactionRecordShow"
  187. round>
  188. <transaction-record @listenClose="handleTransactionRecordClose" />
  189. </van-popup>
  190. <van-popup v-model="VisualChartShow"
  191. round
  192. position="bottom">
  193. <visual-chart @VisualChartClose="visualChartClose"></visual-chart>
  194. </van-popup>
  195. <van-popup v-model="swapPopupShow"
  196. round>
  197. <SwapPopup @cancelButton="popupSwitch"
  198. @switch="swapSwitch"
  199. :swapPopupData="swapPopupData"
  200. :toCur="toCur"
  201. :fromCur="fromCur"
  202. :portion="portion"></SwapPopup>
  203. </van-popup>
  204. </div>
  205. </template>
  206. <script>
  207. import CurrencyList from '@/components/CurrencyList.vue';
  208. import SwapDetail from '@/views/swap/SwapDetail.vue';
  209. import PendingSwap from '@/views/swap/PendingSwap.vue';
  210. import TransactionRecord from '@/views/swap/TransactionRecord.vue';
  211. import VisualChart from '@/views/swap/VisualChart.vue';
  212. import SwapPopup from '@/views/swap/SwapPopup.vue';
  213. import { mapState } from 'vuex';
  214. import { formatAmount, parseAmount, accMul, accDiv, toFixed, accAdd, accSub, accGt, significantDigits, gasProcessing } from '@/utils/format.js';
  215. import { isBnb } from '@/utils/verify.js';
  216. import { getJackRouterAddress } from '@/utils/addressHelp';
  217. import { MaxUint256 } from '@ethersproject/constants';
  218. import { getErc20Contract, getJackRouterContract, getJackPairContract, getJackFactoryContract } from '@/utils/contractHelp';
  219. import SettingsModal from '@/components/SettingsModal.vue';
  220. import { simpleRpcProvider } from '@/utils/provider';
  221. import { useJackRouterContract, useErc20Contract, useWethContract } from '@/utils/useContract';
  222. import { getAllPair } from '@/utils/pairHelp';
  223. import web3 from 'web3';
  224. export default {
  225. name: 'Home',
  226. data () {
  227. return {
  228. fromBalance: '',
  229. tokenListShow: false, //选择代币列表
  230. settingShow: false, //设置滑点
  231. isShow: true, //是否展示余额
  232. approveLoading: false, //授权loading
  233. swapLoading: false,
  234. pendingDetailShow: false, //等待交换弹窗
  235. transactionRecordShow: false, //交易记录
  236. pendingDetail: { status: 0, hash: '', fromInput: '', toInput: '' },
  237. allPaths: [], //所有的多路径
  238. currentPaths: [], //当前所有多路径
  239. pathIndex: -1, //当前选择的多路径
  240. pathRouter: '',
  241. insufficientLiquidityShow: false, //当固定输出时,大于池子深度
  242. fromInput: '', //from输入框
  243. fromCur: {
  244. name: 'BNB',
  245. symbol: 'BNB',
  246. address: '0xc945fD8fe31A454ce821CB4514c7761aaB7b7BE0',
  247. chainId: 97,
  248. decimals: 18,
  249. balance: '',
  250. logoUrl: require('@/assets/img/bnb.png'),
  251. },
  252. toInput: '',
  253. toCur: {
  254. balance: '',
  255. name: '',
  256. symbol: '',
  257. address: '',
  258. chainId: '',
  259. decimals: '',
  260. logoUrl: '',
  261. },
  262. tokenSource: 'from',
  263. priceDirection: false,
  264. price: '',
  265. priceShow: false,
  266. inputSource: '',
  267. allowanceToRouter: false, //显示是否需要授权
  268. swapDetailShow: false, //确认交换弹窗
  269. swapDetail: { fromInput: '', toInput: '', amountIn: 0, amountInMax: 0, amountOut: 0, amountOutMin: 0, path: [], to: '', deadline: 0, inputSource: 'from', fee: 0 },
  270. chartShow: true,
  271. VisualChartShow: false, //数据图弹窗状态
  272. portion: undefined,
  273. switchVersionShow: '0',
  274. less: '<',
  275. swapPopupShow: false, //确认交换弹窗
  276. swapPopupData: {
  277. swapQuantity: '0',
  278. swapTitle: '警告',
  279. swapContent: '内容',
  280. },
  281. site: '',
  282. };
  283. },
  284. mounted () { },
  285. beforeDestroy () {
  286. //清除定时器
  287. window.clearInterval(this.timer);
  288. window.clearInterval(this.timerBalance);
  289. },
  290. async created () {
  291. //获取余额
  292. this.initialization();
  293. console.log(this.$route.query, 'aaaaaaaaa');
  294. this.site = this.$route.query.invite_address ? this.$route.query.invite_address : '';
  295. // if (this.$route.query.invite_address) {
  296. // let data = {
  297. // recommendAddress: this.$route.query.invite_address,
  298. // };
  299. // invite.userBind(data, this.account).then(res => {
  300. // if (res.code === 200) {
  301. // } else {
  302. // }
  303. // });
  304. // }
  305. },
  306. watch: {
  307. account () {
  308. //获取账号
  309. this.initialization();
  310. },
  311. },
  312. components: {
  313. CurrencyList,
  314. SettingsModal,
  315. SwapDetail,
  316. PendingSwap,
  317. TransactionRecord,
  318. VisualChart,
  319. SwapPopup,
  320. },
  321. computed: {
  322. ...mapState(['account', 'provider', 'gasPrice', 'slippage', 'deadline', 'multipath', 'pool', 'expert']),
  323. getAccount () {
  324. if (this.account) {
  325. return '0x...' + this.account.substring(this.account.length - 4, this.account.length);
  326. } else {
  327. return '';
  328. }
  329. },
  330. // 是否需要显示余额不足提示
  331. getNoBalanceBtnShow () {
  332. if (accGt(this.fromInput, this.fromCur.balance)) {
  333. return true;
  334. }
  335. return false;
  336. },
  337. //是否需要显示inputBtn按钮
  338. getNoInputBtnShow () {
  339. if ((parseFloat(this.fromInput) === 0 || this.fromInput === '') && this.fromCur.address !== '') {
  340. return true;
  341. } else if ((parseFloat(this.toInput) === 0 || this.toInput === '') && this.toCur.address !== '') {
  342. return true;
  343. }
  344. return false;
  345. },
  346. // 是否需要显示选择币种
  347. getNoSelectBtnShow () {
  348. if (this.fromCur.address == '' || this.toCur.address == '') {
  349. return true;
  350. }
  351. return false;
  352. },
  353. // 是否BNB - WBNB
  354. getWrap () {
  355. if (isBnb(this.fromCur) && this.toCur.address == this.fromCur.address) {
  356. return true;
  357. }
  358. return false;
  359. },
  360. // 是否WBNB - BNB
  361. getWithdraw () {
  362. if (isBnb(this.toCur) && this.toCur.address == this.fromCur.address) {
  363. return true;
  364. }
  365. return false;
  366. },
  367. },
  368. methods: {
  369. bind () {
  370. let data = {
  371. recommendAddress: this.$route.query.invite_address,
  372. };
  373. invite.userBind(data, this.account).then(res => {
  374. if (res.code === 200) {
  375. } else {
  376. }
  377. });
  378. },
  379. //判断是否登录
  380. handleLogin() {
  381. let token = this.$route.query.token;
  382. if (token) {
  383. localStorage.setItem('website', "app");
  384. localStorage.setItem('account', this.$route.query.mobile);
  385. localStorage.setItem('token__' + this.$route.query.mobile, token);
  386. this.$store.commit('SETACCOUNTS', this.$route.query.mobile);
  387. }
  388. this.$store.dispatch('setWebProvider');
  389. },
  390. //是否授权
  391. async handleDeposit () {
  392. const wethContract = useWethContract();
  393. const payableAmount = parseAmount(this.fromInput);
  394. const gas = await wethContract.methods.deposit().estimateGas({ from: this.account, value: payableAmount });
  395. wethContract.methods
  396. .deposit()
  397. .send({ from: this.account, value: payableAmount, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
  398. .on('transactionHash', hash => {
  399. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap15')} ${this.toInput} ${this.toCur.symbol}`;
  400. const title = this.$t('lang.swap18');
  401. const transactionsDetail = {
  402. hash,
  403. title,
  404. message,
  405. addedTime: new Date().getTime(),
  406. from: this.account,
  407. };
  408. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  409. })
  410. .on('receipt', receipt => { })
  411. .on('error', function (error, receipt) {
  412. throw error;
  413. });
  414. },
  415. //取出
  416. async handleWithdraw () {
  417. const wethContract = useWethContract();
  418. const wad = parseAmount(this.fromInput);
  419. const gas = await wethContract.methods.withdraw(wad).estimateGas({ from: this.account });
  420. wethContract.methods
  421. .withdraw(wad)
  422. .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
  423. .on('transactionHash', hash => {
  424. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap16')} ${this.toInput} ${this.toCur.symbol}`;
  425. const title = this.$t('lang.swap18');
  426. const transactionsDetail = {
  427. hash,
  428. title,
  429. message,
  430. addedTime: new Date().getTime(),
  431. from: this.account,
  432. };
  433. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  434. })
  435. .on('receipt', receipt => { })
  436. .on('error', function (error, receipt) {
  437. throw error;
  438. });
  439. },
  440. //关闭详情
  441. handleSwapDetailClose () {
  442. this.swapDetailShow = false;
  443. },
  444. //关闭详情
  445. handleSwapDetailClosed () {
  446. this.swapDetail = { fromInput: '', toInput: '', amountIn: 0, amountInMax: 0, amountOut: 0, amountOutMin: 0, path: [], to: '', deadline: 0, inputSource: 'from', fee: 0 };
  447. },
  448. handlePendingSwapClose () {
  449. this.pendingDetailShow = false;
  450. },
  451. handleTransactionRecordClose () {
  452. this.transactionRecordShow = false;
  453. },
  454. handlePendingSwapClosed () {
  455. this.pendingDetail = { status: 0, hash: '', fromInput: '', toInput: '' };
  456. },
  457. handleTokenListClose () {
  458. this.tokenListShow = false;
  459. },
  460. handleSettingClose () {
  461. this.settingShow = false;
  462. },
  463. // 获取两边币种余额
  464. async handleCurBalance () {
  465. console.log("获取余额");
  466. if (this.account) {
  467. if (isBnb(this.fromCur)) {
  468. console.log("走了这");
  469. const balance = await simpleRpcProvider.eth.getBalance(this.account);
  470. this.fromCur.balance = formatAmount(balance);
  471. }
  472. if (!isBnb(this.fromCur) && this.fromCur.address != '') {
  473. const erc20Contract = getErc20Contract(this.fromCur.address);
  474. const balance = await erc20Contract.methods.balanceOf(this.account).call();
  475. this.fromCur.balance = formatAmount(balance, this.fromCur.decimals);
  476. }
  477. if (isBnb(this.toCur)) {
  478. const balance = await simpleRpcProvider.eth.getBalance(this.account);
  479. this.toCur.balance = formatAmount(balance);
  480. }
  481. if (!isBnb(this.toCur) && this.toCur.address != '') {
  482. console.log("走了这李", this.toCur);
  483. const erc20Contract = getErc20Contract(this.toCur.address);
  484. const balance = await erc20Contract.methods.balanceOf(this.account).call();
  485. this.toCur.balance = formatAmount(balance, this.toCur.decimals);
  486. }
  487. }
  488. },
  489. flashRight () {
  490. if (this.portion > 10 && this.expert == false) {
  491. this.swapPopupShow = true;
  492. } else {
  493. this.handleSwap();
  494. }
  495. },
  496. // 闪兑
  497. handleSwap () {
  498. if (this.fromCur.address == '0x1676BDdf162A800cCb5f9e81b0F402A33c51e06c' || this.toCur.address == '0x1676BDdf162A800cCb5f9e81b0F402A33c51e06c') {
  499. // Toast.fail(this.$t('lang.swap65'));
  500. // this.$toast.fail(this.$t('lang.swap65'))
  501. return;
  502. }
  503. const slippage = accDiv(this.slippage, 100);
  504. this.swapDetail.inputInMax = significantDigits(accAdd(this.fromInput, accMul(this.fromInput, slippage)));
  505. this.swapDetail.inputOutMin = significantDigits(accSub(this.toInput, accMul(this.toInput, slippage)));
  506. this.swapDetail.inputSource = this.inputSource;
  507. this.swapDetail.price = this.price;
  508. this.swapDetail.fromInput = this.fromInput;
  509. this.swapDetail.toInput = this.toInput;
  510. this.swapDetail.fee = accMul(this.swapDetail.inputInMax, 0.003);
  511. this.swapDetailShow = true;
  512. },
  513. //同意
  514. handleConfirm () {
  515. const slippage = accDiv(this.slippage, 100);
  516. const amountIn = parseAmount(this.fromInput, this.fromCur.decimals);
  517. const amountInMax = toFixed(accAdd(amountIn, accMul(amountIn, slippage)), 0);
  518. const amountOut = parseAmount(this.toInput, this.toCur.decimals);
  519. const amountOutMin = toFixed(accSub(amountOut, accMul(amountOut, slippage)), 0);
  520. let path = [];
  521. const currentPath = this.currentPaths[this.pathIndex];
  522. if (currentPath.length == 1) {
  523. path = [this.fromCur.address, this.toCur.address];
  524. }
  525. if (currentPath.length == 2) {
  526. path = [this.fromCur.address, currentPath[0].toCur.address, currentPath[1].toCur.address];
  527. }
  528. const to = this.account;
  529. const deadline = accAdd(accDiv(Date.parse(new Date()), 1000), accMul(this.deadline, 60));
  530. this.pendingDetail.fromInput = this.fromInput;
  531. this.pendingDetail.toInput = this.toInput;
  532. if (isBnb(this.fromCur) && this.inputSource == 'from') {
  533. console.log('111111111');
  534. this.swapExactETHForTokens(amountIn, amountOutMin, path, to, deadline);
  535. return;
  536. }
  537. if (isBnb(this.fromCur) && this.inputSource == 'to') {
  538. this.swapETHForExactTokens(amountOut, amountInMax, path, to, deadline);
  539. return;
  540. }
  541. if (isBnb(this.toCur) && this.inputSource == 'from') {
  542. this.swapExactTokensForETH(amountIn, amountOutMin, path, to, deadline);
  543. return;
  544. }
  545. if (isBnb(this.toCur) && this.inputSource == 'to') {
  546. this.swapTokensForExactETH(amountOut, amountInMax, path, to, deadline);
  547. return;
  548. }
  549. if (this.inputSource == 'from') {
  550. this.swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline);
  551. return;
  552. }
  553. if (this.inputSource == 'to') {
  554. this.swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline);
  555. return;
  556. }
  557. },
  558. async swapExactETHForTokens (amountIn, amountOutMin, path, to, deadline) {
  559. const jackRouterContract = useJackRouterContract();
  560. const gas = await jackRouterContract.methods.swapExactETHForTokens(amountOutMin, path, to, deadline).estimateGas({ from: this.account, value: amountIn });
  561. this.swapDetailShow = false;
  562. this.swapLoading = true;
  563. this.pendingDetailShow = true;
  564. jackRouterContract.methods
  565. .swapExactETHForTokens(amountOutMin, path, to, deadline)
  566. .send({ from: this.account, value: amountIn })
  567. .on('transactionHash', hash => {
  568. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  569. const title = this.$t('lang.swap18');
  570. const transactionsDetail = {
  571. hash,
  572. title,
  573. message,
  574. addedTime: new Date().getTime(),
  575. from: this.account,
  576. };
  577. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  578. this.pendingDetail.status = 1;
  579. this.pendingDetail.hash = hash;
  580. })
  581. .on('receipt', receipt => {
  582. this.swapLoading = false;
  583. })
  584. .on('error', (error, receipt) => {
  585. this.pendingDetail.status = 2;
  586. this.swapLoading = false;
  587. throw error;
  588. });
  589. },
  590. async swapETHForExactTokens (amountOut, amountInMax, path, to, deadline) {
  591. const jackRouterContract = useJackRouterContract();
  592. const gas = await jackRouterContract.methods
  593. .swapETHForExactTokens(amountOut, path, to, deadline)
  594. .estimateGas({ from: this.account, value: amountInMax })
  595. .catch(async e => {
  596. const gas = await jackRouterContract.methods.swapExactETHForTokensSupportingFeeOnTransferTokens(amountOut, path, to, deadline).estimateGas({ from: this.account, value: amountInMax });
  597. this.swapDetailShow = false;
  598. this.pendingDetailShow = true;
  599. jackRouterContract.methods
  600. .swapExactETHForTokensSupportingFeeOnTransferTokens(amountOut, path, to, deadline)
  601. .send({ from: this.account, value: amountInMax, })
  602. .on('transactionHash', hash => {
  603. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  604. const title = this.$t('lang.swap18');
  605. const transactionsDetail = {
  606. hash,
  607. title,
  608. message,
  609. addedTime: new Date().getTime(),
  610. from: this.account,
  611. };
  612. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  613. this.pendingDetail.status = 1;
  614. this.pendingDetail.hash = hash;
  615. })
  616. .on('error', (error, receipt) => {
  617. this.pendingDetail.status = 2;
  618. throw error;
  619. });
  620. });
  621. this.swapDetailShow = false;
  622. this.swapLoading = true;
  623. this.pendingDetailShow = true;
  624. jackRouterContract.methods
  625. .swapETHForExactTokens(amountOut, path, to, deadline)
  626. .send({ from: this.account, value: amountInMax, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
  627. .on('transactionHash', hash => {
  628. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  629. const title = this.$t('lang.swap18');
  630. const transactionsDetail = {
  631. hash,
  632. title,
  633. message,
  634. addedTime: new Date().getTime(),
  635. from: this.account,
  636. };
  637. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  638. this.pendingDetail.status = 1;
  639. this.pendingDetail.hash = hash;
  640. })
  641. .on('receipt', receipt => {
  642. this.swapLoading = false;
  643. })
  644. .on('error', (error, receipt) => {
  645. this.pendingDetail.status = 2;
  646. throw error;
  647. });
  648. },
  649. async swapExactTokensForETH (amountIn, amountOutMin, path, to, deadline) {
  650. const jackRouterContract = useJackRouterContract();
  651. jackRouterContract.methods
  652. .swapExactTokensForETH(amountIn, amountOutMin, path, to, deadline)
  653. .estimateGas({ from: this.account })
  654. .then(res => {
  655. this.swapDetailShow = false;
  656. this.pendingDetailShow = true;
  657. this.swapLoading = true;
  658. jackRouterContract.methods
  659. .swapExactTokensForETH(amountIn, amountOutMin, path, to, deadline)
  660. .send({ from: this.account, gas: gasProcessing(res), gasPrice: web3.utils.numberToHex(this.gasPrice) })
  661. .on('transactionHash', hash => {
  662. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  663. const title = this.$t('lang.swap18');
  664. const transactionsDetail = {
  665. hash,
  666. title,
  667. message,
  668. addedTime: new Date().getTime(),
  669. from: this.account,
  670. };
  671. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  672. this.pendingDetail.status = 1;
  673. this.pendingDetail.hash = hash;
  674. })
  675. .on('receipt', receipt => {
  676. this.swapLoading = false;
  677. })
  678. .on('error', (error, receipt) => {
  679. this.pendingDetail.status = 2;
  680. throw error;
  681. });
  682. })
  683. .catch(e => {
  684. this.$toast('Try increasing your slippage tolerance.');
  685. this.swapDetailShow = false;
  686. });
  687. },
  688. async swapTokensForExactETH (amountOut, amountInMax, path, to, deadline) {
  689. const jackRouterContract = useJackRouterContract();
  690. const gas = await jackRouterContract.methods.swapTokensForExactETH(amountOut, amountInMax, path, to, deadline).estimateGas({ from: this.account });
  691. this.swapDetailShow = false;
  692. this.pendingDetailShow = true;
  693. jackRouterContract.methods
  694. .swapTokensForExactETH(amountOut, amountInMax, path, to, deadline)
  695. .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
  696. .on('transactionHash', hash => {
  697. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  698. const title = this.$t('lang.swap18');
  699. const transactionsDetail = {
  700. hash,
  701. title,
  702. message,
  703. addedTime: new Date().getTime(),
  704. from: this.account,
  705. };
  706. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  707. this.pendingDetail.status = 1;
  708. this.pendingDetail.hash = hash;
  709. })
  710. .on('error', (error, receipt) => {
  711. this.pendingDetail.status = 2;
  712. throw error;
  713. });
  714. },
  715. async swapExactTokensForTokens (amountIn, amountOutMin, path, to, deadline) {
  716. const jackRouterContract = useJackRouterContract();
  717. const gas = await jackRouterContract.methods
  718. .swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline)
  719. .estimateGas({ from: this.account })
  720. .catch(async e => {
  721. //获取gas报错走这里
  722. console.log('走了这里上面');
  723. const gas = await jackRouterContract.methods
  724. .swapExactTokensForTokensSupportingFeeOnTransferTokens(amountIn, amountOutMin, path, to, deadline)
  725. .estimateGas({ from: this.account })
  726. .catch(res => {
  727. this.swapPopupData.swapQuantity = '1';
  728. this.swapPopupData.swapTitle = 'error';
  729. this.swapPopupData.swapContent = 'The transaction cannot succeed due to error: undefined. This is probably an issue with one of the tokens you are swapping.';
  730. this.swapDetailShow = false;
  731. this.pendingDetailShow = false;
  732. this.swapPopupShow = true;
  733. });
  734. if (gas) {
  735. this.swapDetailShow = false;
  736. this.pendingDetailShow = true;
  737. jackRouterContract.methods
  738. .swapExactTokensForTokensSupportingFeeOnTransferTokens(amountIn, amountOutMin, path, to, deadline)
  739. .send({ from: this.account })
  740. .on('transactionHash', hash => {
  741. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  742. const title = this.$t('lang.swap18');
  743. const transactionsDetail = {
  744. hash,
  745. title,
  746. message,
  747. addedTime: new Date().getTime(),
  748. from: this.account,
  749. };
  750. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  751. this.pendingDetail.status = 1;
  752. this.pendingDetail.hash = hash;
  753. })
  754. .on('error', (error, receipt) => {
  755. this.pendingDetail.status = 2;
  756. this.swapLoading = false;
  757. throw error;
  758. });
  759. }
  760. });
  761. if (gas) {
  762. this.swapDetailShow = false;
  763. this.pendingDetailShow = true;
  764. this.swapLoading = true;
  765. jackRouterContract.methods
  766. .swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline)
  767. .send({ from: this.account })
  768. .on('transactionHash', hash => {
  769. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  770. const title = this.$t('lang.swap18');
  771. const transactionsDetail = {
  772. hash,
  773. title,
  774. message,
  775. addedTime: new Date().getTime(),
  776. from: this.account,
  777. };
  778. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  779. this.pendingDetail.status = 1;
  780. this.pendingDetail.hash = hash;
  781. })
  782. .on('receipt', receipt => {
  783. this.swapLoading = false;
  784. })
  785. .on('error', (error, receipt) => {
  786. this.pendingDetail.status = 2;
  787. this.swapLoading = false;
  788. throw error;
  789. });
  790. }
  791. },
  792. async swapTokensForExactTokens (amountOut, amountInMax, path, to, deadline) {
  793. const jackRouterContract = useJackRouterContract();
  794. const gas = await jackRouterContract.methods.swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline).estimateGas({ from: this.account });
  795. this.swapDetailShow = false;
  796. this.pendingDetailShow = true;
  797. this.swapLoading = true;
  798. jackRouterContract.methods
  799. .swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline)
  800. .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
  801. .on('transactionHash', hash => {
  802. const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
  803. const title = this.$t('lang.swap18');
  804. const transactionsDetail = {
  805. hash,
  806. title,
  807. message,
  808. addedTime: new Date().getTime(),
  809. from: this.account,
  810. };
  811. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  812. this.pendingDetail.status = 1;
  813. this.pendingDetail.hash = hash;
  814. })
  815. .on('receipt', receipt => {
  816. this.swapLoading = false;
  817. })
  818. .on('error', error => {
  819. this.pendingDetail.status = 2;
  820. this.swapLoading = false;
  821. throw error;
  822. });
  823. },
  824. //获取所有的交易对
  825. async handleGetAllPair () {
  826. if (this.getWrap || this.getWithdraw) {
  827. this.allpaths = [];
  828. return;
  829. }
  830. if (this.fromCur.address == '' || this.toCur.address == '') {
  831. return;
  832. }
  833. const allPair = getAllPair(this.fromCur, this.toCur);
  834. console.log(allPair, 'allPairrrrrrrrrrr');
  835. const promisePairAddress = allPair.map(item => {
  836. const jackFactoryContract = getJackFactoryContract();
  837. const pairAddress = jackFactoryContract.methods.getPair(item.fromCur.address, item.toCur.address).call();
  838. return pairAddress;
  839. });
  840. let allPairAddress = await Promise.all(promisePairAddress);
  841. let lpPair = [];
  842. for (let i = 0; i < allPair.length; i++) {
  843. const lpAddress = allPairAddress[i];
  844. if (lpAddress == '0x0000000000000000000000000000000000000000') {
  845. continue;
  846. }
  847. lpPair.push({ lpAddress, ...allPair[i] });
  848. }
  849. let promiseReserve = lpPair.map(item => {
  850. const jackPairContract = getJackPairContract(item.lpAddress);
  851. const reserves = jackPairContract.methods.getReserves().call();
  852. return reserves;
  853. });
  854. const allReserves = await Promise.all(promiseReserve);
  855. let newlpPair = lpPair.map((item, index) => {
  856. let newItem = JSON.parse(JSON.stringify(item));
  857. if (newItem.fromCur.address.toLowerCase() < newItem.toCur.address.toLowerCase()) {
  858. newItem.fromCur.reserves = allReserves[index]._reserve0;
  859. newItem.toCur.reserves = allReserves[index]._reserve1;
  860. } else {
  861. newItem.fromCur.reserves = allReserves[index]._reserve1;
  862. newItem.toCur.reserves = allReserves[index]._reserve0;
  863. }
  864. return newItem;
  865. });
  866. let pathFrom = [];
  867. for (let i of newlpPair) {
  868. if (i.fromCur.address == this.fromCur.address) {
  869. pathFrom.push(i);
  870. }
  871. }
  872. let pathTo = [];
  873. for (let i of newlpPair) {
  874. if (i.toCur.address == this.toCur.address) {
  875. pathTo.push(i);
  876. }
  877. }
  878. let allpaths = [];
  879. // 算出到底有多少条路径
  880. for (let i = 0; i < pathFrom.length; i++) {
  881. const item = pathFrom[i];
  882. const findItem = pathTo.find(toItem => {
  883. return item.toCur.address == toItem.fromCur.address;
  884. });
  885. if (findItem && findItem.toCur.address == this.toCur.address) {
  886. allpaths.push([item, findItem]);
  887. continue;
  888. }
  889. if (item.toCur.address == this.toCur.address) {
  890. allpaths.push([item]);
  891. }
  892. }
  893. this.allpaths = allpaths;
  894. console.log(this.allpaths, 'this.allpaths');
  895. if (this.inputSource === 'from') {
  896. this.getAmountsOut();
  897. }
  898. if (this.inputSource === 'to') {
  899. this.getAmountsIn();
  900. }
  901. },
  902. // from的输入框
  903. async hanldeInputFrom () {
  904. this.inputSource = 'from';
  905. this.getAmountsOut();
  906. },
  907. //to的输入框
  908. hanldeInputTo () {
  909. this.inputSource = 'to';
  910. this.getAmountsIn();
  911. },
  912. // 是否需要显示授权按钮
  913. async handleApproveBtnShow () {
  914. if (isBnb(this.fromCur) || this.fromCur.address == '') {
  915. this.allowanceToRouter = false;
  916. return;
  917. }
  918. if (this.account) {
  919. const erc20Contract = getErc20Contract(this.fromCur.address);
  920. const to = getJackRouterAddress();
  921. const allowance = await erc20Contract.methods.allowance(this.account, to).call();
  922. if (allowance == 0) {
  923. this.allowanceToRouter = true;
  924. } else {
  925. this.allowanceToRouter = false;
  926. }
  927. }
  928. },
  929. // 设置输入框最大值
  930. async handleToMax () {
  931. if (isBnb(this.fromCur)) {
  932. if (this.fromCur.balance > 0.01) {
  933. this.fromInput = significantDigits(this.fromCur.balance * 1 - 0.01 + '');
  934. } else {
  935. this.fromInput = 0;
  936. console.log('8888888888888888');
  937. }
  938. } else {
  939. this.fromInput = significantDigits(this.fromCur.balance);
  940. }
  941. this.inputSource = 'from';
  942. this.getAmountsOut();
  943. },
  944. async initialization () {
  945. console.log("走了这....");
  946. this.handleCurBalance();
  947. // 余额定时器请求
  948. this.handleTimerBalance();
  949. if (this.site) {
  950. this.bind();
  951. }
  952. },
  953. async handleTimerBalance () {
  954. window.clearTimeout(this.timerBalance);
  955. this.timerBalance = setInterval(async () => {
  956. this.handleCurBalance();
  957. }, 3000);
  958. },
  959. // 修改价格方向
  960. changePriceDirection () {
  961. this.priceDirection = !this.priceDirection;
  962. this.getPairPrice();
  963. },
  964. //是否显示设置得余额
  965. handleSettingShow () {
  966. this.settingShow = true;
  967. },
  968. handleRecordShow () {
  969. this.transactionRecordShow = true;
  970. },
  971. async handlerSelecteCurrency (currency) {
  972. this.tokenListShow = false;
  973. if (this.tokenSource == 'from') {
  974. if (currency.address == this.toCur.address && currency.name == this.toCur.name) {
  975. this.turnAround();
  976. } else {
  977. this.fromCur = currency;
  978. }
  979. } else {
  980. if (currency.address == this.fromCur.address && currency.name == this.fromCur.name) {
  981. this.turnAround();
  982. } else {
  983. this.toCur = currency;
  984. }
  985. }
  986. this.handleGetAllPair();
  987. this.handleApproveBtnShow();
  988. this.handleCurBalance();
  989. },
  990. // 流动池价格更换
  991. async getPairPrice () {
  992. if (parseFloat(this.fromInput) === 0 || parseFloat(this.toInput) === 0) {
  993. this.fromInput = '';
  994. return;
  995. }
  996. if (this.fromCur.address === '' || this.toCur.address === '') {
  997. this.fromInput = '';
  998. return;
  999. }
  1000. const fromInput = parseFloat(this.fromInput);
  1001. const toInput = parseFloat(this.toInput);
  1002. if (this.priceDirection) {
  1003. const price = accDiv(fromInput, toInput);
  1004. this.price = significantDigits(price);
  1005. } else {
  1006. const price = accDiv(toInput, fromInput);
  1007. this.price = significantDigits(price);
  1008. }
  1009. this.priceShow = true;
  1010. },
  1011. //获取实时交易显示
  1012. async getAmountsOut () {
  1013. console.log('输出价格');
  1014. this.insufficientLiquidityShow = false;
  1015. if (parseFloat(this.fromInput) === 0 || this.fromInput == '') {
  1016. this.toInput = '';
  1017. this.priceShow = false;
  1018. return;
  1019. }
  1020. if (this.fromCur.address === '' || this.toCur.address === '') {
  1021. this.toInput = '';
  1022. this.priceShow = false;
  1023. return;
  1024. }
  1025. if (this.getWrap || this.getWithdraw) {
  1026. this.toInput = this.fromInput;
  1027. return;
  1028. }
  1029. if (this.multipath) {
  1030. this.currentPaths = this.allpaths.filter(item => {
  1031. return item.length == 1;
  1032. });
  1033. } else {
  1034. this.currentPaths = this.allpaths;
  1035. }
  1036. let pathIndex = -1;
  1037. let max = 0;
  1038. console.log(this.currentPaths, '当前的多路径');
  1039. for (let i = 0; i < this.currentPaths.length; i++) {
  1040. const pathItem = this.currentPaths[i];
  1041. let amounts = [];
  1042. amounts[0] = parseAmount(this.fromInput, this.fromCur.decimals);
  1043. for (let j = 0; j < pathItem.length; j++) {
  1044. let reserveIn = pathItem[j].fromCur.reserves;
  1045. let reserveOut = pathItem[j].toCur.reserves;
  1046. if (reserveIn == 0 || reserveOut == 0) {
  1047. amounts[j + 1] = 0;
  1048. break;
  1049. }
  1050. let amountInWithFee = accMul(amounts[j], 997);
  1051. console.log('amountInWithFee', amountInWithFee);
  1052. let numerator = accMul(amountInWithFee, reserveOut);
  1053. console.log('numerator', numerator);
  1054. let denominator = accAdd(accMul(reserveIn, 1000), amountInWithFee);
  1055. console.log('denominator', denominator);
  1056. let amountOut = toFixed(accDiv(numerator, denominator), 0);
  1057. console.log('当前输出', amountOut);
  1058. amounts[j + 1] = amountOut;
  1059. }
  1060. if (accGt(amounts[amounts.length - 1], max)) {
  1061. max = amounts[amounts.length - 1];
  1062. console.log('最大值', max);
  1063. pathIndex = i;
  1064. }
  1065. }
  1066. if (pathIndex == -1 || this.currentPaths.length == 0) {
  1067. this.insufficientLiquidityShow = true;
  1068. this.toInput = '';
  1069. return;
  1070. }
  1071. this.pathIndex = pathIndex;
  1072. let list = this.currentPaths[this.pathIndex];
  1073. this.pathRouter = '';
  1074. console.log(list, 'list');
  1075. this.proportion(list);
  1076. for (let k = 0; k < list.length; k++) {
  1077. if (k == 0) {
  1078. console.log('1');
  1079. this.pathRouter = this.pathRouter + list[k].fromCur.symbol + '>' + list[k].toCur.symbol;
  1080. } else {
  1081. console.log('2');
  1082. this.pathRouter = this.pathRouter + '>' + list[k].toCur.symbol;
  1083. }
  1084. }
  1085. this.toInput = formatAmount(max, this.toCur.decimals);
  1086. this.getPairPrice();
  1087. },
  1088. proportion (list) {
  1089. let shuru = this.fromInput * 1 * Math.pow(10, this.fromCur.decimals);
  1090. let one = accDiv(shuru, accAdd(shuru, list[0].fromCur.reserves)) * 100; // 第一个的影响
  1091. this.portion = one;
  1092. if (list.length > 1) {
  1093. let two =
  1094. accDiv(
  1095. accMul(shuru, list[0].toCur.reserves),
  1096. accAdd(accAdd(accMul(shuru, list[0].toCur.reserves), accMul(shuru, list[1].fromCur.reserves)), accMul(list[0].fromCur.reserves, list[1].fromCur.reserves))
  1097. ) * 100;
  1098. this.portion = this.portion + two;
  1099. }
  1100. if (this.portion >= 99.75) {
  1101. this.portion = 99.75;
  1102. }
  1103. },
  1104. async getAmountsIn () {
  1105. this.insufficientLiquidityShow = false;
  1106. if (parseFloat(this.toInput) === 0 || this.toInput == '') {
  1107. this.fromInput = '';
  1108. this.priceShow = false;
  1109. return;
  1110. }
  1111. if (this.fromCur.address === '' || this.toCur.address === '') {
  1112. this.fromInput = '';
  1113. this.priceShow = false;
  1114. return;
  1115. }
  1116. if (this.getWrap || this.getWithdraw) {
  1117. this.fromInput = this.toInput;
  1118. return;
  1119. }
  1120. if (this.multipath) {
  1121. this.currentPaths = this.allpaths.filter(item => {
  1122. return item.length == 1;
  1123. });
  1124. } else {
  1125. this.currentPaths = this.allpaths;
  1126. }
  1127. let pathIndex = -1;
  1128. let min = 0;
  1129. for (let i = 0; i < 1; i++) {
  1130. const pathItem = this.currentPaths[i];
  1131. let amounts = [];
  1132. amounts[pathItem.length] = parseAmount(this.toInput, this.toCur.decimals);
  1133. for (let j = pathItem.length; j > 0; j--) {
  1134. let reserveIn = pathItem[j - 1].fromCur.reserves;
  1135. let reserveOut = pathItem[j - 1].toCur.reserves;
  1136. if (reserveIn == 0 || reserveOut == 0) {
  1137. amounts[j - 1] = 0;
  1138. break;
  1139. }
  1140. let numerator = accMul(accMul(reserveIn, amounts[j]), 1000);
  1141. let denominator = accMul(accSub(reserveOut, amounts[j]), 997);
  1142. let amountIn = toFixed(accAdd(accDiv(numerator, denominator), 1), 0);
  1143. amounts[j - 1] = amountIn;
  1144. }
  1145. if (accGt(amounts[0], 0)) {
  1146. if (i == 0) {
  1147. min = amounts[0];
  1148. pathIndex = i;
  1149. } else if (accGt(min, amounts[0])) {
  1150. min = amounts[0];
  1151. pathIndex = i;
  1152. }
  1153. }
  1154. }
  1155. this.pathIndex = pathIndex;
  1156. // 流动性不足
  1157. if (pathIndex == -1 || this.currentPaths.length == 0) {
  1158. this.insufficientLiquidityShow = true;
  1159. this.fromInput = '';
  1160. return;
  1161. }
  1162. this.fromInput = formatAmount(min, this.fromCur.decimals);
  1163. this.getPairPrice();
  1164. },
  1165. handleGetCurrency (tokenSource) {
  1166. // this.tokenSource = tokenSource;
  1167. // this.tokenListShow = true;
  1168. },
  1169. // 点击反转按钮
  1170. handleTurnAround () {
  1171. // this.turnAround();
  1172. // this.handleGetAllPair();
  1173. // this.handleApproveBtnShow();
  1174. // this.handleCurBalance();
  1175. },
  1176. // 交换from to数据
  1177. turnAround () {
  1178. const tempCurrency = { ...this.toCur };
  1179. this.toCur = { ...this.fromCur };
  1180. this.fromCur = { ...tempCurrency };
  1181. const tempInput = this.toInput;
  1182. this.toInput = this.fromInput;
  1183. this.fromInput = tempInput;
  1184. this.inputSource = this.inputSource === 'from' ? 'to' : 'from';
  1185. },
  1186. async handleApprove () {
  1187. const erc20Contract = useErc20Contract(this.fromCur.address);
  1188. const amount = MaxUint256.toString();
  1189. const to = getJackRouterAddress();
  1190. const gas = await erc20Contract.methods.approve(to, amount).estimateGas({ from: this.account });
  1191. this.approveLoading = true;
  1192. erc20Contract.methods
  1193. .approve(to, amount)
  1194. .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
  1195. .on('transactionHash', hash => {
  1196. const transactionsDetail = {
  1197. title: '',
  1198. hash,
  1199. message: `${this.$t('lang.swap14')} ${this.fromCur.symbol}`,
  1200. addedTime: new Date().getTime(),
  1201. from: this.account,
  1202. };
  1203. this.$store.commit('SETTRANSACTIONS', transactionsDetail);
  1204. })
  1205. .on('receipt', receipt => {
  1206. this.handleApproveBtnShow();
  1207. this.approveLoading = false;
  1208. })
  1209. .on('error', (error, receipt) => {
  1210. this.approveLoading = false;
  1211. this.handleApproveBtnShow();
  1212. throw error;
  1213. });
  1214. },
  1215. visualChartClose () {
  1216. this.VisualChartShow = !this.VisualChartShow;
  1217. },
  1218. // 弹窗开关
  1219. swapSwitch () {
  1220. this.swapPopupShow = !this.swapPopupShow;
  1221. },
  1222. // 弹窗确认按钮
  1223. popupSwitch () {
  1224. this.swapPopupShow = false;
  1225. this.handleSwap();
  1226. },
  1227. significantDigits,
  1228. accSub,
  1229. accMul,
  1230. },
  1231. };
  1232. </script>
  1233. <style lang="less" scoped>
  1234. .swap {
  1235. position: relative;
  1236. width: 100%;
  1237. border-radius: 20px;
  1238. .headWrap {
  1239. position: absolute;
  1240. right: 0;
  1241. display: flex;
  1242. align-items: center;
  1243. justify-content: flex-end;
  1244. padding: 8px 16px;
  1245. .iconSet {
  1246. width: 20px;
  1247. height: 20px;
  1248. // margin-right: 23px;
  1249. cursor: pointer;
  1250. }
  1251. .iconRecord {
  1252. width: 20px;
  1253. height: 20px;
  1254. margin-left: 15px;
  1255. cursor: pointer;
  1256. }
  1257. .iconHash {
  1258. width: 20px;
  1259. height: 20px;
  1260. }
  1261. .headWrap_img {
  1262. display: flex;
  1263. align-items: center;
  1264. justify-content: flex-end;
  1265. background: rgba(199, 199, 199, 0.2);
  1266. border-radius: 14px;
  1267. padding: 4px 14px;
  1268. }
  1269. }
  1270. .container {
  1271. border-radius: 0 0 16px 16px;
  1272. padding: 20px;
  1273. background: #171717;
  1274. .box {
  1275. // padding: 20px 15px;
  1276. // background: @background-gray;
  1277. border-radius: 10px;
  1278. // background: #f8f7f7;
  1279. // border: 1px solid #ffd245;
  1280. // box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.3);
  1281. font-weight: bold;
  1282. .balance {
  1283. font-size: 14px;
  1284. font-weight: normal;
  1285. color: #eceef0;
  1286. }
  1287. .be {
  1288. font-size: 12px;
  1289. }
  1290. .select_currency {
  1291. display: flex;
  1292. align-items: center;
  1293. .currency_right {
  1294. display: flex;
  1295. align-items: center;
  1296. justify-content: space-between;
  1297. width: 100%;
  1298. }
  1299. }
  1300. .btRow {
  1301. display: flex;
  1302. // background: #1e242b;
  1303. align-items: center;
  1304. border-radius: 12px;
  1305. margin-top: 20px;
  1306. // padding: 18px 0 18px;
  1307. // .title {
  1308. // width: 100%;
  1309. // }
  1310. }
  1311. .van-field {
  1312. border: 1px solid #1e242b !important;
  1313. color: #eceef0;
  1314. background: #333333 !important;
  1315. padding: 0 10px !important;
  1316. /deep/ .van-field__control {
  1317. color: #eceef0 !important;
  1318. }
  1319. }
  1320. .tokenSymbol {
  1321. font-size: 14px;
  1322. border-radius: 8px;
  1323. text-align: right;
  1324. color: #f6bb31;
  1325. // border: 1px solid #f6bb31;
  1326. // background: linear-gradient(228deg, #fdde34 0%, #65fce4 100%);
  1327. padding: 2px 6px;
  1328. cursor: pointer;
  1329. }
  1330. .maxWord {
  1331. // color: #595b5b;
  1332. // background: linear-gradient(228deg, #fdde34 0%, #65fce4 100%);
  1333. // font-size: 10px;
  1334. // font-weight: bold;
  1335. // cursor: pointer;
  1336. // border-radius: 9px;
  1337. // padding: 4px 6px;
  1338. // margin-left: 10px;
  1339. margin-top: 10px;
  1340. display: flex;
  1341. justify-content: flex-end;
  1342. span {
  1343. color: #f6bb31;
  1344. border-radius: 2px 2px 2px 2px;
  1345. border: 1px solid #f6bb31;
  1346. padding: 4px 10px;
  1347. }
  1348. }
  1349. .selectedCurrency {
  1350. display: flex;
  1351. align-items: center;
  1352. justify-content: flex-end;
  1353. .tokenDetail {
  1354. display: flex;
  1355. align-items: center;
  1356. font-size: 14px;
  1357. // border: 1px solid #ffd245;
  1358. border-radius: 4px;
  1359. color: #e8e7f0;
  1360. padding: 2px 6px;
  1361. margin: 0 2px;
  1362. // border: 1px solid #f6bb31;
  1363. cursor: pointer;
  1364. .arrows {
  1365. width: 10px;
  1366. height: 6px;
  1367. margin-left: 6px;
  1368. }
  1369. }
  1370. .tokenImg {
  1371. margin-right: 4px;
  1372. margin-left: 4px;
  1373. width: 16px !important;
  1374. height: 16px !important;
  1375. }
  1376. }
  1377. }
  1378. .iconDown_img {
  1379. width: 30px;
  1380. height: 30px;
  1381. display: block;
  1382. margin: 20px auto;
  1383. cursor: pointer;
  1384. transform: rotate(90deg);
  1385. }
  1386. // .slipWrap {
  1387. // display: flex;
  1388. // align-items: center;
  1389. // font-size: 12px;
  1390. // font-family: PingFangSC-Medium, PingFang SC;
  1391. // font-weight: 500;
  1392. // // color: #65fce4;
  1393. // margin: 20px 0;
  1394. // .text {
  1395. // color: #eceef0;
  1396. // }
  1397. // .iconSet {
  1398. // display: flex;
  1399. // align-items: center;
  1400. // color: #fff;
  1401. // .iconSet_img {
  1402. // width: 20px;
  1403. // height: 20px;
  1404. // margin-left: 6px;
  1405. // }
  1406. // }
  1407. // }
  1408. }
  1409. }
  1410. .button {
  1411. .swapBtn {
  1412. width: 100%;
  1413. height: auto;
  1414. margin-top: 22px;
  1415. font-size: 14px;
  1416. font-weight: bold;
  1417. border-radius: 6px;
  1418. border: 0;
  1419. padding: 8px 0 !important;
  1420. }
  1421. /deep/ .van-button--primary {
  1422. color: #000000;
  1423. background: linear-gradient(321deg, #fdde34 0%, #65fce4 100%);
  1424. border: 0;
  1425. }
  1426. /deep/ .van-button--disabled {
  1427. color: #878995;
  1428. background: #1e242b;
  1429. }
  1430. }
  1431. .slipWrap {
  1432. color: #ffffff;
  1433. width: 100%;
  1434. background: #333333;
  1435. border-radius: 2px;
  1436. margin: 20px 0 10px;
  1437. padding: 20px;
  1438. .logo {
  1439. display: flex;
  1440. align-items: center;
  1441. color: #fff;
  1442. .slipWrap_logo {
  1443. display: block;
  1444. width: 20px;
  1445. height: 20px;
  1446. border-radius: 50%;
  1447. margin-right: 6px;
  1448. }
  1449. }
  1450. .address {
  1451. font-size: 14px;
  1452. color: #999;
  1453. margin-top: 10px;
  1454. }
  1455. }
  1456. .current_prompt {
  1457. background: #171717;
  1458. border-radius: 8px;
  1459. padding: 20px 22px 10px;
  1460. margin: 30px 0 10px;
  1461. .price {
  1462. margin-bottom: 10px;
  1463. color: #ffffff;
  1464. .text {
  1465. font-size: 12px;
  1466. font-weight: bold;
  1467. }
  1468. .opppsite {
  1469. height: 10px;
  1470. width: 10px;
  1471. }
  1472. }
  1473. .tips {
  1474. display: flex;
  1475. justify-content: space-between;
  1476. font-size: 12px;
  1477. color: #ffffff;
  1478. margin-bottom: 10px;
  1479. .subtitle {
  1480. color: #ffffff;
  1481. }
  1482. .special_color {
  1483. color: #ffd245;
  1484. }
  1485. .special {
  1486. text-align: right;
  1487. }
  1488. }
  1489. }
  1490. .data_sheet {
  1491. }
  1492. </style>