UNPKG

@swapper-finance/sdk

Version:
140 lines (118 loc) 3.79 kB
import { ERC20Abi } from "@src/contractAbis"; import { Chain, TokenBalances } from "@src/models"; import { BigNumber, ethers } from "ethers"; export const IERC20 = new ethers.utils.Interface(ERC20Abi); export const getBalanceOf = async ( wallet: string, token: string, rpcUrl: string, ): Promise<string> => { const provider = ethers.getDefaultProvider(rpcUrl); if (token === ethers.constants.AddressZero) { return ethers.utils.formatEther(await provider.getBalance(wallet)); } const contract = new ethers.Contract(token, ERC20Abi, provider); return ethers.utils.formatUnits( await contract.balanceOf(wallet), await contract.decimals(), ); }; export const getAllowanceOf = async ( token: string, wallet: string, spender: string, rpcUrl: string, ): Promise<string> => { const provider = ethers.getDefaultProvider(rpcUrl); if (token === ethers.constants.AddressZero) { return ethers.constants.MaxUint256.toString(); } const contract = new ethers.Contract(token, ERC20Abi, provider); return ethers.utils.formatUnits( await contract.allowance(wallet, spender), await contract.decimals(), ); }; export const getNativeBalance = async ( chain: Chain, wallet: string, ): Promise<TokenBalances> => { const native = chain.tokens.find( ({ address }) => address.toLowerCase() === ethers.constants.AddressZero.toLowerCase(), ); if (native) { const provider = ethers.getDefaultProvider(chain.publicRpcUrls[0]); const balance = await provider.getBalance(wallet); return { [native.address]: balance, }; } return {}; }; /** * Calculate param's value offset within the encoded function's bytecode. * @param abi * @param funName * @param funParams * @param placeholderValue */ export const findPlaceholderIndex = ( abi: string, funName: string, // eslint-disable-next-line funParams: any[], placeholderValue: BigNumber, ) => { if ( funParams.flat(Infinity).filter((param) => param === placeholderValue) .length !== 1 ) { throw new Error("Random placeholder value must be provided and unique."); } const iface = new ethers.utils.Interface(abi); const functionFragment = iface.getFunction(funName); if (!functionFragment) { throw new Error(`Can't find function "${funName}" in provided ABI.`); } const encodedFunData = iface.encodeFunctionData(functionFragment, funParams); // Remove the 4-byte selector const paramData = encodedFunData.slice(10); // Split into 32-byte (64 hex characters) chunks const chunks: string[] = []; for (let i = 0; i < paramData.length; i += 64) { chunks.push(paramData.slice(i, i + 64)); } // Find the index of the chunk containing the random value const searchValue = placeholderValue.toHexString().slice(2).padStart(64, "0"); const result = chunks.findIndex((chunk) => chunk === searchValue); if (result === -1) { throw new Error("Randomized parameter not found in the encoded data."); } return result; }; export const getEventsFromReceipt = async ( receipt: ethers.providers.TransactionReceipt, abi: ethers.ContractInterface, rpcUrl: string, eventName: string, ) => { const contract = new ethers.Contract( receipt.to, abi, ethers.getDefaultProvider(rpcUrl), ); const eventSignature = contract.interface.getEvent(eventName).format(); return receipt.logs .filter((log) => log.topics[0] === ethers.utils.id(eventSignature)) .map((log) => contract.interface.parseLog(log)); }; export const trimTxHash = (hash: string, beginAndEndCharacters: number = 5) => { if (!hash) { return ""; } return `${hash?.substring(0, beginAndEndCharacters)}...${hash.substring( hash.length - beginAndEndCharacters, hash.length, )}`; };