UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

85 lines 4.58 kB
import { CrossCollateralRouter__factory, PredicateCrossCollateralRouterWrapper__factory, } from '@hyperlane-xyz/core'; import { addressToBytes32, assert, isAddressEvm, isZeroishAddress, } from '@hyperlane-xyz/utils'; import { EvmHypCollateralAdapter } from './EvmTokenAdapter.js'; /** * Adapter for CrossCollateralRouter routers. * Supports transferRemoteTo for both cross-chain and same-chain transfers. */ export class EvmHypCrossCollateralAdapter extends EvmHypCollateralAdapter { chainName; multiProvider; addresses; crossCollateralContract; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, { token: addresses.token }); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.crossCollateralContract = CrossCollateralRouter__factory.connect(addresses.token, this.getProvider()); } // ============ CrossCollateralRouter-specific methods ============ /** * Populate cross-chain transfer to a specific target router. */ async quoteTransferRemoteToRaw(params) { const recipientBytes32 = addressToBytes32(params.recipient); const targetRouterBytes32 = addressToBytes32(params.targetRouter); return this.crossCollateralContract.quoteTransferRemoteTo(params.destination, recipientBytes32, params.amount.toString(), targetRouterBytes32); } async populateTransferRemoteToTx(params) { const recipientBytes32 = addressToBytes32(params.recipient); const targetRouterBytes32 = addressToBytes32(params.targetRouter); const quote = params.interchainGas ?? (await this.quoteTransferRemoteToGas(params)); let nativeValue = !quote.igpQuote.addressOrDenom ? quote.igpQuote.amount : 0n; if (!quote.tokenFeeQuote?.addressOrDenom || isZeroishAddress(quote.tokenFeeQuote.addressOrDenom)) { nativeValue += quote.tokenFeeQuote?.amount ?? 0n; } const nativeGas = nativeValue.toString(); if (params.attestation) { const predicateWrapperAddress = await this.getPredicateWrapperAddress(); if (!predicateWrapperAddress) { throw new Error('Attestation provided but no PredicateCrossCollateralRouterWrapper detected on warp route hook.'); } const predicateWrapper = PredicateCrossCollateralRouterWrapper__factory.connect(predicateWrapperAddress, this.getProvider()); const contractAttestation = { uuid: params.attestation.uuid, expiration: params.attestation.expiration, attester: params.attestation.attester, signature: params.attestation.signature, }; return predicateWrapper.populateTransaction.transferRemoteToWithAttestation(contractAttestation, params.destination, recipientBytes32, params.amount.toString(), targetRouterBytes32, { value: nativeGas }); } return this.crossCollateralContract.populateTransaction.transferRemoteTo(params.destination, recipientBytes32, params.amount.toString(), targetRouterBytes32, { value: nativeGas }); } /** * Quote fees for transferRemoteTo. */ async quoteTransferRemoteToGas(params) { const quotes = await this.quoteTransferRemoteToRaw(params); assert(quotes.length >= 3, 'quoteTransferRemoteTo returned incomplete quote set'); assert(isZeroishAddress(quotes[1].token) || isAddressEvm(quotes[1].token), 'quoteTransferRemoteTo returned invalid token fee denomination'); assert(quotes[2].token.toLowerCase() === quotes[1].token.toLowerCase(), 'quoteTransferRemoteTo returned mismatched token fee denominations'); const amount = BigInt(params.amount.toString()); const tokenQuoteAmount = BigInt(quotes[1].amount.toString()); const externalFeeAmount = BigInt(quotes[2].amount.toString()); const tokenFeeAmount = tokenQuoteAmount >= amount ? tokenQuoteAmount - amount + externalFeeAmount : externalFeeAmount; return { igpQuote: { amount: BigInt(quotes[0].amount.toString()), addressOrDenom: isZeroishAddress(quotes[0].token) ? undefined : quotes[0].token, }, tokenFeeQuote: { addressOrDenom: quotes[1].token, amount: tokenFeeAmount, }, }; } } //# sourceMappingURL=EvmCrossCollateralAdapter.js.map