UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

116 lines 4.82 kB
import { constants } from 'ethers'; import { BaseFee__factory, ERC20__factory, LinearFee__factory, RoutingFee__factory, } from '@hyperlane-xyz/core'; import { assert } from '@hyperlane-xyz/utils'; import { HyperlaneReader } from '../utils/HyperlaneReader.js'; import { OnchainTokenFeeType, TokenFeeType, onChainTypeToTokenFeeTypeMap, } from './types.js'; import { MAX_BPS, convertToBps } from './utils.js'; export class EvmTokenFeeReader extends HyperlaneReader { multiProvider; chain; constructor(multiProvider, chain) { super(multiProvider, chain); this.multiProvider = multiProvider; this.chain = chain; } async deriveTokenFeeConfig(params) { const { address, routingDestinations } = params; const tokenFee = BaseFee__factory.connect(address, this.provider); let derivedConfig; const onchainFeeType = await tokenFee.feeType(); switch (onchainFeeType) { case OnchainTokenFeeType.LinearFee: derivedConfig = await this.deriveLinearFeeConfig(address); break; case OnchainTokenFeeType.ProgressiveFee: derivedConfig = await this.deriveProgressiveFeeConfig(address); break; case OnchainTokenFeeType.RegressiveFee: derivedConfig = await this.deriveRegressiveFeeConfig(address); break; case OnchainTokenFeeType.RoutingFee: assert(routingDestinations, `routingDestinations required for ${onChainTypeToTokenFeeTypeMap[onchainFeeType]}`); derivedConfig = await this.deriveRoutingFeeConfig({ address, routingDestinations, }); break; default: throw new Error(`Unsupported token fee type: ${onchainFeeType}`); } return derivedConfig; } async deriveLinearFeeConfig(address) { const tokenFee = LinearFee__factory.connect(address, this.provider); const [token, owner, maxFee, halfAmount] = await Promise.all([ tokenFee.token(), tokenFee.owner(), tokenFee.maxFee(), tokenFee.halfAmount(), ]); const maxFeeBn = BigInt(maxFee.toString()); const halfAmountBn = BigInt(halfAmount.toString()); const bps = convertToBps(maxFeeBn, halfAmountBn); return { type: TokenFeeType.LinearFee, maxFee: maxFeeBn, halfAmount: halfAmountBn, address, bps, token, owner, }; } async deriveProgressiveFeeConfig(_address) { throw new Error('Not implemented'); } async deriveRegressiveFeeConfig(_address) { throw new Error('Not implemented'); } async deriveRoutingFeeConfig(params) { const { address, routingDestinations } = params; const routingFee = RoutingFee__factory.connect(address, this.provider); const [token, owner, maxFee, halfAmount] = await Promise.all([ routingFee.token(), routingFee.owner(), routingFee.maxFee(), routingFee.halfAmount(), ]); const maxFeeBn = BigInt(maxFee.toString()); const halfAmountBn = BigInt(halfAmount.toString()); const feeContracts = {}; if (routingDestinations) await Promise.all(routingDestinations.map(async (destination) => { const subFeeAddress = await routingFee.feeContracts(destination); if (subFeeAddress === constants.AddressZero) return; const chainName = this.multiProvider.getChainName(destination); feeContracts[chainName] = await this.deriveTokenFeeConfig({ address: subFeeAddress, // Currently, it's not possible to configure nested routing fees domains, // but we should not expect that to exist routingDestinations, }); })); return { type: TokenFeeType.RoutingFee, maxFee: maxFeeBn, halfAmount: halfAmountBn, address, token, owner, feeContracts, }; } async convertFromBps(bps, tokenAddress) { // Assume maxFee is uint256.max / token.totalSupply const token = ERC20__factory.connect(tokenAddress, this.provider); const totalSupplyBn = await token.totalSupply(); const maxFee = BigInt(constants.MaxUint256.div(totalSupplyBn).toString()); const halfAmount = ((maxFee / 2n) * MAX_BPS) / bps; return { maxFee, halfAmount, }; } } //# sourceMappingURL=EvmTokenFeeReader.js.map