@hyperlane-xyz/sdk
Version:
The official SDK for the Hyperlane Network
85 lines • 4.58 kB
JavaScript
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