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