From 0e16072d5955b91b10dd9723992bc7183e34bea9 Mon Sep 17 00:00:00 2001
From: Canh Trinh <canhtrinh@users.noreply.github.com>
Date: Thu, 17 Oct 2024 23:14:42 -0400
Subject: [PATCH] feat: update sdk to support Amplifier chains (#334)

Co-authored-by: npty <78221556+npty@users.noreply.github.com>
---
 CHANGELOG.md                                  |  5 ++++
 package.json                                  |  2 +-
 src/assets/index.ts                           |  8 +++--
 src/chains/index.ts                           | 29 +++++++++++++++++--
 src/chains/types/index.ts                     |  2 +-
 src/libs/AxelarQueryAPI.ts                    |  1 -
 .../AxelarGMPRecoveryAPI.ts                   | 12 ++++----
 .../constants/cosmosGasReceiverOptions.ts     |  2 +-
 .../TransactionRecoveryApi/constants/s3.ts    |  2 +-
 src/libs/test/AxelarQueryAPI.spec.ts          | 14 +++++++++
 src/libs/test/stubs/index.ts                  |  2 +-
 src/libs/types/index.ts                       |  2 +-
 src/utils/validateChain.ts                    | 28 ++++++++++++++++--
 test/e2e/data/index.ts                        |  4 +--
 .../parts/01.deposit-address.spec.ts          |  2 +-
 15 files changed, 92 insertions(+), 23 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index af71ad57..a55bcfc1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
+## [0.17.0] - 2024-OCTOBER-18
+
+- Fixed the error when trying to add gas for cosmos source chain from the axelarscan ui. #333
+- update SDK to support Amplifier chains #334
+
 ## [0.16.1] - 2024-MAY-31
 
 - Add Linea and Polygon Sepolia chains to testnet
diff --git a/package.json b/package.json
index 062888cf..4c5b4f63 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@axelar-network/axelarjs-sdk",
-  "version": "0.16.2",
+  "version": "0.17.0",
   "description": "The JavaScript SDK for Axelar Network",
   "repository": {
     "type": "git",
diff --git a/src/assets/index.ts b/src/assets/index.ts
index 1091c12f..41a214dd 100644
--- a/src/assets/index.ts
+++ b/src/assets/index.ts
@@ -3,11 +3,15 @@ import { AssetConfig, LoadAssetConfig } from "./types";
 import { Environment } from "../libs";
 
 const urlMap: Record<Environment, string> = {
-  devnet: "https://axelar-testnet.s3.us-east-2.amazonaws.com/devnet-asset-config.json",
+  "devnet-amplifier": "https://axelar-testnet.s3.us-east-2.amazonaws.com/devnet-asset-config.json",
   testnet: "https://axelar-testnet.s3.us-east-2.amazonaws.com/testnet-asset-config.json",
   mainnet: "https://axelar-mainnet.s3.us-east-2.amazonaws.com/mainnet-asset-config.json",
 };
-const assetMap: Record<Environment, any> = { devnet: null, testnet: null, mainnet: null };
+const assetMap: Record<Environment, any> = {
+  "devnet-amplifier": null,
+  testnet: null,
+  mainnet: null,
+};
 
 export async function loadAssets(config: LoadAssetConfig): Promise<AssetConfig[]> {
   if (assetMap[config.environment]) return Object.values(assetMap[config.environment]);
diff --git a/src/chains/index.ts b/src/chains/index.ts
index 8d13dc25..e52069d3 100644
--- a/src/chains/index.ts
+++ b/src/chains/index.ts
@@ -39,12 +39,37 @@ export async function loadChains(config: LoadChainConfig) {
   return rawChains;
 }
 
+const s3UrlMap: Record<Environment, string> = {
+  "devnet-amplifier":
+    "https://axelar-devnet-amplifier.s3.us-east-2.amazonaws.com/configs/devnet-amplifier-config-1.x.json",
+  testnet: "https://axelar-testnet.s3.us-east-2.amazonaws.com/configs/testnet-config-1.x.json",
+  mainnet: "https://axelar-mainnet.s3.us-east-2.amazonaws.com/configs/mainnet-config-1.x.json",
+};
+
 const urlMap: Record<Environment, string> = {
-  devnet: "https://axelar-testnet.s3.us-east-2.amazonaws.com/devnet-chain-config.json",
+  "devnet-amplifier": "https://axelar-testnet.s3.us-east-2.amazonaws.com/devnet-chain-config.json",
   testnet: "https://axelar-testnet.s3.us-east-2.amazonaws.com/testnet-chain-config.json",
   mainnet: "https://axelar-mainnet.s3.us-east-2.amazonaws.com/mainnet-chain-config.json",
 };
-const chainMap: Record<Environment, any> = { devnet: null, testnet: null, mainnet: null };
+const chainMap: Record<Environment, any> = {
+  "devnet-amplifier": null,
+  testnet: null,
+  mainnet: null,
+};
+
+const s3Map: Record<Environment, any> = {
+  "devnet-amplifier": null,
+  testnet: null,
+  mainnet: null,
+};
+
+export async function importS3Config(environment: Environment): Promise<any> {
+  if (s3Map[environment]) return s3Map[environment];
+
+  s3Map[environment] = await execGet(s3UrlMap[environment]);
+
+  return s3Map[environment];
+}
 
 export async function importChains(config: LoadChainConfig): Promise<ChainInfo[]> {
   if (chainMap[config.environment]) return Object.values(chainMap[config.environment]);
diff --git a/src/chains/types/index.ts b/src/chains/types/index.ts
index d645e67f..a0a28641 100644
--- a/src/chains/types/index.ts
+++ b/src/chains/types/index.ts
@@ -25,7 +25,7 @@ export interface ChainInfo {
   module: "axelarnet" | "evm";
   confirmLevel?: number;
   chainIdentifier: {
-    devnet: string;
+    "devnet-amplifier": string;
     testnet: string;
     mainnet: string;
   };
diff --git a/src/libs/AxelarQueryAPI.ts b/src/libs/AxelarQueryAPI.ts
index c3361cb9..858a3206 100644
--- a/src/libs/AxelarQueryAPI.ts
+++ b/src/libs/AxelarQueryAPI.ts
@@ -195,7 +195,6 @@ export class AxelarQueryAPI {
     amountInUnits?: BigNumber | string
   ): Promise<BaseFeeResponse> {
     await throwIfInvalidChainIds([sourceChainId, destinationChainId], this.environment);
-    await this.throwIfInactiveChains([sourceChainId, destinationChainId]);
 
     const params: {
       method: string;
diff --git a/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts b/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts
index 1ff57367..703757e4 100644
--- a/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts
+++ b/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts
@@ -889,17 +889,15 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi {
       };
     }
 
-    const denomOnSrcChain = getIBCDenomOnSrcChain(
-      tx.gas_paid?.returnValues?.denom,
-      chainConfig,
-      chainConfigs
-    );
+    const denom = tx.gas_paid?.returnValues?.asset;
+
+    const denomOnSrcChain = getIBCDenomOnSrcChain(denom, chainConfig, chainConfigs);
 
     if (!matchesOriginalTokenPayment(params.token, denomOnSrcChain)) {
       return {
         success: false,
         info: `The token you are trying to send does not match the token originally \
-          used for gas payment. Please send ${tx.gas_paid?.returnValues?.denom} instead`,
+          used for gas payment. Please send ${denom} instead`,
       };
     }
 
@@ -913,7 +911,7 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi {
               tx.call.returnValues.destinationChain,
               gasLimit,
               autocalculateGasOptions?.gasMultipler,
-              tx.gas_paid?.returnValues?.denom ?? "uaxl"
+              denom ?? "uaxl"
             ),
           };
 
diff --git a/src/libs/TransactionRecoveryApi/constants/cosmosGasReceiverOptions.ts b/src/libs/TransactionRecoveryApi/constants/cosmosGasReceiverOptions.ts
index a4e357d5..60eb6ffd 100644
--- a/src/libs/TransactionRecoveryApi/constants/cosmosGasReceiverOptions.ts
+++ b/src/libs/TransactionRecoveryApi/constants/cosmosGasReceiverOptions.ts
@@ -1,5 +1,5 @@
 export const COSMOS_GAS_RECEIVER_OPTIONS = {
-  devnet: "axelar1zl3rxpp70lmte2xr6c4lgske2fyuj3hupcsvcd",
+  "devnet-amplifier": "axelar1zl3rxpp70lmte2xr6c4lgske2fyuj3hupcsvcd",
   testnet: "axelar1zl3rxpp70lmte2xr6c4lgske2fyuj3hupcsvcd",
   mainnet: "axelar1aythygn6z5thymj6tmzfwekzh05ewg3l7d6y89",
 } as const;
diff --git a/src/libs/TransactionRecoveryApi/constants/s3.ts b/src/libs/TransactionRecoveryApi/constants/s3.ts
index a3019941..495b6c04 100644
--- a/src/libs/TransactionRecoveryApi/constants/s3.ts
+++ b/src/libs/TransactionRecoveryApi/constants/s3.ts
@@ -1,5 +1,5 @@
 export default {
   mainnet: "https://axelar-mainnet.s3.us-east-2.amazonaws.com/mainnet-config.json",
   testnet: "https://axelar-testnet.s3.us-east-2.amazonaws.com/testnet-config.json",
-  devnet: "https://axelar-testnet.s3.us-east-2.amazonaws.com/testnet-config.json", //same as testnet for now
+  "devnet-amplifier": "https://axelar-testnet.s3.us-east-2.amazonaws.com/testnet-config.json", //same as testnet for now
 };
diff --git a/src/libs/test/AxelarQueryAPI.spec.ts b/src/libs/test/AxelarQueryAPI.spec.ts
index af6035de..8532bf2b 100644
--- a/src/libs/test/AxelarQueryAPI.spec.ts
+++ b/src/libs/test/AxelarQueryAPI.spec.ts
@@ -264,6 +264,20 @@ describe("AxelarQueryAPI", () => {
       // gasAmount should be greater than 0.0000001, otherwise we handle decimal conversion incorrectly.
       expect(ethers.utils.parseEther("0.0000001").lt(gasAmount as BigNumberish)).toBeTruthy();
     });
+    test("It should return estimated gas amount for an Amplifier chain", async () => {
+      const gasAmount = await api.estimateGasFee(
+        CHAINS.TESTNET.AVALANCHE as EvmChain,
+        "flow",
+        700000,
+        1.1,
+        undefined,
+        "5000000000"
+      );
+
+      // gasAmount should be greater than 0.0000001, otherwise we handle decimal conversion incorrectly.
+      expect(ethers.utils.parseEther("0.0000001").lt(gasAmount as BigNumberish)).toBeTruthy();
+    });
+
     // TODO: fix this test. Potential rounding issue
     test.skip("It should use `minGasPrice` if it is greater than the destination chain's gas_price returned from the api", async () => {
       const feeStub = getFeeStub();
diff --git a/src/libs/test/stubs/index.ts b/src/libs/test/stubs/index.ts
index b45897ed..9a9fc028 100644
--- a/src/libs/test/stubs/index.ts
+++ b/src/libs/test/stubs/index.ts
@@ -170,7 +170,7 @@ export const chainInfoStub = () => ({
   txFeeInPercent: 0.1,
   module: "axelarnet",
   chainIdentifier: {
-    devnet: "mockedDevnet",
+    "devnet-amplifier": "mockedDevnet",
     testnet: "mockedTestnet",
     mainnet: "mockedMainnet",
   },
diff --git a/src/libs/types/index.ts b/src/libs/types/index.ts
index d1ee94da..099cbe43 100644
--- a/src/libs/types/index.ts
+++ b/src/libs/types/index.ts
@@ -9,7 +9,7 @@ import { GasToken } from "../../constants/GasToken";
 import { EvmChain } from "../../constants/EvmChain";
 
 export enum Environment {
-  DEVNET = "devnet",
+  DEVNET = "devnet-amplifier",
   TESTNET = "testnet",
   MAINNET = "mainnet",
 }
diff --git a/src/utils/validateChain.ts b/src/utils/validateChain.ts
index 2ce80684..8f42b0a5 100644
--- a/src/utils/validateChain.ts
+++ b/src/utils/validateChain.ts
@@ -1,8 +1,11 @@
 import { stringSimilarity } from "string-similarity-js";
-import { loadChains } from "../chains";
+import { importS3Config, loadChains } from "../chains";
 import { Environment } from "../libs";
 
-export async function validateChainIdentifier(chainIdentifier: string, environment: Environment) {
+export async function validateChainIdentifierOld(
+  chainIdentifier: string,
+  environment: Environment
+) {
   const chains = await loadChains({
     environment,
   });
@@ -18,6 +21,27 @@ export async function validateChainIdentifier(chainIdentifier: string, environme
   };
 }
 
+export async function validateChainIdentifier(chainIdentifier: string, environment: Environment) {
+  const s3 = await importS3Config(environment);
+
+  if (!s3 || !s3.chains)
+    return {
+      foundChain: false,
+      bestMatch: false,
+    };
+
+  const chainIdentifiers = Object.keys(s3.chains);
+
+  const foundChain = chainIdentifiers.find(
+    (identifier: string) => identifier === chainIdentifier.toLowerCase()
+  );
+
+  return {
+    foundChain: !!foundChain,
+    bestMatch: foundChain ? false : findSimilarInArray(chainIdentifiers, chainIdentifier),
+  };
+}
+
 function findSimilarInArray(array: Array<string>, wordsToFind: string) {
   let bestMatch = array[0];
   let bestScore = 0;
diff --git a/test/e2e/data/index.ts b/test/e2e/data/index.ts
index aafbd525..f2270bf0 100644
--- a/test/e2e/data/index.ts
+++ b/test/e2e/data/index.ts
@@ -18,7 +18,7 @@ export const getTransferPayload = (
       txFeeInPercent: 0.1,
       module: "axelarnet",
       chainIdentifier: {
-        devnet: "terra",
+        "devnet-amplifier": "terra",
         testnet: "terra",
         mainnet: "terra",
       },
@@ -45,7 +45,7 @@ export const getTransferPayload = (
       module: "evm",
       confirmLevel: 12,
       chainIdentifier: {
-        devnet: "avalanche",
+        "devnet-amplifier": "avalanche",
         testnet: "avalanche",
         mainnet: "avalanche",
       },
diff --git a/test/integration/parts/01.deposit-address.spec.ts b/test/integration/parts/01.deposit-address.spec.ts
index a27058ee..9da0a844 100644
--- a/test/integration/parts/01.deposit-address.spec.ts
+++ b/test/integration/parts/01.deposit-address.spec.ts
@@ -46,7 +46,7 @@ describe(
             "uausdc"
           ),
           axelarAssetTransferTestnet.getDepositAddress(
-            CHAINS.TESTNET.AURORA,
+            CHAINS.TESTNET.SEPOLIA,
             CHAINS.TESTNET.MOONBEAM,
             "0xB8Cd93C83A974649D76B1c19f311f639e62272BC",
             "uausdc"