UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

185 lines 8.82 kB
import { BigNumber } from 'ethers'; import { CairoOption, CairoOptionVariant, cairo, num, } from 'starknet'; import { ProtocolType, addressToBytes32, assert, } from '@hyperlane-xyz/utils'; import { BaseStarknetAdapter } from '../../app/MultiProtocolApp.js'; import { getStarknetEtherContract, getStarknetHypERC20CollateralContract, getStarknetHypERC20Contract, } from '../../utils/starknet.js'; import { PROTOCOL_TO_DEFAULT_NATIVE_TOKEN } from '../nativeTokenMetadata.js'; export class StarknetTokenAdapter extends BaseStarknetAdapter { chainName; multiProvider; addresses; contract; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.contract = getStarknetHypERC20Contract(addresses.warpRouter, multiProvider.getStarknetProvider(chainName)); } async getBalance(address) { return this.contract.balance_of(address); } async getMetadata(_isNft) { const [decimals, symbol, name] = await Promise.all([ this.contract.decimals(), this.contract.symbol(), this.contract.name(), ]); return { decimals, symbol, name }; } async getMinimumTransferAmount(_recipient) { return 0n; } async isApproveRequired(owner, spender, weiAmountOrId) { const allowance = await this.contract.allowance(owner, spender); return BigNumber.from(allowance.toString()).lt(BigNumber.from(weiAmountOrId)); } async isRevokeApprovalRequired(_owner, _spender) { return false; } async populateApproveTx({ weiAmountOrId, recipient, }) { return this.contract.populateTransaction.approve(recipient, weiAmountOrId); } async populateTransferTx({ weiAmountOrId, recipient, }) { return this.contract.populateTransaction.transfer(recipient, weiAmountOrId); } async getTotalSupply() { return this.contract.total_supply(); } } export class StarknetHypSyntheticAdapter extends StarknetTokenAdapter { chainName; multiProvider; addresses; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; } async isApproveRequired(_owner, _spender, _weiAmountOrId) { return false; } async isRevokeApprovalRequired(_owner, _spender) { return false; } async getDomains() { return this.contract.domains(); } async getRouterAddress(domain) { const routerAddresses = await this.contract.routers(domain); return Buffer.from(routerAddresses); } async getAllRouters() { const domains = await this.getDomains(); const routers = await Promise.all(domains.map((d) => this.getRouterAddress(d))); return domains.map((d, i) => ({ domain: d, address: routers[i] })); } async getBridgedSupply() { return this.getTotalSupply(); } async quoteTransferRemoteGas(destination) { const gasPayment = await this.contract.quote_gas_payment(destination); return { amount: BigInt(gasPayment.toString()) }; } async populateTransferRemoteTx({ weiAmountOrId, destination, recipient, interchainGas, }) { const nonOption = new CairoOption(CairoOptionVariant.None); const quote = interchainGas || (await this.quoteTransferRemoteGas(destination)); return this.contract.populateTransaction.transfer_remote(destination, cairo.uint256(addressToBytes32(recipient)), cairo.uint256(BigInt(weiAmountOrId.toString())), cairo.uint256(BigInt(quote.amount)), nonOption, nonOption); } } export class StarknetHypCollateralAdapter extends StarknetHypSyntheticAdapter { collateralContract; wrappedTokenAddress; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.collateralContract = getStarknetHypERC20CollateralContract(addresses.warpRouter, multiProvider.getStarknetProvider(chainName)); } async getWrappedTokenAddress() { if (!this.wrappedTokenAddress) { this.wrappedTokenAddress = num.toHex64(await this.collateralContract.get_wrapped_token()); } return this.wrappedTokenAddress; } async getWrappedTokenAdapter() { return new StarknetHypSyntheticAdapter(this.chainName, this.multiProvider, { warpRouter: await this.getWrappedTokenAddress(), }); } getBridgedSupply() { return this.getBalance(this.addresses.warpRouter); } async getMetadata(isNft) { const adapter = await this.getWrappedTokenAdapter(); return adapter.getMetadata(isNft); } async isApproveRequired(owner, spender, weiAmountOrId) { const adapter = await this.getWrappedTokenAdapter(); return adapter.isApproveRequired(owner, spender, weiAmountOrId); } async populateApproveTx(params) { const adapter = await this.getWrappedTokenAdapter(); return adapter.populateApproveTx(params); } async populateTransferTx(params) { const adapter = await this.getWrappedTokenAdapter(); return adapter.populateTransferTx(params); } } export class StarknetHypNativeAdapter extends StarknetHypSyntheticAdapter { collateralContract; nativeContract; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.collateralContract = getStarknetHypERC20CollateralContract(addresses.warpRouter, multiProvider.getStarknetProvider(chainName)); const nativeAddress = multiProvider.getChainMetadata(chainName)?.nativeToken?.denom; const tokenAddress = nativeAddress ?? PROTOCOL_TO_DEFAULT_NATIVE_TOKEN[ProtocolType.Starknet].denom; assert(tokenAddress, `Native address not found for chain ${chainName}`); this.nativeContract = getStarknetEtherContract(tokenAddress, multiProvider.getStarknetProvider(chainName)); } async getBalance(address) { return this.nativeContract.balanceOf(address); } async isApproveRequired(owner, spender, weiAmountOrId) { const allowance = await this.nativeContract.allowance(owner, spender); return BigNumber.from(allowance.toString()).lt(BigNumber.from(weiAmountOrId)); } async populateApproveTx({ weiAmountOrId, recipient, }) { return this.nativeContract.populateTransaction.approve(recipient, weiAmountOrId); } async populateTransferRemoteTx({ weiAmountOrId, destination, recipient, interchainGas, }) { const nonOption = new CairoOption(CairoOptionVariant.None); const amount = BigInt(weiAmountOrId.toString()); const gasAmount = BigInt(interchainGas?.amount.toString() ?? '0'); const totalAmount = amount + gasAmount; return this.collateralContract.populateTransaction.transfer_remote(destination, cairo.uint256(addressToBytes32(recipient)), cairo.uint256(amount), cairo.uint256(totalAmount), nonOption, nonOption); } } export class StarknetHypFeeAdapter extends StarknetHypSyntheticAdapter { collateralContract; feeTokenContract; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.collateralContract = getStarknetHypERC20CollateralContract(addresses.warpRouter, multiProvider.getStarknetProvider(chainName)); this.feeTokenContract = getStarknetEtherContract(addresses.warpRouter, multiProvider.getStarknetProvider(chainName)); } async getBalance(address) { return this.feeTokenContract.balanceOf(address); } async isApproveRequired(owner, spender, weiAmountOrId) { const allowance = await this.feeTokenContract.allowance(owner, spender); return BigNumber.from(allowance.toString()).lt(BigNumber.from(weiAmountOrId)); } async populateApproveTx({ weiAmountOrId, recipient, }) { return this.feeTokenContract.populateTransaction.approve(recipient, weiAmountOrId); } async populateTransferRemoteTx({ weiAmountOrId, destination, recipient, interchainGas, }) { const nonOption = new CairoOption(CairoOptionVariant.None); const amount = BigInt(weiAmountOrId.toString()); const gasAmount = BigInt(interchainGas?.amount.toString() ?? '0'); const totalAmount = amount + gasAmount; return this.collateralContract.populateTransaction.transfer_remote(destination, cairo.uint256(addressToBytes32(recipient)), cairo.uint256(amount), cairo.uint256(totalAmount), nonOption, nonOption); } } //# sourceMappingURL=StarknetTokenAdapter.js.map