From 939ae1bd09e3c2caa30aae8e04bff520ff1027fc Mon Sep 17 00:00:00 2001 From: koko37 Date: Fri, 22 Nov 2024 14:37:30 +0800 Subject: [PATCH] refactor trx api calls --- src/components/NetworkSelector.jsx | 12 +- src/contexts/Store.jsx | 7 +- src/lib/account/evm.js | 29 +--- src/lib/account/tron.js | 20 +-- src/lib/conf.js | 75 +++++----- src/lib/erc20.json | 224 +---------------------------- src/pages/Signin/index.jsx | 33 +---- 7 files changed, 67 insertions(+), 333 deletions(-) diff --git a/src/components/NetworkSelector.jsx b/src/components/NetworkSelector.jsx index 905610c..e93217e 100644 --- a/src/components/NetworkSelector.jsx +++ b/src/components/NetworkSelector.jsx @@ -9,13 +9,11 @@ const NetworkSelector = ({ network, chainId, updateNetwork }) => { return ( diff --git a/src/contexts/Store.jsx b/src/contexts/Store.jsx index 67ba8ca..e348ab0 100644 --- a/src/contexts/Store.jsx +++ b/src/contexts/Store.jsx @@ -13,7 +13,6 @@ export const StoreContext = createContext({ connectivity: true, password: "", passcode: "", - salt: "", hash: "", setup: (p, pc, s, h) => {}, reset: () => {}, @@ -49,7 +48,6 @@ const StoreProvider = ({ children }) => { // key parts const [password, setPassword] = useState(""); const [passcode, setPasscode] = useState(""); - const [salt, setSalt] = useState(""); const [hash, setHash] = useState(""); // network related @@ -118,7 +116,6 @@ const StoreProvider = ({ children }) => { const reset = () => { setPassword(""); setPasscode(""); - setSalt(""); setHash(""); setNetwork(DEFAULT_NETWORK); @@ -136,10 +133,9 @@ const StoreProvider = ({ children }) => { selectToken(""); }; - const setup = (pw, pc, s, h) => { + const setup = (pw, pc, h) => { setPassword(pw); setPasscode(pc); - setSalt(s); setHash(h); }; @@ -172,7 +168,6 @@ const StoreProvider = ({ children }) => { connectivity, password, passcode, - salt, hash, reset, setup, diff --git a/src/lib/account/evm.js b/src/lib/account/evm.js index 8ec9a0e..993b93a 100644 --- a/src/lib/account/evm.js +++ b/src/lib/account/evm.js @@ -9,6 +9,7 @@ import IERC20 from "@mybucks/lib/erc20.json"; class EvmAccount { network = NETWORK.EVM; chainId = null; + networkInfo = null; signer = null; account = null; @@ -26,7 +27,8 @@ class EvmAccount { constructor(hashKey, chainId) { this.chainId = chainId; - this.provider = new ethers.JsonRpcProvider(EVM_NETWORKS[chainId].provider); + this.networkInfo = EVM_NETWORKS.find((n) => n.chainId === chainId); + this.provider = new ethers.JsonRpcProvider(this.networkInfo.provider); this.signer = getEvmPrivateKey(hashKey); this.account = new ethers.Wallet(this.signer, this.provider); @@ -42,15 +44,15 @@ class EvmAccount { } linkOfAddress(address) { - return EVM_NETWORKS[this.chainId].scanner + "/address/" + address; + return this.networkInfo.scanner + "/address/" + address; } linkOfContract(address) { - return EVM_NETWORKS[this.chainId].scanner + "/address/" + address + "#code"; + return this.networkInfo.scanner + "/address/" + address + "#code"; } linkOfTransaction(txn) { - return EVM_NETWORKS[this.chainId].scanner + "/tx/" + txn; + return this.networkInfo.scanner + "/tx/" + txn; } async getNetworkStatus() { @@ -147,25 +149,6 @@ class EvmAccount { } } - /* - async nativeCurrency() { - const balance = await this.provider.getBalance(this.address); - return ethers.formatEther(balance); - } - - async balanceOfErc20(token) { - const erc20 = new Contract(token, IERC20.abi, this.provider); - const result = await erc20.balanceOf(this.account.address); - return result; - } - - async transferErc20(token, to, amount, gasPrice = null, gasLimit = null) { - const erc20 = new Contract(token, IERC20.abi, this.provider); - const tx = await erc20.connect(this.account).transfer(to, amount); - await tx.wait(); - } -*/ - /** * * @param {*} token contract address or null(for native currency) diff --git a/src/lib/account/tron.js b/src/lib/account/tron.js index 3d47001..70297ba 100644 --- a/src/lib/account/tron.js +++ b/src/lib/account/tron.js @@ -90,18 +90,18 @@ class TronAccount { // [TODO] Now it only returns balance of TRX and USDT async queryBalances() { const nativeTokenName = "TRX"; - // get TRX balance - const trxRawBalance = await this.tronweb.trx.getBalance(this.address); - const nativeTokenBalance = this.tronweb.fromSun(trxRawBalance); - const nativeTokenPrice = await queryPrice(nativeTokenName); - - // balance of TRC20 USDT const usdtContract = await this.tronweb.contract().at(TRC20_USDT_ADDRESS); - const usdtRawBalance = await usdtContract.methods - .balanceOf(this.address) - .call(); + + const [trxRawBalance, nativeTokenPrice, usdtRawBalance, usdtPrice] = + await Promise.all([ + this.tronweb.trx.getBalance(this.address), + queryPrice(nativeTokenName), + usdtContract.methods.balanceOf(this.address).call(), + queryPrice("USDT"), + ]); + + const nativeTokenBalance = this.tronweb.fromSun(trxRawBalance); const usdtBalance = this.tronweb.fromSun(usdtRawBalance); - const usdtPrice = await queryPrice("USDT"); return [ nativeTokenName, diff --git a/src/lib/conf.js b/src/lib/conf.js index 4b0ad72..31d9feb 100644 --- a/src/lib/conf.js +++ b/src/lib/conf.js @@ -1,6 +1,16 @@ +import { Buffer } from "buffer"; import { ethers } from "ethers"; +import { scrypt } from "scrypt-js"; + const abi = new ethers.AbiCoder(); +export const PASSWORD_MIN_LENGTH = 12; +export const PASSWORD_MAX_LENGTH = 128; +export const PASSCODE_MIN_LENGTH = 6; +export const PASSCODE_MAX_LENGTH = 16; + +export const PASSCODE_MAX_TRY = 3; + /** * [CRITICAL] DON'T CHANGE FOREVER!!! * Reference: @@ -12,15 +22,26 @@ export const HASH_OPTIONS = { p: import.meta.env.DEV ? 1 : 5, // parallelization parameter keyLen: 64, }; -export const PASSWORD_MIN_LENGTH = 12; -export const PASSWORD_MAX_LENGTH = 128; -export const PASSCODE_MIN_LENGTH = 6; -export const PASSCODE_MAX_LENGTH = 16; -export const PASSCODE_MAX_TRY = 3; +export const generateHash = async (password, passcode, cb = () => {}) => { + const salt = `${password.slice(-4)}${passcode}`; + + const passwordBuffer = Buffer.from(password); + const saltBuffer = Buffer.from(salt); + + const hashBuffer = await scrypt( + passwordBuffer, + saltBuffer, + HASH_OPTIONS.N, + HASH_OPTIONS.r, + HASH_OPTIONS.p, + HASH_OPTIONS.keyLen, + cb + ); + + return Buffer.from(hashBuffer).toString("hex"); +}; -export const generateSalt = (password, passcode) => - `${password.slice(-4)}${passcode}`; export const getEvmPrivateKey = (h) => ethers.keccak256(abi.encode(["string"], [h])); @@ -32,8 +53,8 @@ export const NETWORK = Object.freeze({ export const DEFAULT_NETWORK = NETWORK.EVM; export const DEFAULT_CHAIN_ID = 1; -export const EVM_NETWORKS = { - 1: { +export const EVM_NETWORKS = [ + { chainId: 1, name: "ethereum", label: "Ethereum", @@ -42,7 +63,7 @@ export const EVM_NETWORKS = { scanner: "https://etherscan.io", order: 1, }, - 137: { + { chainId: 137, name: "polygon", label: "Polygon", @@ -52,7 +73,7 @@ export const EVM_NETWORKS = { scanner: "https://polygonscan.com", order: 2, }, - 42161: { + { chainId: 42161, name: "arbitrum", label: "Arbitrum", @@ -62,7 +83,7 @@ export const EVM_NETWORKS = { scanner: "https://arbiscan.io", order: 3, }, - 10: { + { chainId: 10, name: "optimism", label: "Optimism", @@ -72,7 +93,7 @@ export const EVM_NETWORKS = { scanner: "https://optimistic.etherscan.io", order: 4, }, - 56: { + { chainId: 56, name: "bsc", label: "BNB Chain", @@ -80,7 +101,7 @@ export const EVM_NETWORKS = { scanner: "https://bscscan.com", order: 5, }, - 43114: { + { chainId: 43114, name: "avalanche", label: "Avalanche", @@ -90,27 +111,7 @@ export const EVM_NETWORKS = { scanner: "https://snowtrace.io", order: 6, }, - 42220: { - chainId: 42220, - name: "celo", - label: "Celo", - provider: - "https://celo-mainnet.infura.io/v3/" + - import.meta.env.VITE_INFURA_API_KEY, - scanner: "https://celoscan.io", - order: 7, - }, - 59144: { - chainId: 59144, - name: "linea", - label: "Linea", - provider: - "https://linea-mainnet.infura.io/v3/" + - import.meta.env.VITE_INFURA_API_KEY, - scanner: "https://lineascan.build", - order: 8, - }, -}; +]; export const GAS_PRICE = Object.freeze({ HIGH: "high", @@ -129,8 +130,8 @@ export const gasMultiplier = (option) => // 15 minutes, after this period, wallet will be locked. export const IDLE_DURATION = 900_000; -// in every 15 seconds, it refreshes gas price or network status -export const REFRESH_STATUS_DURATION = 15_000; +// in every 30 seconds, it refreshes gas price or network status +export const REFRESH_STATUS_DURATION = 30_000; // The hidden balances will be displayed as shown below export const BALANCE_PLACEHOLDER = "*****"; diff --git a/src/lib/erc20.json b/src/lib/erc20.json index 8237965..1d5ea44 100644 --- a/src/lib/erc20.json +++ b/src/lib/erc20.json @@ -1,227 +1,5 @@ { "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -276,4 +54,4 @@ "type": "function" } ] -} \ No newline at end of file +} diff --git a/src/pages/Signin/index.jsx b/src/pages/Signin/index.jsx index a41abfb..206b103 100644 --- a/src/pages/Signin/index.jsx +++ b/src/pages/Signin/index.jsx @@ -1,6 +1,4 @@ import { useContext, useMemo, useState } from "react"; -import { Buffer } from "buffer"; -import { scrypt } from "scrypt-js"; import styled from "styled-components"; import Button from "@mybucks/components/Button"; @@ -13,8 +11,7 @@ import Progress from "@mybucks/components/Progress"; import { H1 } from "@mybucks/components/Texts"; import { StoreContext } from "@mybucks/contexts/Store"; import { - generateSalt, - HASH_OPTIONS, + generateHash, PASSCODE_MAX_LENGTH, PASSCODE_MIN_LENGTH, PASSWORD_MAX_LENGTH, @@ -141,10 +138,6 @@ const SignIn = () => { const [disabled, setDisabled] = useState(false); const [progress, setProgress] = useState(0); - const salt = useMemo( - () => generateSalt(password, passcode), - [password, passcode] - ); const hasMinLengthPassword = useMemo( () => password.length >= PASSWORD_MIN_LENGTH, [password] @@ -187,25 +180,11 @@ const SignIn = () => { const onSubmit = async () => { setDisabled(true); - try { - const passwordBuffer = Buffer.from(password); - const saltBuffer = Buffer.from(salt); - const hashBuffer = await scrypt( - passwordBuffer, - saltBuffer, - HASH_OPTIONS.N, - HASH_OPTIONS.r, - HASH_OPTIONS.p, - HASH_OPTIONS.keyLen, - (p) => setProgress(Math.floor(p * 100)) - ); - const hashHex = Buffer.from(hashBuffer).toString("hex"); - setup(password, passcode, salt, hashHex); - } catch (e) { - console.error("Error while setting up account ..."); - } finally { - setDisabled(false); - } + const hash = await generateHash(password, passcode, (p) => + setProgress(Math.floor(p * 100)) + ); + setup(password, passcode, hash); + setDisabled(false); }; const onKeyDown = (e) => {