UNPKG

@kaiachain/kss-bridges-celer

Version:
226 lines (202 loc) 7.03 kB
import { BigNumber, Contract, ethers, utils } from "ethers" import { TransactionResponse } from "@ethersproject/abstract-provider" import { parseUnits } from "@ethersproject/units" import { safeParseUnits } from "celer-web-utils/lib/format" import { ITransferConfigs, ITransferObject } from "../constants/type" import { getSigner } from "./constant" import ERC20ABI from "../contract/abi/pegged/tokens/ERC20Permit/SingleBridgeTokenPermit.sol/SingleBridgeTokenPermit.json" import { Token } from "../constants/type" const tokenInterface = new utils.Interface(ERC20ABI.abi) export const getBridgeContractAddress = (transferConfigs: ITransferConfigs, chainId: number) => { return transferConfigs.chains.find(chain => chain.id === chainId)?.contract_addr } export const getTransferId = ( address: string, tokenAddress?: string, value?: BigNumber, toChainId?: number, nonce?: number, fromChainId?: number ) => { return utils.solidityKeccak256( ["address", "address", "address", "uint256", "uint64", "uint64", "uint64"], [ address, address, tokenAddress, value?.toString(), toChainId?.toString(), nonce?.toString(), fromChainId?.toString(), ] ) } export const transactor = async (tx: any, rpcURL: string, privateKey: string): Promise<ethers.ContractTransaction> => { let result: TransactionResponse; if (tx instanceof Promise) { result = await tx; } else { if (!tx.gasPrice) { tx.gasPrice = parseUnits("4.1", "gwei") } if (!tx.gasLimit) { tx.gasLimit = BigNumber.from(120000) } result = await getSigner(rpcURL, privateKey).sendTransaction(tx); } return result!; } export const getTransferObject = ( transferConfigs: ITransferConfigs, srcChainId: number, dstChainId: number, tokenSymbol: string, transferValue: string ): ITransferObject => { const transferObject: ITransferObject = {} const transferToken = transferConfigs.chain_token[`${srcChainId}`]?.token.find( ({ token }) => token.symbol === tokenSymbol ) const fromChain = transferConfigs.chains.find(({ id }) => id === srcChainId) const toChain = transferConfigs.chains.find(({ id }) => id === dstChainId) const value = safeParseUnits(transferValue, transferToken?.token?.decimal ?? 18) const nonce = new Date().getTime() Object.assign(transferObject, { transferToken, fromChain, toChain, value, nonce }) return transferObject } export const getPegConfig = ( transferConfigs: ITransferConfigs, srcChainId: number, dstChainId: number, tokenSymbol: string ) => { const depositConfigs = transferConfigs.pegged_pair_configs.filter( (e) => e.org_chain_id === srcChainId && e.pegged_chain_id === dstChainId && e.org_token.token.symbol === tokenSymbol ) if (depositConfigs.length) { return depositConfigs[0] } const burnConfigs = transferConfigs.pegged_pair_configs.filter( (e) => e.org_chain_id === dstChainId && e.pegged_chain_id === srcChainId && e.org_token.token.symbol === tokenSymbol ) if (burnConfigs.length) { return burnConfigs[0] } return } const isNonEVMChain = (chainId: number) => { if ( chainId === 12340001 || chainId === 12340002 || chainId === 999999998 || chainId === 999999999 ) { return true } return false } const getTokenBalanceAddress = ( originalAddress: string, fromChainId: number | undefined = undefined, tokenSymbol: string | undefined = undefined, peggedPairs: Array<any> | undefined = undefined ) => { if (!fromChainId || !tokenSymbol || !peggedPairs) { return originalAddress } const peggedTokens = peggedPairs?.filter((item) => { return ( item.pegged_chain_id === fromChainId && tokenSymbol === item.pegged_token.token.symbol ) }) if ( peggedTokens && peggedTokens.length > 0 && peggedTokens[0].canonical_token_contract_addr.length > 0 ) { return peggedTokens[0].canonical_token_contract_addr } if (isNonEVMChain(fromChainId)) { const nonEVMDeposit = peggedPairs?.find((peggedPairConfig) => { return ( peggedPairConfig.org_chain_id === fromChainId && peggedPairConfig.org_token.token.symbol === tokenSymbol ) }) if (nonEVMDeposit) { return nonEVMDeposit.pegged_token.token.address } const nonEVMBurn = peggedPairs?.find((peggedPairConfig) => { return ( peggedPairConfig.pegged_chain_id === fromChainId && peggedPairConfig.pegged_token.token.symbol === tokenSymbol ) }) if (nonEVMBurn) { return nonEVMBurn.org_token.token.address } } return originalAddress } export const getAllowance = async ( walletAddress: string, spenderAddress: string, originalAddress: string, fromChainId: number | undefined = undefined, tokenSymbol: string | undefined = undefined, rpcURL: string, peggedPairs: Array<any> | undefined = undefined ) => { const tokenAddress = getTokenBalanceAddress( originalAddress, fromChainId, tokenSymbol, peggedPairs ) const tokenContract = new Contract(tokenAddress, tokenInterface, getSigner(rpcURL)) const allowance = await tokenContract?.allowance(walletAddress, spenderAddress) return allowance } export const checkApprove = (allowance: BigNumber, amount: string, token?: Token, isNative?: boolean) : boolean => { /**Native token case */ if(isNative) { return false; } if (!allowance || allowance.isZero()) { return true } console.log("Allowance: "+allowance.toString()); console.log("Amount : "+safeParseUnits(amount || "0", token?.decimal ?? 18).toString()); try { const isGreatThanAllowance = safeParseUnits(amount || "0", token?.decimal ?? 18).gt( allowance ) return isGreatThanAllowance } catch { return true } } export const approve = async (spenderAddress: string, rpcURL: string, privateKey: string, token?: Token, amount?: string) => { if (!token) { return } try { const tokenContract = new Contract(token.address, tokenInterface, getSigner(rpcURL, privateKey)) const approveTx = await transactor( tokenContract.approve(spenderAddress, safeParseUnits(amount || "0", token?.decimal ?? 18), {gasLimit: 100000 }), rpcURL, privateKey ) await approveTx.wait() return approveTx } catch (e) { console.error(`-Failed to approve token. Error:`, e) return } }