diff --git a/.registryrc b/.registryrc index b0f729b8d..24eb8a50a 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -d71eb5f42616998f77ce01079fd06a8e118966f7 +10fdae0f566c7c213b6b1b27b8620e8776f2895f diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 77d1cdb5f..1637a3538 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -24,20 +24,20 @@ import { supportedChainNames, } from './supportedChainNames.js'; import { validatorChainConfig } from './validators.js'; -import ancient8EthereumUsdcAddresses from './warp/ancient8-USDC-addresses.json'; -import arbitrumTIAAddresses from './warp/arbitrum-TIA-addresses.json'; -import arbitrumNeutronEclipAddresses from './warp/arbitrum-neutron-eclip-addresses.json'; -import eclipseStrideTiaAddresses from './warp/eclipse-stride-TIA-addresses.json'; -import eclipseStrideStTiaAddresses from './warp/eclipse-stride-stTIA-addresses.json'; -import inevmEthereumUsdcAddresses from './warp/inevm-USDC-addresses.json'; -import inevmEthereumUsdtAddresses from './warp/inevm-USDT-addresses.json'; -import injectiveInevmInjAddresses from './warp/injective-inevm-addresses.json'; -import mantaTIAAddresses from './warp/manta-TIA-addresses.json'; -import merklyEthAddresses from './warp/merkly-eth-addresses.json'; -import renzoEzEthAddressesV3 from './warp/renzo-ezETH-addresses-v3.json'; -import victionEthereumEthAddresses from './warp/viction-ETH-addresses.json'; -import victionEthereumUsdcAddresses from './warp/viction-USDC-addresses.json'; -import victionEthereumUsdtAddresses from './warp/viction-USDT-addresses.json'; +import ancient8EthereumUsdcAddresses from './warp/artifacts/ancient8-USDC-addresses.json'; +import arbitrumTIAAddresses from './warp/artifacts/arbitrum-TIA-addresses.json'; +import arbitrumNeutronEclipAddresses from './warp/artifacts/arbitrum-neutron-eclip-addresses.json'; +import eclipseStrideTiaAddresses from './warp/artifacts/eclipse-stride-TIA-addresses.json'; +import eclipseStrideStTiaAddresses from './warp/artifacts/eclipse-stride-stTIA-addresses.json'; +import inevmEthereumUsdcAddresses from './warp/artifacts/inevm-USDC-addresses.json'; +import inevmEthereumUsdtAddresses from './warp/artifacts/inevm-USDT-addresses.json'; +import injectiveInevmInjAddresses from './warp/artifacts/injective-inevm-addresses.json'; +import mantaTIAAddresses from './warp/artifacts/manta-TIA-addresses.json'; +import merklyEthAddresses from './warp/artifacts/merkly-eth-addresses.json'; +import renzoEzEthAddressesV3 from './warp/artifacts/renzo-ezETH-addresses-v3.json'; +import victionEthereumEthAddresses from './warp/artifacts/viction-ETH-addresses.json'; +import victionEthereumUsdcAddresses from './warp/artifacts/viction-USDC-addresses.json'; +import victionEthereumUsdtAddresses from './warp/artifacts/viction-USDT-addresses.json'; import { WarpRouteIds } from './warp/warpIds.js'; // const releaseCandidateHelloworldMatchingList = routerMatchingList( diff --git a/typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml deleted file mode 100644 index 222a321c2..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -description: Hyperlane Warp Route artifacts -timestamp: '2024-10-18T14:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - arbitrum: - protocolType: ethereum - type: synthetic - hypAddress: '0x6D251aADfc6Ff69031e01eA39bE3cb5BABf8438f' - name: Amphor Restaked ETH - symbol: AMPHRETH - decimals: 18 - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0xdc89990a6fdC1C922b841f1d977835628A24Ed57' - tokenAddress: '0x5fD13359Ba15A84B76f7F87568309040176167cd' - name: Amphor Restaked ETH - symbol: AMPHRETH - decimals: 18 - zircuit: - protocolType: ethereum - type: synthetic - hypAddress: '0x7D5a79539d7B1c9aE5e54d18EEE188840f1Fe4CC' - name: Amphor Restaked ETH - symbol: AMPHRETH - decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml deleted file mode 100644 index 26a0a5807..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml +++ /dev/null @@ -1,86 +0,0 @@ -description: Hyperlane Warp Route artifacts -timestamp: '2024-06-04T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: xERC20Lockbox - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0xC59336D8edDa9722B4f1Ec104007191Ec16f7087' - tokenAddress: '0xbf5495Efe5DB9ce00f80364C8B423567e58d2110' - tokenCoinGeckoId: renzo-restaked-eth - decimals: 18 - bsc: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0xE00C6185a5c19219F1FFeD213b4406a254968c26' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - arbitrum: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0xB26bBfC6d1F469C821Ea25099017862e7368F4E8' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - optimism: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0xacEB607CdF59EB8022Cc0699eEF3eCF246d149e2' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - base: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0x2552516453368e42705D791F674b312b8b87CD9e' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - blast: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0x486b39378f99f073A3043C6Aabe8666876A8F3C5' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - mode: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0xC59336D8edDa9722B4f1Ec104007191Ec16f7087' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - linea: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0xC59336D8edDa9722B4f1Ec104007191Ec16f7087' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - fraxtal: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0x3aE8635A4D581d40a6Edfb3f2ED480f9532994F5' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 - zircuit: - protocolType: ethereum - type: xERC20 - name: Renzo Restaked ETH - symbol: ezETH - hypAddress: '0x2552516453368e42705D791F674b312b8b87CD9e' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' - decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/TIA-eclipse-stride-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/TIA-eclipse-stride-deployments.yaml deleted file mode 100644 index 45c9e0efc..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/TIA-eclipse-stride-deployments.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -description: Hyperlane Warp Route artifacts -timestamp: '2024-10-18T14:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - stride: - protocolType: cosmos - type: collateral - hypAddress: stride1pvtesu3ve7qn7ctll2x495mrqf2ysp6fws68grvcu6f7n2ajghgsh2jdj6 - tokenAddress: ibc/BF3B4F53F3694B66E13C23107C84B6485BD2B96296BB7EC680EA77BBA75B4801 - tokenCoinGeckoId: celestia - name: Celestia - symbol: TIA - decimals: 6 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: 'BpXHAiktwjx7fN6M9ST9wr6qKAsH27wZFhdHEhReJsR6' - tokenAddress: '9RryNMhAVJpAwAGjCAMKbbTFwgjapqPkzpGMfTQhEjf8' - isSpl2022: true - name: Turbo Eth - symbol: tETH - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-deployments.yaml deleted file mode 100644 index d87b3fa0a..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between ancient8 and Ethereum -description: Hyperlane Warp Route artifacts -timestamp: '2024-04-15T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0x8b4192B9Ad1fCa440A5808641261e5289e6de95D' - tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' # USDC - tokenCoinGeckoId: usd-coin - name: USDC - symbol: USDC - decimals: 6 - ancient8: - protocolType: ethereum - type: synthetic - hypAddress: '0x97423A68BAe94b5De52d767a17aBCc54c157c0E5' - name: USDC - symbol: USDC - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/ancient8-USDC-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/ancient8-USDC-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/arbitrum-TIA-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/arbitrum-TIA-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/arbitrum-TIA-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/arbitrum-TIA-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/arbitrum-neutron-eclip-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/arbitrum-neutron-eclip-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/arbitrum-neutron-eclip-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/arbitrum-neutron-eclip-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-TIA-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/eclipse-stride-TIA-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/eclipse-stride-TIA-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/eclipse-stride-TIA-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-stTIA-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/eclipse-stride-stTIA-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/eclipse-stride-stTIA-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/eclipse-stride-stTIA-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/inevm-USDC-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/inevm-USDC-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/inevm-USDC-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/inevm-USDC-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/inevm-USDT-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/inevm-USDT-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/inevm-USDT-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/inevm-USDT-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/injective-inevm-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/injective-inevm-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/injective-inevm-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/injective-inevm-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/manta-TIA-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/manta-TIA-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/manta-TIA-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/manta-TIA-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/merkly-erc20-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/merkly-erc20-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/merkly-erc20-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/merkly-erc20-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/merkly-eth-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/merkly-eth-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/merkly-eth-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/merkly-eth-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/merkly-nft-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/merkly-nft-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/merkly-nft-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/merkly-nft-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v1.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/renzo-ezETH-addresses-v1.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v1.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/renzo-ezETH-addresses-v1.json diff --git a/typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v3.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/renzo-ezETH-addresses-v3.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v3.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/renzo-ezETH-addresses-v3.json diff --git a/typescript/infra/config/environments/mainnet3/warp/verification.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/verification.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/verification.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/verification.json diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-ETH-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/viction-ETH-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/viction-ETH-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/viction-ETH-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-USDC-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/viction-USDC-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/viction-USDC-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/viction-USDC-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-USDT-addresses.json b/typescript/infra/config/environments/mainnet3/warp/artifacts/viction-USDT-addresses.json similarity index 100% rename from typescript/infra/config/environments/mainnet3/warp/viction-USDT-addresses.json rename to typescript/infra/config/environments/mainnet3/warp/artifacts/viction-USDT-addresses.json diff --git a/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml deleted file mode 100644 index d106ac884..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between Ethereum and Binance Smart Chain and Lumia -description: Hyperlane Warp Route artifacts -timestamp: '2024-10-18T14:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0xdD313D475f8A9d81CBE2eA953a357f52e10BA357' - tokenAddress: '0xd9343a049d5dbd89cd19dc6bca8c48fb3a0a42a7' - tokenCoinGeckoId: lumia - name: Lumia Token - symbol: LUMIA - decimals: 18 - bsc: - protocolType: ethereum - type: synthetic - hypAddress: '0x7F39BcdCa8E0E581c1d43aaa1cB862AA1c8C2047' - name: Lumia Token - symbol: LUMIA - decimals: 18 - lumia: - protocolType: ethereum - type: native - hypAddress: '0x6a77331cE28E47c3Cb9Fea48AB6cD1e9594ce0A9' - name: Lumia Token - symbol: LUMIA - decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-ORCA-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-ORCA-deployments.yaml deleted file mode 100644 index 8205cc93e..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-ORCA-deployments.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -description: Hyperlane Warp Route artifacts -timestamp: '2024-09-19T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - solanamainnet: - protocolType: sealevel - type: collateral - hypAddress: '8acihSm2QTGswniKgdgr4JBvJihZ1cakfvbqWCPBLoSp' - tokenAddress: 'orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE' - tokenCoinGeckoId: orca - name: Orca - symbol: ORCA - decimals: 6 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: '8CvWJS7SPtauAXinJUURkBDLsGUXWiiTdENkEFUPjQ9j' - tokenAddress: '2tGbYEm4nuPFyS6zjDTELzEhvVKizgKewi6xT7AaSKzn' - isSpl2022: true - name: Orca - symbol: ORCA - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml deleted file mode 100644 index 711e6d428..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between injective and inevm -description: Hyperlane Warp Route artifacts -timestamp: '2024-09-19T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - solanamainnet: - protocolType: sealevel - type: native - hypAddress: '8DtAGQpcMuD5sG3KdxDy49ydqXUggR1LQtebh2TECbAc' - tokenCoinGeckoId: solana - name: Solana - symbol: SOL - decimals: 9 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: 'FJu4E1BDYKVg7aTWdwATZRUvytJZ8ZZ2gQuvPfMWAz9y' - tokenAddress: 'BeRUj3h7BqkbdfFU7FBNYbodgf8GCHodzKvF9aVjNNfL' - isSpl2022: true - name: Solana - symbol: SOL - decimals: 9 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml deleted file mode 100644 index 7405cb94d..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between injective and inevm -description: Hyperlane Warp Route artifacts -timestamp: '2024-09-19T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0xe1De9910fe71cC216490AC7FCF019e13a34481D7' - tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' # USDC - tokenCoinGeckoId: usd-coin - name: USDC - symbol: USDC - decimals: 6 - solanamainnet: - protocolType: sealevel - type: collateral - hypAddress: '3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm' - tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' - tokenCoinGeckoId: usd-coin - isSpl2022: false - name: USDC - symbol: USDC - decimals: 6 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: 'EqRSt9aUDMKYKhzd1DGMderr3KNp29VZH3x5P7LFTC8m' - tokenAddress: 'AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE' - isSpl2022: true - name: USDC - symbol: USDC - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-USDT-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-USDT-deployments.yaml deleted file mode 100644 index 0a126ed76..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-USDT-deployments.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -description: Hyperlane Warp Route artifacts -timestamp: '2024-09-19T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0x647C621CEb36853Ef6A907E397Adf18568E70543' - tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7' # USDT - tokenCoinGeckoId: tether - name: USDT - symbol: USDT - decimals: 6 - solanamainnet: - protocolType: sealevel - type: collateral - hypAddress: 'Bk79wMjvpPCh5iQcCEjPWFcG1V2TfgdwaBsWBEYFYSNU' - tokenAddress: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB' - tokenCoinGeckoId: tether - isSpl2022: false - name: USDT - symbol: USDT - decimals: 6 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: '5g5ujyYUNvdydwyDVCpZwPpgYRqH5RYJRi156cxyE3me' - tokenAddress: 'CEBP3CqAbW4zdZA57H2wfaSG1QNdzQ72GiQEbQXyW9Tm' - isSpl2022: true - name: USDT - symbol: USDT - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-WBTC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-WBTC-deployments.yaml deleted file mode 100644 index bd993b8c9..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-WBTC-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -description: Hyperlane Warp Route artifacts -timestamp: '2024-09-19T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0x5B4e223DE74ef8c3218e66EEcC541003CAB3121A' - tokenAddress: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' - name: WBTC - symbol: WBTC - decimals: 8 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: 'A7EGCDYFw5R7Jfm6cYtKvY8dmkrYMgwRCJFkyQwpHTYu' - tokenAddress: '7UTjr1VC6Z9DPsWD6mh5wPzNtufN17VnzpKS3ASpfAji' - isSpl2022: true - name: WBTC - symbol: WBTC - decimals: 8 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml deleted file mode 100644 index 1b7245c91..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between injective and inevm -description: Hyperlane Warp Route artifacts -timestamp: '2024-09-19T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - solanamainnet: - protocolType: sealevel - type: collateral - hypAddress: 'CuQmsT4eSF4dYiiGUGYYQxJ7c58pUAD5ADE3BbFGzQKx' - tokenAddress: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm' - tokenCoinGeckoId: dogwifcoin - name: dogwifhat - symbol: WIF - decimals: 9 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: '6tBGmKNxirxBYnm9khkaTtcr2fhJ9YviCgRm1RWM8NJv' - tokenAddress: '841P4tebEgNux2jaWSjCoi9LhrVr9eHGjLc758Va3RPH' - isSpl2022: false - name: dogwifhat - symbol: WIF - decimals: 9 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-tETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-tETH-deployments.yaml deleted file mode 100644 index 1f77a34e5..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-tETH-deployments.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between injective and inevm -description: Hyperlane Warp Route artifacts -timestamp: '2024-09-19T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0xc2495f3183F043627CAECD56dAaa726e3B2D9c09' - tokenAddress: '0x19e099B7aEd41FA52718D780dDA74678113C0b32' - name: Turbo Eth - symbol: tETH - decimals: 18 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: '6GM7hy6M6LjhadG1xuKXPQ3jPC1eieEszR8DforoRzUp' - tokenAddress: 'GU7NS9xCwgNPiAdJ69iusFrRfawjDDPjeMBovhV1d4kn' - isSpl2022: false - name: Turbo Eth - symbol: tETH - decimals: 9 diff --git a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDC-inevm-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/ethereumUSDC-inevm-deployments.yaml deleted file mode 100644 index 90f22e0df..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDC-inevm-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between injective and inevm -description: Hyperlane Warp Route artifacts -timestamp: '2024-02-06T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0xED56728fb977b0bBdacf65bCdD5e17Bb7e84504f' - tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' # USDC - tokenCoinGeckoId: usd-coin - name: USDC - symbol: USDC - decimals: 6 - inevm: - protocolType: ethereum - type: synthetic - hypAddress: '0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147' - name: USDC - symbol: USDC - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDT-inevm-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/ethereumUSDT-inevm-deployments.yaml deleted file mode 100644 index 91976ddd9..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDT-inevm-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between injective and inevm -description: Hyperlane Warp Route artifacts -timestamp: '2024-02-06T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0xab852e67bf03E74C89aF67C4BA97dd1088D3dA19' - tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7' # USDT - tokenCoinGeckoId: tether - name: Tether USD - symbol: USDT - decimals: 6 - inevm: - protocolType: ethereum - type: synthetic - hypAddress: '0x97423A68BAe94b5De52d767a17aBCc54c157c0E5' - name: Tether USD - symbol: USDT - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/injective-inevm-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/injective-inevm-deployments.yaml deleted file mode 100644 index cd39382ea..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/injective-inevm-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between injective and inevm -description: Hyperlane Warp Route artifacts -timestamp: '2024-01-31T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - injective: - protocolType: cosmos - type: native - hypAddress: inj1mv9tjvkaw7x8w8y9vds8pkfq46g2vcfkjehc6k - tokenCoinGeckoId: injective-protocol - name: Injective Coin - symbol: INJ - decimals: 18 - ibcDenom: inj - inevm: - protocolType: ethereum - type: native - hypAddress: '0x26f32245fCF5Ad53159E875d5Cae62aEcf19c2d4' - name: Injective coin - symbol: INJ - decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/nautilus-solana-bsc-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/nautilus-solana-bsc-deployments.yaml deleted file mode 100644 index e3e877007..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/nautilus-solana-bsc-deployments.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between nautilus and bsc, solana -description: Hyperlane Warp Route artifacts -timestamp: '2023-09-23T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - bsc: - protocolType: ethereum - type: collateral - hypAddress: '0xC27980812E2E66491FD457D488509b7E04144b98' - tokenAddress: '0x37a56cdcD83Dce2868f721De58cB3830C44C6303' - name: Zebec - symbol: ZBC - decimals: 9 - nautilus: - protocolType: ethereum - type: native - hypAddress: '0x4501bBE6e731A4bC5c60C03A77435b2f6d5e9Fe7' - name: Zebec - symbol: ZBC - decimals: 18 - solana: - protocolType: sealevel - type: collateral - tokenAddress: 'wzbcJyhGhQDLTV1S99apZiiBdE4jmYfbw99saMMdP59' - hypAddress: 'EJqwFjvVJSAxH8Ur2PYuMfdvoJeutjmH6GkoEFQ4MdSa' - name: Zebec - symbol: ZBC - decimals: 9 - isSpl2022: true diff --git a/typescript/infra/config/environments/mainnet3/warp/neutron-mantapacific-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/neutron-mantapacific-deployments.yaml deleted file mode 100644 index bf4e1770a..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/neutron-mantapacific-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between neutron and mantapacific -description: Hyperlane Warp Route artifacts -timestamp: '2023-09-23T16:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - neutron: - protocolType: cosmos - type: collateral - hypAddress: neutron1ch7x3xgpnj62weyes8vfada35zff6z59kt2psqhnx9gjnt2ttqdqtva3pa - tokenAddress: ibc/773B4D0A3CD667B2275D5A4A7A2F0909C0BA0F4059C0B9181E680DDF4965DCC7 - tokenCoinGeckoId: celestia - name: Celestia - symbol: TIA - decimals: 6 - mantapacific: - protocolType: ethereum - type: synthetic - hypAddress: '0x6Fae4D9935E2fcb11fC79a64e917fb2BF14DaFaa' - name: Celestia - symbol: TIA - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml deleted file mode 100644 index ed9672e41..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml +++ /dev/null @@ -1,22 +0,0 @@ -description: Hyperlane Warp Route artifacts -timestamp: '2024-10-17T14:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0x9AD81058c6C3Bf552C9014CB30E824717A0ee21b' - tokenAddress: '0x15700B564Ca08D9439C58cA5053166E8317aa138' - tokenCoinGeckoId: elixir-deusd # unique setup where we want deUSD to be deposited as collateral and we want fastUSD to be minted as a synthetic on sei - name: fastUSD - symbol: fastUSD - decimals: 18 - sei: - protocolType: ethereum - type: xERC20 - hypAddress: '0xeA895A7Ff45d8d3857A04c1E38A362f3bd9a076f' - tokenAddress: '0x37a4dD9CED2b19Cfe8FAC251cd727b5787E45269' - name: fastUSD - symbol: fastUSD - decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/stTIA-eclipse-stride-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/stTIA-eclipse-stride-deployments.yaml deleted file mode 100644 index 7f18e471c..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/stTIA-eclipse-stride-deployments.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -description: Hyperlane Warp Route artifacts -timestamp: '2024-10-18T14:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - stride: - protocolType: cosmos - type: collateral - hypAddress: stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee - tokenAddress: 'stutia' - tokenCoinGeckoId: stride-staked-tia - name: Stride Staked TIA - symbol: stTIA - decimals: 6 - eclipsemainnet: - protocolType: sealevel - type: synthetic - hypAddress: 'tKUHyJ5NxhnwU94JUmzh1ekukDcHHX8mZF6fqxbMwX6' - tokenAddress: 'V5m1Cc9VK61mKL8xVYrjR7bjD2BC5VpADLa6ws3G8KM' - isSpl2022: true - name: Turbo Eth - symbol: tETH - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-ETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-ETH-deployments.yaml deleted file mode 100644 index c3e03b54d..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-ETH-deployments.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between viction and ethereum, ETH -description: Hyperlane Warp Route artifacts -timestamp: '2023-02-14T20:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: native - hypAddress: '0x15b5D6B614242B118AA404528A7f3E2Ad241e4A4' - tokenCoinGeckoId: ethereum - name: Ether - symbol: ETH - decimals: 18 - viction: - protocolType: ethereum - type: synthetic - hypAddress: '0x182E8d7c5F1B06201b102123FC7dF0EaeB445a7B' - name: ETH - symbol: ETH - decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDC-deployments.yaml deleted file mode 100644 index 8a84e6a7c..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDC-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between viction and ethereum, USDC -description: Hyperlane Warp Route artifacts -timestamp: '2023-02-14T20:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0x31Dca7762930f56D81292f85E65c9D67575804fE' - tokenAddress: '0x31Dca7762930f56D81292f85E65c9D67575804fE' # USDC - tokenCoinGeckoId: usd-coin - name: USD Coin - symbol: USDC - decimals: 6 - viction: - protocolType: ethereum - type: synthetic - hypAddress: '0xBDa330Ea8F3005C421C8088e638fBB64fA71b9e0' - name: USDC - symbol: USDC - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDT-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDT-deployments.yaml deleted file mode 100644 index a22598042..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDT-deployments.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Configs and artifacts for the deployment of Hyperlane Warp Routes -# Between viction and ethereum, USDT -description: Hyperlane Warp Route artifacts -timestamp: '2023-02-14T20:00:00.000Z' -deployer: Abacus Works (Hyperlane) -data: - config: - ethereum: - protocolType: ethereum - type: collateral - hypAddress: '0x4221a16A01F61c2b38A03C52d828a7041f6AAA49' - tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7' # USDT - tokenCoinGeckoId: tether - name: Tether USD - symbol: USDT - decimals: 6 - viction: - protocolType: ethereum - type: synthetic - hypAddress: '0x48083c69f5a42c6b69abbad48ae195bd36770ee2' - name: USDT - symbol: USDT - decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index d70348b56..a68ed19c8 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -9,10 +9,11 @@ export enum WarpRouteIds { EclipseEthereumTETH = 'tETH/eclipsemainnet-ethereum', EclipseEthereumWBTC = 'WBTC/eclipsemainnet-ethereum', EclipseEthereumWeETHs = 'weETHs/eclipsemainnet-ethereum', + EclipseSolanaORCA = 'ORCA/eclipsemainnet-solanamainnet', EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet', EclipseSolanaWIF = 'WIF/eclipsemainnet-solanamainnet', - EclipseStrideSTTIA = 'stTIA/eclipse-stride', - EclipseStrideTIA = 'TIA/eclipse-stride', + EclipseStrideSTTIA = 'stTIA/eclipsemainnet-stride', + EclipseStrideTIA = 'TIA/eclipsemainnet-stride', EthereumInevmUSDC = 'USDC/ethereum-inevm', EthereumInevmUSDT = 'USDT/ethereum-inevm', EthereumSeiFastUSD = 'FASTUSD/ethereum-sei', diff --git a/typescript/infra/config/registry.ts b/typescript/infra/config/registry.ts index 4b72c9f5b..8b9ea5edb 100644 --- a/typescript/infra/config/registry.ts +++ b/typescript/infra/config/registry.ts @@ -12,6 +12,7 @@ import { ChainMap, ChainMetadata, ChainName, + WarpCoreConfig, getDomainId as resolveDomainId, getReorgPeriod as resolveReorgPeriod, } from '@hyperlane-xyz/sdk'; @@ -91,7 +92,7 @@ export function getChainAddresses(): ChainMap { return getRegistry().getAddresses(); } -export function getWarpAddresses(warpRouteId: string) { +export function getWarpCoreConfig(warpRouteId: string): WarpCoreConfig { const registry = getRegistry(); const warpRouteConfig = registry.getWarpRoute(warpRouteId); @@ -100,8 +101,12 @@ export function getWarpAddresses(warpRouteId: string) { `Warp route config for ${warpRouteId} not found in registry`, ); } + return warpRouteConfig; +} - return warpConfigToWarpAddresses(warpRouteConfig); +export function getWarpAddresses(warpRouteId: string) { + const warpCoreConfig = getWarpCoreConfig(warpRouteId); + return warpConfigToWarpAddresses(warpCoreConfig); } export function getEnvChains(env: DeployEnvironment): ChainName[] { diff --git a/typescript/infra/helm/warp-routes/templates/_helpers.tpl b/typescript/infra/helm/warp-routes/templates/_helpers.tpl index 52bc42a86..bc732a5a3 100644 --- a/typescript/infra/helm/warp-routes/templates/_helpers.tpl +++ b/typescript/infra/helm/warp-routes/templates/_helpers.tpl @@ -72,11 +72,11 @@ The warp-routes container value: pretty command: - ./node_modules/.bin/tsx - - ./typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts + - ./typescript/infra/scripts/warp-routes/monitor/monitor-warp-route-balances.ts - -v - - "10000" - - -f - - {{ .Values.configFilePath }} + - "30000" + - --warpRouteId + - {{ .Values.warpRouteId }} - -e - {{ .Values.environment}} envFrom: diff --git a/typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml b/typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml index d1f1eda25..5bad068b9 100644 --- a/typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml +++ b/typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml @@ -22,6 +22,7 @@ spec: data: GCP_SECRET_OVERRIDES_ENABLED: "true" GCP_SECRET_OVERRIDE_{{ $.Values.hyperlane.runEnv | upper }}_COINGECKO_API_KEY: {{ printf "'{{ .%s_coingecko_api_key | toString }}'" .Values.hyperlane.runEnv }} + GCP_SECRET_OVERRIDE_HYPERLANE_{{ .Values.hyperlane.runEnv | upper }}_KEY_DEPLOYER: {{ print "'{{ .deployer_key | toString }}'" }} {{/* * For each network, create an environment variable with the RPC endpoint. * The templating of external-secrets will use the data section below to know how @@ -34,6 +35,9 @@ spec: - secretKey: {{ printf "%s_coingecko_api_key" .Values.hyperlane.runEnv }} remoteRef: key: {{ printf "%s-coingecko-api-key" .Values.hyperlane.runEnv }} + - secretKey: deployer_key + remoteRef: + key: {{ printf "hyperlane-%s-key-deployer" .Values.hyperlane.runEnv }} {{/* * For each network, load the secret in GCP secret manager with the form: environment-rpc-endpoint-network, * and associate it with the secret key networkname_rpc. diff --git a/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts b/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts index 95a749ace..bc19f434f 100644 --- a/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts +++ b/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts @@ -1,32 +1,58 @@ +import { checkbox } from '@inquirer/prompts'; import yargs from 'yargs'; import { Contexts } from '../../config/contexts.js'; +import { WarpRouteIds } from '../../config/environments/mainnet3/warp/warpIds.js'; import { HelmCommand } from '../../src/utils/helm.js'; import { WarpRouteMonitorHelmManager } from '../../src/warp/helm.js'; -import { assertCorrectKubeContext, getAgentConfig } from '../agent-utils.js'; +import { + assertCorrectKubeContext, + getAgentConfig, + getArgs, + withWarpRouteId, +} from '../agent-utils.js'; import { getEnvironmentConfig } from '../core-utils.js'; async function main() { - const { filePath } = await yargs(process.argv.slice(2)) - .alias('f', 'filePath') - .describe( - 'filePath', - 'indicate the filepath to the warp route yaml file relative to the monorepo root', - ) - .demandOption('filePath') - .string('filePath') - .parse(); - - const environment = 'mainnet3'; + const { environment, warpRouteId } = await withWarpRouteId(getArgs()).argv; + + let warpRouteIds; + if (warpRouteId) { + warpRouteIds = [warpRouteId]; + } else { + warpRouteIds = await getWarpRouteIdsInteractive(); + } + await assertCorrectKubeContext(getEnvironmentConfig(environment)); const agentConfig = getAgentConfig(Contexts.Hyperlane, environment); - const helmManager = new WarpRouteMonitorHelmManager( - filePath, - environment, - agentConfig.environmentChainNames, - ); - await helmManager.runHelmCommand(HelmCommand.InstallOrUpgrade); + const deployWarpMonitor = async (warpRouteId: string) => { + const helmManager = new WarpRouteMonitorHelmManager( + warpRouteId, + environment, + agentConfig.environmentChainNames, + ); + await helmManager.runHelmCommand(HelmCommand.InstallOrUpgrade); + }; + + for (const id of warpRouteIds) { + console.log(`Deploying Warp Monitor for Warp Route ID: ${id}`); + await deployWarpMonitor(id); + } +} + +async function getWarpRouteIdsInteractive() { + const choices = Object.values(WarpRouteIds).map((id) => ({ + value: id, + })); + + const selection = await checkbox({ + message: 'Select Warp Route IDs to deploy', + choices, + pageSize: 30, + }); + + return selection; } main() diff --git a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts deleted file mode 100644 index 06b4fb78f..000000000 --- a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts +++ /dev/null @@ -1,697 +0,0 @@ -import { SystemProgram } from '@solana/web3.js'; -import { ethers } from 'ethers'; -import { Gauge, Registry } from 'prom-client'; - -import { - ERC20__factory, - HypXERC20Lockbox__factory, - HypXERC20__factory, - IXERC20, - IXERC20__factory, -} from '@hyperlane-xyz/core'; -import { createWarpRouteConfigId } from '@hyperlane-xyz/registry'; -import { - ChainMap, - ChainMetadata, - ChainName, - CoinGeckoTokenPriceGetter, - CosmNativeTokenAdapter, - CwNativeTokenAdapter, - MultiProtocolProvider, - SealevelHypCollateralAdapter, - SealevelHypNativeAdapter, - SealevelHypSyntheticAdapter, - TokenType, - WarpRouteConfig, - WarpRouteConfigSchema, -} from '@hyperlane-xyz/sdk'; -import { - ProtocolType, - objMap, - promiseObjAll, - rootLogger, -} from '@hyperlane-xyz/utils'; - -import { DeployEnvironment } from '../../src/config/environment.js'; -import { fetchGCPSecret } from '../../src/utils/gcloud.js'; -import { startMetricsServer } from '../../src/utils/metrics.js'; -import { readYaml } from '../../src/utils/utils.js'; -import { getArgs } from '../agent-utils.js'; -import { getEnvironmentConfig } from '../core-utils.js'; - -const logger = rootLogger.child({ module: 'warp-balance-monitor' }); - -const metricsRegister = new Registry(); - -interface WarpRouteMetrics { - chain_name: ChainName; - token_address: string; - token_name: string; - wallet_address: string; - token_type: TokenType; - warp_route_id: string; - related_chain_names: string; -} - -type WarpRouteMetricLabels = keyof WarpRouteMetrics; - -const warpRouteMetricLabels: WarpRouteMetricLabels[] = [ - 'chain_name', - 'token_address', - 'token_name', - 'wallet_address', - 'token_type', - 'warp_route_id', - 'related_chain_names', -]; - -const warpRouteTokenBalance = new Gauge({ - name: 'hyperlane_warp_route_token_balance', - help: 'HypERC20 token balance of a Warp Route', - registers: [metricsRegister], - labelNames: warpRouteMetricLabels, -}); - -const warpRouteCollateralValue = new Gauge({ - name: 'hyperlane_warp_route_collateral_value', - help: 'Total value of collateral held in a HypERC20Collateral or HypNative contract of a Warp Route', - registers: [metricsRegister], - labelNames: warpRouteMetricLabels, -}); - -const xERC20LimitsGauge = new Gauge({ - name: 'hyperlane_xerc20_limits', - help: 'Current minting and burning limits of xERC20 tokens', - registers: [metricsRegister], - labelNames: ['chain_name', 'limit_type', 'token_name'], -}); - -interface xERC20Limit { - tokenName: string; - mint: number; - burn: number; - mintMax: number; - burnMax: number; -} - -interface WarpRouteInfo { - balance: number; - valueUSD?: number; -} - -export function readWarpRouteConfig(filePath: string) { - const config = readYaml(filePath); - if (!config) throw new Error(`No warp config found at ${filePath}`); - const result = WarpRouteConfigSchema.safeParse(config); - if (!result.success) { - const errorMessages = result.error.issues.map( - (issue: any) => `${issue.path} => ${issue.message}`, - ); - throw new Error(`Invalid warp config:\n ${errorMessages.join('\n')}`); - } - return result.data; -} - -async function main(): Promise { - const { checkFrequency, filePath, environment } = await getArgs() - .describe('checkFrequency', 'frequency to check balances in ms') - .demandOption('checkFrequency') - .alias('v', 'checkFrequency') // v as in Greek letter nu - .number('checkFrequency') - .alias('f', 'filePath') - .describe( - 'filePath', - 'indicate the filepatch to the warp route yaml file relative to typescript/infra', - ) - .demandOption('filePath') - .string('filePath') - .parse(); - - startMetricsServer(metricsRegister); - - const tokenConfig: WarpRouteConfig = - readWarpRouteConfig(filePath).data.config; - - const envConfig = getEnvironmentConfig(environment); - const registry = await envConfig.getRegistry(); - const chainMetadata = await registry.getMetadata(); - - await checkWarpRouteMetrics(checkFrequency, tokenConfig, chainMetadata); - - return true; -} - -// TODO: see issue https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2708 -async function checkBalance( - tokenConfig: WarpRouteConfig, - multiProtocolProvider: MultiProtocolProvider, - tokenPriceGetter: CoinGeckoTokenPriceGetter, -): Promise> { - const output = objMap( - tokenConfig, - async (chain: ChainName, token: WarpRouteConfig[ChainName]) => { - switch (token.type) { - case TokenType.native: { - switch (token.protocolType) { - case ProtocolType.Ethereum: { - const provider = multiProtocolProvider.getEthersV5Provider(chain); - const nativeBalance = await provider.getBalance(token.hypAddress); - - return getNativeTokenWarpInfo( - nativeBalance, - token.decimals, - tokenPriceGetter, - chain, - ); - } - case ProtocolType.Sealevel: { - const adapter = new SealevelHypNativeAdapter( - chain, - multiProtocolProvider, - { - token: token.tokenAddress, - warpRouter: token.hypAddress, - // Mailbox only required for transfers, using system as placeholder - mailbox: SystemProgram.programId.toBase58(), - }, - // Not used for native tokens, but required for the adapter - token?.isSpl2022 ?? false, - ); - const balance = ethers.BigNumber.from( - await adapter.getBalance(token.hypAddress), - ); - - return getNativeTokenWarpInfo( - balance, - token.decimals, - tokenPriceGetter, - chain, - ); - } - case ProtocolType.Cosmos: { - if (!token.ibcDenom) - throw new Error('IBC denom missing for native token'); - const adapter = new CosmNativeTokenAdapter( - chain, - multiProtocolProvider, - {}, - { ibcDenom: token.ibcDenom }, - ); - const tokenBalance = await adapter.getBalance(token.hypAddress); - - return getNativeTokenWarpInfo( - tokenBalance, - token.decimals, - tokenPriceGetter, - chain, - ); - } - } - break; - } - case TokenType.collateral: { - switch (token.protocolType) { - case ProtocolType.Ethereum: { - const provider = multiProtocolProvider.getEthersV5Provider(chain); - if (!token.tokenAddress) - throw new Error('Token address missing for collateral token'); - const tokenContract = ERC20__factory.connect( - token.tokenAddress, - provider, - ); - const collateralBalance = await tokenContract.balanceOf( - token.hypAddress, - ); - - return getCollateralTokenWarpInfo( - collateralBalance, - token.decimals, - tokenPriceGetter, - token.tokenCoinGeckoId, - ); - } - case ProtocolType.Sealevel: { - if (!token.tokenAddress) - throw new Error('Token address missing for collateral token'); - const adapter = new SealevelHypCollateralAdapter( - chain, - multiProtocolProvider, - { - token: token.tokenAddress, - warpRouter: token.hypAddress, - // Mailbox only required for transfers, using system as placeholder - mailbox: SystemProgram.programId.toBase58(), - }, - token?.isSpl2022 ?? false, - ); - const collateralBalance = ethers.BigNumber.from( - await adapter.getBalance(token.hypAddress), - ); - - return getCollateralTokenWarpInfo( - collateralBalance, - token.decimals, - tokenPriceGetter, - token.tokenCoinGeckoId, - ); - } - case ProtocolType.Cosmos: { - if (!token.tokenAddress) - throw new Error('Token address missing for cosmos token'); - const adapter = new CwNativeTokenAdapter( - chain, - multiProtocolProvider, - { - token: token.hypAddress, - }, - token.tokenAddress, - ); - const collateralBalance = ethers.BigNumber.from( - await adapter.getBalance(token.hypAddress), - ); - - return getCollateralTokenWarpInfo( - collateralBalance, - token.decimals, - tokenPriceGetter, - token.tokenCoinGeckoId, - ); - } - } - break; - } - case TokenType.synthetic: { - switch (token.protocolType) { - case ProtocolType.Ethereum: { - const provider = multiProtocolProvider.getEthersV5Provider(chain); - const tokenContract = ERC20__factory.connect( - token.hypAddress, - provider, - ); - const syntheticBalance = await tokenContract.totalSupply(); - return { - balance: parseFloat( - ethers.utils.formatUnits(syntheticBalance, token.decimals), - ), - }; - } - case ProtocolType.Sealevel: { - if (!token.tokenAddress) - throw new Error('Token address missing for synthetic token'); - const adapter = new SealevelHypSyntheticAdapter( - chain, - multiProtocolProvider, - { - token: token.tokenAddress, - warpRouter: token.hypAddress, - // Mailbox only required for transfers, using system as placeholder - mailbox: SystemProgram.programId.toBase58(), - }, - token?.isSpl2022 ?? false, - ); - const syntheticBalance = ethers.BigNumber.from( - await adapter.getTotalSupply(), - ); - return { - balance: parseFloat( - ethers.utils.formatUnits(syntheticBalance, token.decimals), - ), - }; - } - case ProtocolType.Cosmos: - // TODO - cosmos synthetic - return { balance: 0 }; - } - break; - } - case TokenType.XERC20: { - switch (token.protocolType) { - case ProtocolType.Ethereum: { - const provider = multiProtocolProvider.getEthersV5Provider(chain); - const hypXERC20 = HypXERC20__factory.connect( - token.hypAddress, - provider, - ); - const xerc20Address = await hypXERC20.wrappedToken(); - const xerc20 = IXERC20__factory.connect(xerc20Address, provider); - const syntheticBalance = await xerc20.totalSupply(); - - return { - balance: parseFloat( - ethers.utils.formatUnits(syntheticBalance, token.decimals), - ), - }; - } - default: - throw new Error( - `Unsupported protocol type ${token.protocolType} for token type ${token.type}`, - ); - } - } - case TokenType.XERC20Lockbox: { - switch (token.protocolType) { - case ProtocolType.Ethereum: { - if (!token.tokenAddress) - throw new Error( - 'Token address missing for xERC20Lockbox token', - ); - const provider = multiProtocolProvider.getEthersV5Provider(chain); - const hypXERC20Lockbox = HypXERC20Lockbox__factory.connect( - token.hypAddress, - provider, - ); - const xerc20LockboxAddress = await hypXERC20Lockbox.lockbox(); - const tokenContract = ERC20__factory.connect( - token.tokenAddress, - provider, - ); - - const collateralBalance = await tokenContract.balanceOf( - xerc20LockboxAddress, - ); - - return getCollateralTokenWarpInfo( - collateralBalance, - token.decimals, - tokenPriceGetter, - token.tokenCoinGeckoId, - ); - } - default: - throw new Error( - `Unsupported protocol type ${token.protocolType} for token type ${token.type}`, - ); - } - } - } - return { balance: 0 }; - }, - ); - - return promiseObjAll(output); -} - -export function updateTokenBalanceMetrics( - tokenConfig: WarpRouteConfig, - balances: ChainMap, -) { - objMap(tokenConfig, (chain: ChainName, token: WarpRouteConfig[ChainName]) => { - const metrics: WarpRouteMetrics = { - chain_name: chain, - token_address: token.tokenAddress ?? ethers.constants.AddressZero, - token_name: token.name, - wallet_address: token.hypAddress, - token_type: token.type, - warp_route_id: createWarpRouteConfigId( - token.symbol, - Object.keys(tokenConfig) as ChainName[], - ), - related_chain_names: Object.keys(tokenConfig) - .filter((chainName) => chainName !== chain) - .sort() - .join(','), - }; - - warpRouteTokenBalance.labels(metrics).set(balances[chain].balance); - if (balances[chain].valueUSD) { - warpRouteCollateralValue - .labels(metrics) - .set(balances[chain].valueUSD as number); - logger.debug('Collateral value updated for chain', { - chain, - related_chain_names: metrics.related_chain_names, - warp_route_id: metrics.warp_route_id, - token: metrics.token_name, - value: balances[chain].valueUSD, - }); - } - logger.debug('Wallet balance updated for chain', { - chain, - related_chain_names: metrics.related_chain_names, - warp_route_id: metrics.warp_route_id, - token: metrics.token_name, - balance: balances[chain].balance, - }); - }); -} - -export function updateXERC20LimitsMetrics( - xERC20Limits: ChainMap, -) { - objMap(xERC20Limits, (chain: ChainName, limits: xERC20Limit | undefined) => { - if (limits) { - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'mint', - token_name: limits.tokenName, - }) - .set(limits.mint); - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'burn', - token_name: limits.tokenName, - }) - .set(limits.burn); - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'mintMax', - token_name: limits.tokenName, - }) - .set(limits.mintMax); - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'burnMax', - token_name: limits.tokenName, - }) - .set(limits.burnMax); - logger.info('xERC20 limits updated for chain', { - chain, - limits, - }); - } - }); -} - -async function getXERC20Limits( - tokenConfig: WarpRouteConfig, - chainMetadata: ChainMap, -): Promise> { - const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); - - const output = objMap( - tokenConfig, - async (chain: ChainName, token: WarpRouteConfig[ChainName]) => { - switch (token.protocolType) { - case ProtocolType.Ethereum: { - switch (token.type) { - case TokenType.XERC20Lockbox: { - const provider = multiProtocolProvider.getEthersV5Provider(chain); - const routerAddress = token.hypAddress; - const lockbox = HypXERC20Lockbox__factory.connect( - token.hypAddress, - provider, - ); - const xerc20Address = await lockbox.xERC20(); - const xerc20 = IXERC20__factory.connect(xerc20Address, provider); - return getXERC20Limit( - routerAddress, - xerc20, - token.decimals, - token.name, - ); - } - case TokenType.XERC20: { - const provider = multiProtocolProvider.getEthersV5Provider(chain); - const routerAddress = token.hypAddress; - const hypXERC20 = HypXERC20__factory.connect( - routerAddress, - provider, - ); - const xerc20Address = await hypXERC20.wrappedToken(); - const xerc20 = IXERC20__factory.connect(xerc20Address, provider); - return getXERC20Limit( - routerAddress, - xerc20, - token.decimals, - token.name, - ); - } - default: - logger.info( - `Unsupported token type ${token.type} for xERC20 limits check on protocol type ${token.protocolType}`, - ); - - return undefined; - } - } - default: - throw new Error(`Unsupported protocol type ${token.protocolType}`); - } - }, - ); - - return promiseObjAll(output); -} - -const getXERC20Limit = async ( - routerAddress: string, - xerc20: IXERC20, - decimals: number, - tokenName: string, -): Promise => { - const mintCurrent = await xerc20.mintingCurrentLimitOf(routerAddress); - const mintMax = await xerc20.mintingMaxLimitOf(routerAddress); - const burnCurrent = await xerc20.burningCurrentLimitOf(routerAddress); - const burnMax = await xerc20.burningMaxLimitOf(routerAddress); - return { - tokenName, - mint: parseFloat(ethers.utils.formatUnits(mintCurrent, decimals)), - mintMax: parseFloat(ethers.utils.formatUnits(mintMax, decimals)), - burn: parseFloat(ethers.utils.formatUnits(burnCurrent, decimals)), - burnMax: parseFloat(ethers.utils.formatUnits(burnMax, decimals)), - }; -}; - -async function getTokenPriceByChain( - chain: ChainName, - tokenPriceGetter: CoinGeckoTokenPriceGetter, -): Promise { - try { - return await tokenPriceGetter.getTokenPrice(chain); - } catch (e) { - logger.warn('Error getting token price', e); - return undefined; - } -} - -async function getNativeTokenValue( - chain: ChainName, - balanceFloat: number, - tokenPriceGetter: CoinGeckoTokenPriceGetter, -): Promise { - const price = await getTokenPriceByChain(chain, tokenPriceGetter); - logger.debug(`${chain} native token price ${price}`); - if (!price) return undefined; - return balanceFloat * price; -} - -async function getNativeTokenWarpInfo( - balance: ethers.BigNumber | bigint, - decimal: number, - tokenPriceGetter: CoinGeckoTokenPriceGetter, - chain: ChainName, -): Promise { - const balanceFloat = parseFloat(ethers.utils.formatUnits(balance, decimal)); - const value = await getNativeTokenValue( - chain, - balanceFloat, - tokenPriceGetter, - ); - return { balance: balanceFloat, valueUSD: value }; -} - -async function getCollateralTokenPrice( - tokenCoinGeckoId: string | undefined, - tokenPriceGetter: CoinGeckoTokenPriceGetter, -): Promise { - if (!tokenCoinGeckoId) return undefined; - const prices = await tokenPriceGetter.getTokenPriceByIds([tokenCoinGeckoId]); - if (!prices) return undefined; - return prices[0]; -} - -async function getCollateralTokenValue( - tokenCoinGeckoId: string | undefined, - balanceFloat: number, - tokenPriceGetter: CoinGeckoTokenPriceGetter, -): Promise { - const price = await getCollateralTokenPrice( - tokenCoinGeckoId, - tokenPriceGetter, - ); - logger.debug(`${tokenCoinGeckoId} token price ${price}`); - if (!price) return undefined; - return balanceFloat * price; -} - -async function getCollateralTokenWarpInfo( - balance: ethers.BigNumber | bigint, - decimal: number, - tokenPriceGetter: CoinGeckoTokenPriceGetter, - tokenCoinGeckoId?: string, -): Promise { - const balanceFloat = parseFloat(ethers.utils.formatUnits(balance, decimal)); - const value = await getCollateralTokenValue( - tokenCoinGeckoId, - balanceFloat, - tokenPriceGetter, - ); - return { balance: balanceFloat, valueUSD: value }; -} - -async function checkWarpRouteMetrics( - checkFrequency: number, - tokenConfig: WarpRouteConfig, - chainMetadata: ChainMap, -) { - const tokenPriceGetter = new CoinGeckoTokenPriceGetter({ - chainMetadata, - apiKey: await getCoinGeckoApiKey(), - }); - - setInterval(async () => { - try { - const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); - const balances = await checkBalance( - tokenConfig, - multiProtocolProvider, - tokenPriceGetter, - ); - logger.info('Token Balances:', balances); - updateTokenBalanceMetrics(tokenConfig, balances); - } catch (e) { - logger.error('Error checking balances', e); - } - - // only check xERC20 limits if there are xERC20 tokens in the config - if ( - Object.keys(tokenConfig).some( - (chain) => - tokenConfig[chain].type === TokenType.XERC20 || - tokenConfig[chain].type === TokenType.XERC20Lockbox, - ) - ) { - try { - const xERC20Limits = await getXERC20Limits(tokenConfig, chainMetadata); - logger.info('xERC20 Limits:', xERC20Limits); - updateXERC20LimitsMetrics(xERC20Limits); - } catch (e) { - logger.error('Error checking xERC20 limits', e); - } - } - }, checkFrequency); -} - -async function getCoinGeckoApiKey(): Promise { - const environment: DeployEnvironment = 'mainnet3'; - let apiKey: string | undefined; - try { - apiKey = (await fetchGCPSecret( - `${environment}-coingecko-api-key`, - false, - )) as string; - } catch (e) { - logger.error( - 'Error fetching CoinGecko API key, proceeding with public tier', - e, - ); - } - - return apiKey; -} - -main().then(logger.info).catch(logger.error); diff --git a/typescript/infra/scripts/warp-routes/monitor/metrics.ts b/typescript/infra/scripts/warp-routes/monitor/metrics.ts new file mode 100644 index 000000000..7f832b512 --- /dev/null +++ b/typescript/infra/scripts/warp-routes/monitor/metrics.ts @@ -0,0 +1,105 @@ +import { Gauge, Registry } from 'prom-client'; + +import { createWarpRouteConfigId } from '@hyperlane-xyz/registry'; +import { ChainName, Token, TokenStandard, WarpCore } from '@hyperlane-xyz/sdk'; + +import { WarpRouteBalance, XERC20Limit } from './types.js'; +import { logger } from './utils.js'; + +export const metricsRegister = new Registry(); + +type WarpRouteMetricLabels = keyof WarpRouteMetrics; + +interface WarpRouteMetrics { + chain_name: ChainName; + token_address: string; + token_name: string; + wallet_address: string; + token_standard: TokenStandard; + warp_route_id: string; + related_chain_names: string; +} + +const warpRouteMetricLabels: WarpRouteMetricLabels[] = [ + 'chain_name', + 'token_address', + 'token_name', + 'wallet_address', + 'token_standard', + 'warp_route_id', + 'related_chain_names', +]; + +const warpRouteTokenBalance = new Gauge({ + name: 'hyperlane_warp_route_token_balance', + help: 'HypERC20 token balance of a Warp Route', + registers: [metricsRegister], + labelNames: warpRouteMetricLabels, +}); + +const warpRouteCollateralValue = new Gauge({ + name: 'hyperlane_warp_route_collateral_value', + help: 'Total value of collateral held in a HypERC20Collateral or HypNative contract of a Warp Route', + registers: [metricsRegister], + labelNames: warpRouteMetricLabels, +}); + +const xERC20LimitsGauge = new Gauge({ + name: 'hyperlane_xerc20_limits', + help: 'Current minting and burning limits of xERC20 tokens', + registers: [metricsRegister], + labelNames: ['chain_name', 'limit_type', 'token_name'], +}); + +export function updateTokenBalanceMetrics( + warpCore: WarpCore, + token: Token, + balanceInfo: WarpRouteBalance, +) { + const metrics: WarpRouteMetrics = { + chain_name: token.chainName, + token_address: token.collateralAddressOrDenom || token.addressOrDenom, + token_name: token.name, + wallet_address: token.addressOrDenom, + token_standard: token.standard, + warp_route_id: createWarpRouteConfigId( + token.symbol, + warpCore.getTokenChains(), + ), + related_chain_names: warpCore + .getTokenChains() + .filter((chainName) => chainName !== token.chainName) + .sort() + .join(','), + }; + + warpRouteTokenBalance.labels(metrics).set(balanceInfo.balance); + logger.info('Wallet balance updated for token', { + labels: metrics, + balance: balanceInfo.balance, + }); + + if (balanceInfo.valueUSD) { + warpRouteCollateralValue.labels(metrics).set(balanceInfo.valueUSD); + logger.info('Wallet balance updated for token', { + labels: metrics, + valueUSD: balanceInfo.valueUSD, + }); + } +} + +export function updateXERC20LimitsMetrics(token: Token, limits: XERC20Limit) { + for (const [limitType, limit] of Object.entries(limits)) { + xERC20LimitsGauge + .labels({ + chain_name: token.chainName, + limit_type: limitType, + token_name: token.name, + }) + .set(limit); + } + logger.info('xERC20 limits updated for chain', { + chain: token.chainName, + limits, + }); +} diff --git a/typescript/infra/scripts/warp-routes/monitor/monitor-warp-route-balances.ts b/typescript/infra/scripts/warp-routes/monitor/monitor-warp-route-balances.ts new file mode 100644 index 000000000..f9af0039d --- /dev/null +++ b/typescript/infra/scripts/warp-routes/monitor/monitor-warp-route-balances.ts @@ -0,0 +1,254 @@ +import { PopulatedTransaction } from 'ethers'; + +import { + ChainMap, + ChainMetadata, + CoinGeckoTokenPriceGetter, + EvmHypXERC20Adapter, + EvmHypXERC20LockboxAdapter, + IHypXERC20Adapter, + MultiProtocolProvider, + RouterConfig, + Token, + TokenStandard, + WarpCore, +} from '@hyperlane-xyz/sdk'; +import { ProtocolType, objMap, objMerge } from '@hyperlane-xyz/utils'; + +import { getWarpCoreConfig } from '../../../config/registry.js'; +import { + DeployEnvironment, + getRouterConfigsForAllVms, +} from '../../../src/config/environment.js'; +import { fetchGCPSecret } from '../../../src/utils/gcloud.js'; +import { startMetricsServer } from '../../../src/utils/metrics.js'; +import { getArgs, withWarpRouteIdRequired } from '../../agent-utils.js'; +import { getEnvironmentConfig } from '../../core-utils.js'; + +import { + metricsRegister, + updateTokenBalanceMetrics, + updateXERC20LimitsMetrics, +} from './metrics.js'; +import { WarpRouteBalance, XERC20Limit } from './types.js'; +import { logger, tryFn } from './utils.js'; + +async function main() { + const { checkFrequency, environment, warpRouteId } = + await withWarpRouteIdRequired(getArgs()) + .describe('checkFrequency', 'frequency to check balances in ms') + .demandOption('checkFrequency') + .alias('v', 'checkFrequency') // v as in Greek letter nu + .number('checkFrequency') + .parse(); + + startMetricsServer(metricsRegister); + + const envConfig = getEnvironmentConfig(environment); + const registry = await envConfig.getRegistry(); + const chainMetadata = await registry.getMetadata(); + + // The Sealevel warp adapters require the Mailbox address, so we + // get router configs (that include the Mailbox address) for all chains + // and merge them with the chain metadata. + const routerConfig = await getRouterConfigsForAllVms( + envConfig, + await envConfig.getMultiProvider(), + ); + const mailboxes = objMap(routerConfig, (_chain, config: RouterConfig) => ({ + mailbox: config.mailbox, + })); + const multiProtocolProvider = new MultiProtocolProvider( + objMerge(chainMetadata, mailboxes), + ); + const warpCoreConfig = getWarpCoreConfig(warpRouteId); + const warpCore = WarpCore.FromConfig(multiProtocolProvider, warpCoreConfig); + + await pollAndUpdateWarpRouteMetrics(checkFrequency, warpCore, chainMetadata); +} + +// Indefinitely loops, updating warp route metrics at the specified frequency. +async function pollAndUpdateWarpRouteMetrics( + checkFrequency: number, + warpCore: WarpCore, + chainMetadata: ChainMap, +) { + const tokenPriceGetter = new CoinGeckoTokenPriceGetter({ + chainMetadata, + apiKey: await getCoinGeckoApiKey(), + }); + + setInterval(async () => { + await tryFn(async () => { + await Promise.all( + warpCore.tokens.map((token) => + updateTokenMetrics(warpCore, token, tokenPriceGetter), + ), + ); + }, 'Updating warp route metrics'); + }, checkFrequency); +} + +// Updates the metrics for a single token in a warp route. +async function updateTokenMetrics( + warpCore: WarpCore, + token: Token, + tokenPriceGetter: CoinGeckoTokenPriceGetter, +) { + const promises = [ + tryFn(async () => { + const balanceInfo = await getTokenBridgedBalance( + warpCore, + token, + tokenPriceGetter, + ); + if (!balanceInfo) { + return; + } + updateTokenBalanceMetrics(warpCore, token, balanceInfo); + }, 'Getting bridged balance and value'), + ]; + + if (token.isXerc20()) { + promises.push( + tryFn(async () => { + const limits = await getXERC20Limits(warpCore, token); + updateXERC20LimitsMetrics(token, limits); + }, 'Getting xERC20 limits'), + ); + } + + await Promise.all(promises); +} + +// Gets the bridged balance and value of a token in a warp route. +async function getTokenBridgedBalance( + warpCore: WarpCore, + token: Token, + tokenPriceGetter: CoinGeckoTokenPriceGetter, +): Promise { + if (!token.isHypToken()) { + logger.warn('Cannot get bridged balance for a non-Hyperlane token', token); + return undefined; + } + + const adapter = token.getHypAdapter(warpCore.multiProvider); + const bridgedSupply = await adapter.getBridgedSupply(); + if (!bridgedSupply) { + logger.warn('Bridged supply not found for token', token); + return undefined; + } + const balance = token.amount(bridgedSupply).getDecimalFormattedAmount(); + + let tokenPrice; + // Only record value for collateralized and xERC20 lockbox tokens. + if ( + token.isCollateralized() || + token.standard === TokenStandard.EvmHypXERC20Lockbox + ) { + tokenPrice = await tryGetTokenPrice(token, tokenPriceGetter); + } + + return { + balance, + valueUSD: tokenPrice ? balance * tokenPrice : undefined, + }; +} + +async function getXERC20Limits( + warpCore: WarpCore, + token: Token, +): Promise { + if (token.protocol !== ProtocolType.Ethereum) { + throw new Error(`Unsupported XERC20 protocol type ${token.protocol}`); + } + + if (token.standard === TokenStandard.EvmHypXERC20) { + const adapter = token.getAdapter( + warpCore.multiProvider, + ) as EvmHypXERC20Adapter; + return getXERC20Limit(token, adapter); + } else if (token.standard === TokenStandard.EvmHypXERC20Lockbox) { + const adapter = token.getAdapter( + warpCore.multiProvider, + ) as EvmHypXERC20LockboxAdapter; + return getXERC20Limit(token, adapter); + } + throw new Error(`Unsupported XERC20 token standard ${token.standard}`); +} + +async function getXERC20Limit( + token: Token, + xerc20: IHypXERC20Adapter, +): Promise { + const formatBigInt = (num: bigint) => { + return token.amount(num).getDecimalFormattedAmount(); + }; + + const [mintCurrent, mintMax, burnCurrent, burnMax] = await Promise.all([ + xerc20.getMintLimit(), + xerc20.getMintMaxLimit(), + xerc20.getBurnLimit(), + xerc20.getBurnMaxLimit(), + ]); + + return { + mint: formatBigInt(mintCurrent), + mintMax: formatBigInt(mintMax), + burn: formatBigInt(burnCurrent), + burnMax: formatBigInt(burnMax), + }; +} + +// Tries to get the price of a token from CoinGecko. Returns undefined if there's no +// CoinGecko ID for the token. +async function tryGetTokenPrice( + token: Token, + tokenPriceGetter: CoinGeckoTokenPriceGetter, +): Promise { + // We only get a price if the token defines a CoinGecko ID. + // This way we can ignore values of certain types of collateralized warp routes, + // e.g. Native warp routes on rollups that have been pre-funded. + let coinGeckoId = token.coinGeckoId; + + if (!coinGeckoId) { + logger.warn('CoinGecko ID missing for token', token.symbol); + return undefined; + } + + return getCoingeckoPrice(tokenPriceGetter, coinGeckoId); +} + +async function getCoingeckoPrice( + tokenPriceGetter: CoinGeckoTokenPriceGetter, + coingeckoId: string, +): Promise { + const prices = await tokenPriceGetter.getTokenPriceByIds([coingeckoId]); + if (!prices) return undefined; + return prices[0]; +} + +async function getCoinGeckoApiKey(): Promise { + const environment: DeployEnvironment = 'mainnet3'; + let apiKey: string | undefined; + try { + apiKey = (await fetchGCPSecret( + `${environment}-coingecko-api-key`, + false, + )) as string; + } catch (e) { + logger.error( + 'Error fetching CoinGecko API key, proceeding with public tier', + e, + ); + } + + return apiKey; +} + +main() + .then(logger.info) + .catch((err) => { + logger.error('Error in main', err); + process.exit(1); + }); diff --git a/typescript/infra/scripts/warp-routes/monitor/types.ts b/typescript/infra/scripts/warp-routes/monitor/types.ts new file mode 100644 index 000000000..5a2d87749 --- /dev/null +++ b/typescript/infra/scripts/warp-routes/monitor/types.ts @@ -0,0 +1,11 @@ +export interface XERC20Limit { + mint: number; + burn: number; + mintMax: number; + burnMax: number; +} + +export interface WarpRouteBalance { + balance: number; + valueUSD?: number; +} diff --git a/typescript/infra/scripts/warp-routes/monitor/utils.ts b/typescript/infra/scripts/warp-routes/monitor/utils.ts new file mode 100644 index 000000000..414843416 --- /dev/null +++ b/typescript/infra/scripts/warp-routes/monitor/utils.ts @@ -0,0 +1,11 @@ +import { rootLogger } from '@hyperlane-xyz/utils'; + +export const logger = rootLogger.child({ module: 'warp-balance-monitor' }); + +export async function tryFn(fn: () => Promise, context: string) { + try { + await fn(); + } catch (e) { + logger.error(`Error in ${context}`, e); + } +} diff --git a/typescript/infra/src/warp/helm.ts b/typescript/infra/src/warp/helm.ts index 1db3dedce..019e9b5b2 100644 --- a/typescript/infra/src/warp/helm.ts +++ b/typescript/infra/src/warp/helm.ts @@ -11,7 +11,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager { ); constructor( - readonly configFilePath: string, + readonly warpRouteId: string, readonly runEnv: DeployEnvironment, readonly environmentChainNames: string[], ) { @@ -19,17 +19,12 @@ export class WarpRouteMonitorHelmManager extends HelmManager { } async helmValues() { - const pathRelativeToMonorepoRoot = this.configFilePath.includes( - 'typescript/infra', - ) - ? this.configFilePath - : path.join('typescript/infra', this.configFilePath); return { image: { repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: 'd3925b3-20241105-141649', + tag: '91aaa4a-20241108-204429', }, - configFilePath: pathRelativeToMonorepoRoot, + warpRouteId: this.warpRouteId, fullnameOverride: this.helmReleaseName, environment: this.runEnv, hyperlane: { @@ -43,8 +38,19 @@ export class WarpRouteMonitorHelmManager extends HelmManager { } get helmReleaseName(): string { - const match = this.configFilePath.match(/\/([^/]+)-deployments\.yaml$/); - const name = match ? match[1] : this.configFilePath; - return `hyperlane-warp-route-${name.toLowerCase()}`; // helm requires lower case release names + let name = `hyperlane-warp-route-${this.warpRouteId + .toLowerCase() + .replaceAll('/', '-')}`; + + // 52 because the max label length is 63, and there is an auto appended 11 char + // suffix, e.g. `controller-revision-hash=hyperlane-warp-route-tia-mantapacific-neutron-566dc75599` + const maxChars = 52; + + // Max out length, and it can't end with a dash. + if (name.length > maxChars) { + name = name.slice(0, maxChars); + name = name.replace(/-+$/, ''); + } + return name; } } diff --git a/typescript/infra/test/warpIds.test.ts b/typescript/infra/test/warpIds.test.ts new file mode 100644 index 000000000..ba171c5ba --- /dev/null +++ b/typescript/infra/test/warpIds.test.ts @@ -0,0 +1,15 @@ +import { expect } from 'chai'; + +import { WarpRouteIds } from '../config/environments/mainnet3/warp/warpIds.js'; +import { getRegistry } from '../config/registry.js'; + +describe('Warp IDs', () => { + it('Has all warp IDs in the registry', () => { + const registry = getRegistry(); + for (const warpId of Object.values(WarpRouteIds)) { + // That's a long sentence! + expect(registry.getWarpRoute(warpId), `Warp ID ${warpId} not in registry`) + .to.not.be.null.and.not.be.undefined; + } + }); +}); diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index ccc0a324f..75d74e5c8 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -420,11 +420,14 @@ export { EvmHypCollateralAdapter, EvmHypNativeAdapter, EvmHypSyntheticAdapter, + EvmHypXERC20Adapter, + EvmHypXERC20LockboxAdapter, EvmNativeTokenAdapter, EvmTokenAdapter, } from './token/adapters/EvmTokenAdapter.js'; export { IHypTokenAdapter, + IHypXERC20Adapter, ITokenAdapter, InterchainGasQuote, TransferParams, diff --git a/typescript/sdk/src/token/Token.ts b/typescript/sdk/src/token/Token.ts index 527adc2b5..b63915969 100644 --- a/typescript/sdk/src/token/Token.ts +++ b/typescript/sdk/src/token/Token.ts @@ -24,6 +24,7 @@ import { TOKEN_NFT_STANDARDS, TOKEN_STANDARD_TO_PROTOCOL, TokenStandard, + XERC20_STANDARDS, } from './TokenStandard.js'; import { CwHypCollateralAdapter, @@ -353,10 +354,18 @@ export class Token implements IToken { return Object.values(PROTOCOL_TO_NATIVE_STANDARD).includes(this.standard); } + isCollateralized(): boolean { + return TOKEN_COLLATERALIZED_STANDARDS.includes(this.standard); + } + isHypToken(): boolean { return TOKEN_HYP_STANDARDS.includes(this.standard); } + isXerc20(): boolean { + return XERC20_STANDARDS.includes(this.standard); + } + isIbcToken(): boolean { return this.standard === TokenStandard.CosmosIbc; } @@ -417,7 +426,7 @@ export class Token implements IToken { if (this.equals(token)) return true; - if (TOKEN_COLLATERALIZED_STANDARDS.includes(this.standard)) { + if (this.isCollateralized()) { if ( this.collateralAddressOrDenom && eqAddress(this.collateralAddressOrDenom, token.addressOrDenom) diff --git a/typescript/sdk/src/token/TokenStandard.ts b/typescript/sdk/src/token/TokenStandard.ts index ee434b777..690096a43 100644 --- a/typescript/sdk/src/token/TokenStandard.ts +++ b/typescript/sdk/src/token/TokenStandard.ts @@ -108,11 +108,13 @@ export const TOKEN_COLLATERALIZED_STANDARDS = [ TokenStandard.CwHypNative, ]; -export const MINT_LIMITED_STANDARDS = [ +export const XERC20_STANDARDS = [ TokenStandard.EvmHypXERC20, TokenStandard.EvmHypXERC20Lockbox, ]; +export const MINT_LIMITED_STANDARDS = [...XERC20_STANDARDS]; + export const TOKEN_HYP_STANDARDS = [ TokenStandard.EvmHypNative, TokenStandard.EvmHypCollateral, diff --git a/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts b/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts index 10f32e5b0..e472133bd 100644 --- a/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts @@ -90,6 +90,11 @@ export class CwNativeTokenAdapter ], }; } + + async getTotalSupply(): Promise { + // Not implemented. + return undefined; + } } export type CW20Metadata = TokenMetadata; @@ -172,6 +177,11 @@ export class CwTokenAdapter }, }); } + + async getTotalSupply(): Promise { + // Not implemented. + return undefined; + } } type TokenRouterResponse = @@ -274,6 +284,10 @@ export class CwHypSyntheticAdapter })); } + getBridgedSupply(): Promise { + return this.getTotalSupply(); + } + async quoteTransferRemoteGas( _destination: Domain, ): Promise { @@ -366,6 +380,10 @@ export class CwHypNativeAdapter return this.cw20adapter.getAllRouters(); } + getBridgedSupply(): Promise { + return this.getBalance(this.addresses.warpRouter); + } + quoteTransferRemoteGas(destination: Domain): Promise { return this.cw20adapter.quoteTransferRemoteGas(destination); } diff --git a/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts b/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts index 73f094b94..06ea3dde1 100644 --- a/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts @@ -61,6 +61,11 @@ export class CosmNativeTokenAdapter ): Promise { throw new Error('TODO not yet implemented'); } + + async getTotalSupply(): Promise { + // Not implemented. + return undefined; + } } // Interacts with native tokens on a Cosmos chain and adds support for IBC transfers @@ -103,6 +108,11 @@ export class CosmIbcTokenAdapter > { throw new Error('Method not applicable to IBC adapters'); } + + getBridgedSupply(): Promise { + throw new Error('Method not applicable to IBC adapters'); + } + async quoteTransferRemoteGas( _destination: Domain, ): Promise { diff --git a/typescript/sdk/src/token/adapters/EvmTokenAdapter.ts b/typescript/sdk/src/token/adapters/EvmTokenAdapter.ts index 885cdad2f..794d5cdff 100644 --- a/typescript/sdk/src/token/adapters/EvmTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/EvmTokenAdapter.ts @@ -11,6 +11,7 @@ import { HypXERC20Lockbox, HypXERC20Lockbox__factory, HypXERC20__factory, + IXERC20, IXERC20__factory, } from '@hyperlane-xyz/core'; import { @@ -77,6 +78,11 @@ export class EvmNativeTokenAdapter const value = BigNumber.from(weiAmountOrId.toString()); return { value, to: recipient }; } + + async getTotalSupply(): Promise { + // Not implemented, native tokens don't have an accessible total supply + return undefined; + } } // Interacts with ERC20/721 contracts @@ -109,7 +115,7 @@ export class EvmTokenAdapter isNft ? 0 : this.contract.decimals(), this.contract.symbol(), this.contract.name(), - this.contract.totalSupply(), + this.getTotalSupply(), ]); return { decimals, symbol, name, totalSupply: totalSupply.toString() }; } @@ -142,6 +148,11 @@ export class EvmTokenAdapter weiAmountOrId.toString(), ); } + + async getTotalSupply(): Promise { + const totalSupply = await this.contract.totalSupply(); + return totalSupply.toBigInt(); + } } // Interacts with Hyp Synthetic token contracts (aka 'HypTokens') @@ -192,6 +203,10 @@ export class EvmHypSyntheticAdapter return domains.map((d, i) => ({ domain: d, address: routers[i] })); } + getBridgedSupply(): Promise { + return this.getTotalSupply(); + } + async quoteTransferRemoteGas( destination: Domain, ): Promise { @@ -254,6 +269,10 @@ export class EvmHypCollateralAdapter }); } + override getBridgedSupply(): Promise { + return this.getBalance(this.addresses.token); + } + override getMetadata(isNft?: boolean): Promise { return this.getWrappedTokenAdapter().then((t) => t.getMetadata(isNft)); } @@ -305,26 +324,44 @@ export class EvmHypXERC20LockboxAdapter ); } - async getMintLimit(): Promise { - const xERC20 = await this.hypXERC20Lockbox.xERC20(); + /** + * Note this may be inaccurate, as this returns the balance + * of the lockbox contract, which may be used by other bridges. + * However this is the best we can do with a simple view call. + */ + override async getBridgedSupply(): Promise { + const lockboxAddress = await this.hypXERC20Lockbox.lockbox(); + return this.getBalance(lockboxAddress); + } - const limit = await IXERC20__factory.connect( - xERC20, - this.getProvider(), - ).mintingCurrentLimitOf(this.contract.address); + async getMintLimit(): Promise { + const xERC20 = await this.getXErc20(); + const limit = await xERC20.mintingCurrentLimitOf(this.contract.address); + return limit.toBigInt(); + } - return BigInt(limit.toString()); + async getMintMaxLimit(): Promise { + const xERC20 = await this.getXErc20(); + const limit = await xERC20.mintingMaxLimitOf(this.contract.address); + return limit.toBigInt(); } async getBurnLimit(): Promise { - const xERC20 = await this.hypXERC20Lockbox.xERC20(); + const xERC20 = await this.getXErc20(); + const limit = await xERC20.burningCurrentLimitOf(this.contract.address); + return limit.toBigInt(); + } - const limit = await IXERC20__factory.connect( - xERC20, - this.getProvider(), - ).mintingCurrentLimitOf(this.contract.address); + async getBurnMaxLimit(): Promise { + const xERC20 = await this.getXErc20(); + const limit = await xERC20.burningMaxLimitOf(this.contract.address); + return limit.toBigInt(); + } + + async getXErc20(): Promise { + const xERC20 = await this.hypXERC20Lockbox.xERC20(); - return BigInt(limit.toString()); + return IXERC20__factory.connect(xERC20, this.getProvider()); } } @@ -348,26 +385,47 @@ export class EvmHypXERC20Adapter ); } - async getMintLimit(): Promise { - const xERC20 = await this.hypXERC20.wrappedToken(); + /** + * Note this may be inaccurate, as this returns the total supply + * of the xERC20 contract, which may be used by other bridges. + * However this is the best we can do with a simple view call. + */ + override async getBridgedSupply(): Promise { + const xerc20TokenAddress = await this.hypXERC20.wrappedToken(); + const xerc20 = new EvmTokenAdapter(this.chainName, this.multiProvider, { + token: xerc20TokenAddress, + }); + return xerc20.getTotalSupply(); + } - const limit = await IXERC20__factory.connect( - xERC20, - this.getProvider(), - ).mintingCurrentLimitOf(this.contract.address); + async getMintLimit(): Promise { + const xERC20 = await this.getXErc20(); + const limit = await xERC20.mintingCurrentLimitOf(this.contract.address); + return limit.toBigInt(); + } - return BigInt(limit.toString()); + async getMintMaxLimit(): Promise { + const xERC20 = await this.getXErc20(); + const limit = await xERC20.mintingMaxLimitOf(this.contract.address); + return limit.toBigInt(); } async getBurnLimit(): Promise { - const xERC20 = await this.hypXERC20.wrappedToken(); + const xERC20 = await this.getXErc20(); + const limit = await xERC20.burningCurrentLimitOf(this.contract.address); + return limit.toBigInt(); + } - const limit = await IXERC20__factory.connect( - xERC20, - this.getProvider(), - ).burningCurrentLimitOf(this.contract.address); + async getBurnMaxLimit(): Promise { + const xERC20 = await this.getXErc20(); + const limit = await xERC20.burningMaxLimitOf(this.contract.address); + return limit.toBigInt(); + } + + async getXErc20(): Promise { + const xERC20 = await this.hypXERC20.wrappedToken(); - return BigInt(limit.toString()); + return IXERC20__factory.connect(xERC20, this.getProvider()); } } diff --git a/typescript/sdk/src/token/adapters/ITokenAdapter.ts b/typescript/sdk/src/token/adapters/ITokenAdapter.ts index f0a8032d5..d989fb709 100644 --- a/typescript/sdk/src/token/adapters/ITokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/ITokenAdapter.ts @@ -23,6 +23,7 @@ export interface InterchainGasQuote { export interface ITokenAdapter { getBalance(address: Address): Promise; + getTotalSupply(): Promise; getMetadata(isNft?: boolean): Promise; isApproveRequired( owner: Address, @@ -37,11 +38,15 @@ export interface IHypTokenAdapter extends ITokenAdapter { getDomains(): Promise; getRouterAddress(domain: Domain): Promise; getAllRouters(): Promise>; + getBridgedSupply(): Promise; quoteTransferRemoteGas(destination: Domain): Promise; populateTransferRemoteTx(p: TransferRemoteParams): Promise; } export interface IHypXERC20Adapter extends IHypTokenAdapter { getMintLimit(): Promise; + getMintMaxLimit(): Promise; + getBurnLimit(): Promise; + getBurnMaxLimit(): Promise; } diff --git a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts index 1df0d8637..788fa5f91 100644 --- a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts @@ -113,6 +113,11 @@ export class SealevelNativeTokenAdapter }), ); } + + async getTotalSupply(): Promise { + // Not implemented. + return undefined; + } } // Interacts with SPL token programs @@ -190,6 +195,13 @@ export class SealevelTokenAdapter this.getTokenProgramId(), ); } + + async getTotalSupply(): Promise { + const response = await this.getProvider().getTokenSupply( + this.tokenMintPubKey, + ); + return BigInt(response.value.amount); + } } interface HypTokenAddresses { @@ -266,6 +278,11 @@ export abstract class SealevelHypTokenAdapter })); } + // Intended to be overridden by subclasses + async getBridgedSupply(): Promise { + return undefined; + } + async quoteTransferRemoteGas( _destination: Domain, ): Promise { @@ -581,6 +598,10 @@ export class SealevelHypNativeAdapter extends SealevelHypTokenAdapter { return this.wrappedNative.getBalance(owner); } + override async getBridgedSupply(): Promise { + return this.getBalance(this.addresses.warpRouter); + } + override async getMetadata(): Promise { return this.wrappedNative.getMetadata(); } @@ -632,6 +653,10 @@ export class SealevelHypCollateralAdapter extends SealevelHypTokenAdapter { return super.getBalance(owner); } + override async getBridgedSupply(): Promise { + return this.getBalance(this.addresses.warpRouter); + } + override getTransferInstructionKeyList( params: KeyListParams, ): Array { @@ -697,6 +722,10 @@ export class SealevelHypSyntheticAdapter extends SealevelHypTokenAdapter { } } + override async getBridgedSupply(): Promise { + return this.getTotalSupply(); + } + async getTotalSupply(): Promise { const response = await this.getProvider().getTokenSupply( this.tokenMintPubKey,