UNPKG

sdk-utils

Version:

TEST TEST

463 lines (455 loc) 14.4 kB
import Web3 from "web3"; export var web3: Web3; import { ERC20 } from "./lib_abi"; import walletlink from 'walletlink'; import { BigNumber } from "bignumber.js"; import { Contract } from "web3-eth-contract"; import { chainIdDict, userInfo } from "./lib_config"; import WalletConnectProvider from "@walletconnect/web3-provider"; BigNumber.config({ ROUNDING_MODE: 1 }); BigNumber.config({ EXPONENTIAL_AT: 1e+9 }); const MAXNUM = (9999 * 99999 * 100000).toString(); /** * 大数转常数 * @param number 大数 * @param decimals 精度(可选) * @returns string */ export function convertBigNumberToNormal(number: string, decimals = 18) { let result = new BigNumber(number).dividedBy(new BigNumber(Math.pow(10, decimals))); return result.toFixed(10); } /** * 常数转大数 * @param number 常数 * @param decimals 精度(选填) * @param fix 截取(选填) * @returns string */ export function convertNormalToBigNumber(number: string, decimals = 18, fix = 0) { return new BigNumber(number).multipliedBy(new BigNumber(Math.pow(10, decimals))).minus(fix).toFixed(0); } /** * calculatePercentage * @param numerator x * @param denominator y * @returns string */ export function calculatePercentage(numerator: string, denominator: string) { return new BigNumber(numerator) .dividedBy(new BigNumber(denominator)) .toFixed(); } /** * multipliedBy * @param number1 x * @param number2 y * @returns string */ export function calculateMultiplied(number1: string, number2: string) { return new BigNumber(number1).multipliedBy(new BigNumber(number2)).toFixed(0); } /** * minus * @param number1 x * @param number2 y * @returns string */ export function minusBigNumber(number1: string, number2: string) { return new BigNumber(number1).minus(new BigNumber(number2)).toFixed(0); } /** * 加 x+y * @param number1 x * @param number2 y * @returns string */ export function add(number1: string, number2: string) { return new BigNumber(number1).plus(new BigNumber(number2)).toFixed(10); } /** * 减 x-y * @param number1 x * @param number2 y * @returns string */ export function sub(number1: string, number2: string) { return new BigNumber(number1).minus(new BigNumber(number2)).toFixed(10); } /** * 乘 x*y * @param number1 x * @param number2 y * @returns string */ export function mul(number1: string, number2: string) { return new BigNumber(number1).times(new BigNumber(number2)).toFixed(10); } /** * 除 x/y * @param number1 x * @param number2 y * @returns string */ export function div(number1: string, number2: string) { return new BigNumber(number1).div(new BigNumber(number2)).toFixed(10); } /** * deadline * @param delay time * @returns timestemp */ export function getDeadLine(delay: number) { return Math.floor(new Date().getTime() / 1000 + 60 * delay); } export const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms)); interface DictObject { [key: string]: string; } /** * 通过value找key * @param obj 对象 * @param value value * @param compare 比较(可选) * @returns key */ export function findToken(obj: DictObject, value: string, compare = (a: string, b: string) => a.toLowerCase() === b.toLowerCase()) { return Object.keys(obj).find((k) => compare(obj[k], value)); } /** * 判断是否为以太坊地址 * @param token_address 地址 * @returns bool */ export async function isETHAddress(token_address: string) { try { var code = await web3.eth.getCode(token_address); if (code === "0x") { return true; } else { return false; } } catch (e) { return false; } } /** * 查币的余额 * @param token_address 币地址 * @returns 余额 常数 */ export async function getBalance(token_address: string) { let tokenContract = new web3.eth.Contract(ERC20, token_address); let balance = await tokenContract.methods.balanceOf(userInfo.account).call(); return convertBigNumberToNormal(balance, await getDecimal(token_address)); } /** * 转账 * @param token_address 币地址 * @param to_address 收款地址 * @param amount 数量 常数 * @param callback 回调 */ export async function transfer(token_address: string, to_address: string, amount: string, callback: (code: number, hash: string) => void) { let tokenContract = new web3.eth.Contract(ERC20, token_address); let bigAmount = convertNormalToBigNumber(amount, await getDecimal(token_address)); executeContract(tokenContract, "transfer", 0, [to_address, bigAmount], callback); } /** * 从**转账 * @param token_address 币的地址 * @param from_address 出账地址 * @param to_address 入账地址 * @param amount 数量 常数 * @param callback 回调 */ export async function transferFrom(token_address: string, from_address: string, to_address: string, amount: string, callback: (code: number, hash: string) => void) { let tokenContract = new web3.eth.Contract(ERC20, token_address); let bigAmount = convertNormalToBigNumber(amount, await getDecimal(token_address)); executeContract(tokenContract, "transferFrom", 0, [from_address, to_address, bigAmount], callback); } /** * 获取币的精度 * @param token_address * @returns */ export async function getDecimal(token_address: string) { let tokenContract = new web3.eth.Contract(ERC20, token_address); let decimal = await tokenContract.methods.decimals().call(); return decimal; } /** * approve Token * @param token_address 币地址 * @param destina_address 目标地址 * @param callback 回调 */ export async function approveToken(token_address: string, destina_address: string, callback: (code: number, hash: string) => void) { let tokenContract = new web3.eth.Contract(ERC20, token_address); let bigAmount = convertNormalToBigNumber("500000000000", await getDecimal(token_address)); executeContract(tokenContract, "approve", 0, [destina_address, bigAmount], callback); } /** * 获取授权额度 * @param token_address * @param destina_address * @returns */ export async function getAllowance(token_address: string, destina_address: string) { let tokenContract = new web3.eth.Contract(ERC20, token_address); let allowance = await tokenContract.methods.allowance(userInfo.account, destina_address).call(); return convertBigNumberToNormal(allowance, await getDecimal(token_address)); } /** * 执行合约 * @param contract 合约实例 * @param methodName 方法 * @param value value * @param params 参数 * @param callback 回调 */ export function executeContract(contract: Contract, methodName: string, value: number, params: any, callback: (code: number, hash: string) => void) { contract.methods[methodName](...params) .send({ from: userInfo.account, value: value }) .on("transactionHash", function (hash: string) { callback(0, hash); }) .on("confirmation", function (confirmationNumber: number, receipt: any) { if (confirmationNumber === 1) { callback(1, receipt.transactionHash); } }) .on("error", function (error: any, message: any) { if (message && message.transactionHash) { callback(3, message.transactionHash); } else { callback(2, error.message); } }); } let walletDisconnectTimer: any; var provider: WalletConnectProvider; var walletLink: walletlink; const coinbaseRpc = "https://jsonrpc.maiziqianbao.net/"; /** * 链接钱包 * @param walletName 钱包的名字小写 * @param callback * @returns */ export async function connect(walletName: "walletconnect" | "metamask" | "huobiwallet" | "mathwallet" | "tokenpocket" | "coinbasewallet", callback: (data: { account: string; chainID: number; chain: string, message: string; }) => void) { let resMsg = { account: "", chainID: 0, chain: "", message: "success", }; try { if (walletName === "walletconnect") { provider = new WalletConnectProvider({ rpc: { 1: "https://jsonrpc.maiziqianbao.net/", 56: 'https://bsc-dataseed.binance.org/', }, }); await provider.enable(); //@ts-ignore web3 = new Web3(provider); userInfo.account = provider.accounts[0].toLowerCase(); userInfo.chainID = await web3.eth.getChainId() as typeof userInfo.chainID; resMsg.account = userInfo.account; resMsg.chain = chainIdDict[userInfo.chainID]; resMsg.message = "success"; provider.on("accountsChanged", (accounts: string[]) => { userInfo.account = accounts[0].toLowerCase(); callback({ account: userInfo.account, chainID: userInfo.chainID, chain: chainIdDict[userInfo.chainID], message: "accountsChanged", }); }); provider.on("chainChanged", async (chainId: number) => { userInfo.chainID = await web3.eth.getChainId() as typeof userInfo.chainID; callback({ account: userInfo.account, chainID: userInfo.chainID, chain: chainIdDict[userInfo.chainID], message: "chainChanged", }); }); provider.on("disconnect", (code: number, reason: string) => { if (walletDisconnectTimer !== null) clearTimeout(walletDisconnectTimer) walletDisconnectTimer = setTimeout(() => { walletDisconnectTimer = null; if (code) { userInfo.account = ""; userInfo.chainID = 1; userInfo.chain = "Ethereum"; callback({ account: "", chainID: 1, chain: "", message: "disconnect", }) } }, 300); }) } else if (walletName === "coinbasewallet") { walletLink = new walletlink({ appName: "Multiple", appLogoUrl: "https://avatars.githubusercontent.com/u/23645629?s=48&v=4", darkMode: false }) let _ethereum = walletLink.makeWeb3Provider(coinbaseRpc, 1); let accounts = await _ethereum.enable(); web3 = new Web3(_ethereum); userInfo.account = accounts[0].toLocaleLowerCase(); userInfo.chainID = 1; userInfo.chain = "Ethereum"; resMsg.account = userInfo.account; resMsg.chainID = userInfo.chainID; resMsg.chain = userInfo.chain; _ethereum.on("disconnect", (code: number, reason: string) => { if (code) { userInfo.account = ""; userInfo.chainID = 1; userInfo.chain = "Ethereum"; callback({ account: "", chainID: 1, chain: "", message: "disconnect", }) } }) } else { //@ts-ignore let _ethereum = window["ethereum"]; if (!_ethereum) { resMsg.message = "Check your wallet!"; return resMsg; } let accounts = await _ethereum.enable(); web3 = new Web3(_ethereum); userInfo.account = accounts[0].toLocaleLowerCase(); userInfo.chainID = await web3.eth.getChainId() as typeof userInfo.chainID; userInfo.chain = chainIdDict[userInfo.chainID] as typeof userInfo.chain; resMsg.account = userInfo.account; resMsg.chainID = userInfo.chainID; resMsg.chain = userInfo.chain; _ethereum.on("accountsChanged", (accounts: string[]) => { userInfo.account = accounts[0].toLowerCase(); callback({ account: userInfo.account, chainID: userInfo.chainID, chain: chainIdDict[userInfo.chainID], message: "accountsChanged", }); }); _ethereum.on("chainChanged", async () => { userInfo.chainID = await web3.eth.getChainId() as typeof userInfo.chainID; callback({ account: userInfo.account, chainID: userInfo.chainID, chain: chainIdDict[userInfo.chainID], message: "chainChanged", }); }); } } catch (e) { resMsg.message = e.message; } return resMsg; } /** * 一键添加切换BSC/HECO智能链 * @param chainName "BSC" | "HECO" * @returns "" 无返回 */ export async function changeMetamaskChain(chainName: "PLAYGROUND" | "HECO") { //@ts-ignore let _ethereum = window['ethereum']; if (!_ethereum || !_ethereum.isMetaMask) { return; } const PLAYGROUNDinfo = [{ chainId: '0x150', chainName: 'Multiple Testnet', nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 }, rpcUrls: ['https://testnet.multiple.fi'], blockExplorerUrls: ['https://testnet.multiple.fi'], }]; const HECOinfo = [{ chainId: '0x80', chainName: 'HECO Mainnet', nativeCurrency: { name: 'HT', symbol: 'HT', decimals: 18 }, rpcUrls: ['https://http-mainnet.hecochain.com/'], blockExplorerUrls: ['https://hecoinfo.com/'], }]; let data = chainName == "PLAYGROUND" ? PLAYGROUNDinfo : HECOinfo; await _ethereum.request({ method: 'wallet_addEthereumChain', params: data }).catch() } /** * 退出 * @returns */ export function logout() { userInfo.account = ""; userInfo.chainID = 1; userInfo.chain = "Ethereum"; provider.disconnect(); walletLink.disconnect(); return { account: "", chainID: 1, chain: "", message: "logout", } } //全局log let isTrace = false; /** * 删除数字末尾多余的0 * @param str * @returns 字符串型的数字 */ export function toPrecision(str: string) { if (!Boolean(str)) return '0'; if (!(/^[0-9.]+$/g.test(str))) return '0'; while (str.includes(".") && (str.endsWith('.') || str.endsWith('0'))) { str = str.slice(0, -1) } return str } export class Trace { public constructor() { } /** *设置log的开关 * @param b bool */ public static setTraceShow(b: boolean) { isTrace = b; } /** * log的内容 * @param message log提示 * @param optionalParams log内容 */ public static trace(message?: string, ...optionalParams: any[]) { if (isTrace) { console.log(message, ...optionalParams); } } }