You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
4.9 KiB

1 year ago
  1. import '~/styles/recharge.scss'
  2. import { observer } from 'mobx-react'
  3. import store from '../../store'
  4. import { useMemo, useRef, useState } from 'react'
  5. import { useRouter } from '../../hooks/useRouter'
  6. import { ethers } from 'ethers'
  7. import { Button, Toast } from 'react-vant'
  8. import { switchNetWork } from '../../utils'
  9. import { IERC20__factory } from '../../contract/IERC20__factory'
  10. import { toWei } from '../../utils/wei'
  11. import BackBar from '~/components/BackBar'
  12. const Recharge = () => {
  13. const { coinIndex, coinList, userInfo } = store.state
  14. const { push } = useRouter()
  15. const inputRef = useRef<HTMLInputElement>(null);
  16. const currentCoin = useMemo(() => coinList[coinIndex], [coinIndex, coinList])
  17. const [loading, setLoading] = useState(false);
  18. const provider = useMemo(() => {
  19. if (window.ethereum) {
  20. return new ethers.providers.Web3Provider(window.ethereum)
  21. };
  22. return null;
  23. }, []);
  24. const handleTransferParams = async () => {
  25. let from = window.ethereum.selectedAddress;
  26. let toAddress = userInfo.deposit_address;
  27. let contractAddress = currentCoin.address;
  28. if (!provider) {
  29. Toast.info('請檢查網絡是否正常');
  30. return -1
  31. }
  32. if (!inputRef.current) {
  33. Toast.info('請稍後重試');
  34. return -1
  35. }
  36. let value = inputRef.current.value;
  37. if (!value) {
  38. Toast.info('請輸入數量');
  39. return -1
  40. }
  41. let _contract = IERC20__factory.connect(contractAddress as string, provider);
  42. // 判断 gas 余额
  43. let eth = await provider.getBalance(from)
  44. const needGas = toWei("0.01")
  45. if (eth.lt(needGas)) {
  46. Toast.info('Gas 費不足 0.01');
  47. return -1
  48. }
  49. // 判断代币余额
  50. let balanceToken = await _contract.balanceOf(from)
  51. let currToken = toWei(value)
  52. if (balanceToken.lt(currToken)) {
  53. Toast.info('Token 餘額不足');
  54. return -1
  55. }
  56. let { to, data } = await _contract.populateTransaction.transfer(toAddress, toWei(value));
  57. let requestData = {
  58. from,
  59. to,
  60. data,
  61. value: '0x0'
  62. };
  63. return requestData;
  64. };
  65. const handleExchange = async () => {
  66. if (!provider || loading) return;
  67. let value = inputRef.current?.value;
  68. if (!value) {
  69. Toast.info('請輸入數量');
  70. return;
  71. };
  72. setLoading(true);
  73. try {
  74. let isNode = await switchNetWork();
  75. if (!isNode) return;
  76. let data = await handleTransferParams();
  77. if (data == -1) {
  78. // Toast.info('请检查网络是否正常');
  79. setLoading(false);
  80. return;
  81. }
  82. let txHash = await window.ethereum.request({
  83. method: 'eth_sendTransaction',
  84. params: [
  85. data
  86. ]
  87. });
  88. let tx = await provider.getTransaction(txHash);
  89. let { status } = await tx.wait();
  90. setLoading(false);
  91. if (status === 1) {
  92. Toast.success('充值成功');
  93. setTimeout(() => {
  94. push(-1)
  95. }, 1000)
  96. } else {
  97. Toast.fail('充值失敗');
  98. }
  99. } catch (error) {
  100. setLoading(false);
  101. }
  102. };
  103. return (
  104. <div className='recharge plr-2'>
  105. <BackBar title='充值' />
  106. <div className='container row-center mt-2'>
  107. <div className='box plr-2 row-between' onClick={() => push('/choose')}>
  108. <div className='row-items'>
  109. {
  110. currentCoin && <img src={require(`~/assets/${currentCoin.symbol}.png`)} alt="" />
  111. }
  112. <div className='fz-wb-550 ml-1'>{currentCoin && currentCoin.symbol}</div>
  113. </div>
  114. <div>
  115. <i className='iconfont icon-arrow-right-bold'></i>
  116. </div>
  117. </div>
  118. <div className='box-img row-center'>
  119. <i className='iconfont icon-datijilu fz-22'></i>
  120. </div>
  121. </div>
  122. <div className='mt-2'>
  123. <div className='white-bg p-2 r-1'>
  124. <div className='fz-14'></div>
  125. <div className='mt-1 fz-wb-550'>BNB Smart Chain(BEP20)</div>
  126. </div>
  127. <div className='mt-2 white-bg r-1 p-2'>
  128. <div className='fz-14' style={{ color: '#828284' }}></div>
  129. <div className='mt-1 input-box plr-1'>
  130. <input type="number" placeholder='請輸入數量' ref={inputRef} />
  131. <div className='row-items'>
  132. {
  133. currentCoin && <img src={require(`~/assets/${currentCoin.symbol}.png`)} alt="" />
  134. }
  135. <div className='ml-5px'>{currentCoin && currentCoin.symbol}</div>
  136. {/* <div className='primary-color ml-5px'>最大</div> */}
  137. </div>
  138. </div>
  139. </div>
  140. <div className='mt-3'>
  141. <Button className='button' onClick={handleExchange} loading={loading} loadingType="ball" ></Button>
  142. </div>
  143. </div>
  144. </div>
  145. )
  146. }
  147. export default observer(Recharge)