Skip to content

Commit

Permalink
v0.16 (#325)
Browse files Browse the repository at this point in the history
* chore: fix decimals issue with l2 dest chains (#315)

* chore: fix decimals issue with l2 dest chains

chore: delete unused test

* 0.16.0-alpha.1

* chore: improve convertTokenAmount impl

* chore: refactor bignumber amount conversion

---------

Co-authored-by: npty <[email protected]>

* chore: fix commandId generation (#321)

* chore: fix gas limit function doc (#316)

* chore: fix gas limit function doc

* chore: remove mantle

* chore: fix commandId generation

* chore: update comment

* chore: remove unused var

* chore: update testnet rpc

* chore: bump axelar-cgp-solidity to 6.3.0 (#324)

* chore: fix gas limit function doc (#316)

* chore: fix gas limit function doc

* chore: remove mantle

* chore: change executeData type from `0x${string}` to `string` (#317)

* chore: change executeData type from `0x${string}` to `string`

* chore: fix build error

* chore: fix testnet rpc

* Update issue templates

* chore: bump axelar-cgp-solidity to 6.3.0

---------

Co-authored-by: Canh Trinh <[email protected]>

* 0.16.0

* chore: update changelog for 0.16.0

* chore: remove unused import

* chore: update changelog date

---------

Co-authored-by: Canh Trinh <[email protected]>
  • Loading branch information
npty and canhtrinh authored May 8, 2024
1 parent 0ff1061 commit de261a9
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 37 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ 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.16.0] - 2024-MAY-1

- Upgraded axelar-cgp-solidity to `6.3.0` to enable support for Node.js version >= 20
- Fixed an issue with the generation of `commandId`
- Changed the type of `executeData` from `0x${string}` to `string` to ensure compatibility with most libraries and clients
- Corrected the documentation for the `estimateGasFee` function regarding gas limit calculation
- Resolved an issue with the calculation of L1 gas fees when the source and destination tokens have different decimal places

## [0.15.0] - 2024-MARCH-20

- Improved the accuracy of `estimateGasFee` function by incorporating L1 rollup fee for destination L2 chain.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@axelar-network/axelarjs-sdk",
"version": "0.15.0",
"version": "0.16.0",
"description": "The JavaScript SDK for Axelar Network",
"repository": {
"type": "git",
Expand Down Expand Up @@ -41,7 +41,7 @@
"author": "Axelar Network",
"license": "MIT",
"dependencies": {
"@axelar-network/axelar-cgp-solidity": "^4.5.0",
"@axelar-network/axelar-cgp-solidity": "^6.3.0",
"@axelar-network/axelarjs-types": "^0.33.0",
"@cosmjs/json-rpc": "^0.30.1",
"@cosmjs/stargate": "0.31.0-alpha.1",
Expand Down
17 changes: 15 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions src/libs/AxelarQueryAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ export class AxelarQueryAPI {
);
}

// Calculate the L1 execution fee. This value is in ETH.
// Calculate the L1 execution fee. This value is in ETH wei.
l1ExecutionFee = await this.estimateL1GasFee(destChainId, {
executeData: executeData || DEFAULT_L1_EXECUTE_DATA,
l1GasPrice: destToken.l1_gas_price_in_units,
Expand All @@ -310,10 +310,18 @@ export class AxelarQueryAPI {
const ethTokenPrice = Number(ethereumToken.token_price.usd);
const ethToSrcTokenPriceRatio = ethTokenPrice / srcTokenPrice;

const actualL1ExecutionFee = l1ExecutionFee
let actualL1ExecutionFee = l1ExecutionFee
.mul(Math.ceil(ethToSrcTokenPriceRatio * 1000))
.div(1000);

if (sourceToken.decimals !== destToken.decimals) {
actualL1ExecutionFee = BigNumberUtils.convertTokenAmount(
actualL1ExecutionFee,
destToken.decimals,
sourceToken.decimals
);
}

l1ExecutionFee = BigNumber.from(actualL1ExecutionFee.toString());

// Calculate the L1 execution fee with the gas multiplier
Expand Down
8 changes: 8 additions & 0 deletions src/libs/BigNumberUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ export class BigNumberUtils {
public static divideToGetWei(bn: BigNumber | string, number: string, units: number): BigNumber {
return BigNumber.from(bn).div(parseUnits(number, units));
}

public static convertTokenAmount(
ethAmount: BigNumber,
sourceDecimals: number,
targetDecimals: number
) {
return ethAmount.mul(parseUnits("1", targetDecimals)).div(parseUnits("1", sourceDecimals));
}
}
11 changes: 7 additions & 4 deletions src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi {
});
}

public getCidFromSrcTxHash(destChainId: string, txHash: string, eventIndex: number) {
return getCommandId(destChainId, txHash, eventIndex, this.environment, rpcInfo);
public getCidFromSrcTxHash(destChainId: string, messageId: string, eventIndex: number) {
const chainId = rpcInfo[this.environment].networkInfo[destChainId.toLowerCase()]?.chainId;
return getCommandId(messageId, eventIndex, chainId);
}

public async doesTxMeetConfirmHt(chain: string, txHash: string, provider?: JsonRpcProvider) {
Expand Down Expand Up @@ -244,8 +245,10 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi {
};
}

const commandId = this.getCidFromSrcTxHash(destChainId, srcTxHash, eventIndex);
const eventResponse = await this.axelarQueryApi.getEVMEvent(srcChainId, srcTxHash, eventIndex);
const isCallContract = eventResponse?.event?.contractCall ? true : false;
const messageId = isCallContract ? `${srcTxHash}-${eventIndex}` : srcTxHash;
const commandId = this.getCidFromSrcTxHash(destChainId, messageId, eventIndex);

if (!eventResponse || this.isEVMEventFailed(eventResponse)) {
const errorMessage = this.isEVMEventFailed(eventResponse)
Expand Down Expand Up @@ -1149,7 +1152,7 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi {

const executeParams = response.data as ExecuteParams;
const gasLimitBuffer = evmWalletDetails?.gasLimitBuffer || 0;
const { destinationChain, destinationContractAddress, srcTxInfo } = executeParams;
const { destinationChain, destinationContractAddress } = executeParams;

const signer = this.getSigner(
destinationChain,
Expand Down
38 changes: 16 additions & 22 deletions src/libs/TransactionRecoveryApi/helpers/getCommandId.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { arrayify, keccak256 } from "ethers/lib/utils";
import { Environment } from "src/libs/types";
import { RPCInfoType } from "../constants/chain";
import { arrayify, concat, hexlify, hexZeroPad, keccak256 } from "ethers/lib/utils";

export const getCommandId = (
chainName: string,
txHash: string,
sourceEventIndex: number,
environment: Environment,
rpcInfo: RPCInfoType
) => {
const chainID: number = rpcInfo[environment].networkInfo[chainName.toLowerCase()]?.chainId;
if (!chainID) return "";
const seiArr = arrayify(sourceEventIndex).reverse();
const txHashWithEventIndex = new Uint8Array([
...arrayify(txHash),
...new Uint8Array(8).map((a, i) => seiArr[i] || a),
]);
const chainIdByteArray = arrayify(chainID);
const dataToHash = new Uint8Array(txHashWithEventIndex.length + chainIdByteArray.length);
dataToHash.set(txHashWithEventIndex, 0);
dataToHash.set(chainIdByteArray, txHashWithEventIndex.length);
return keccak256(dataToHash).slice(2); // remove 0x prefix
const stringToCharcodeArray = (text: string) => Array.from(text, (char) => char.charCodeAt(0));

// This function is specifically designed for use with EVM-based chains. Its behavior may not be as expected if used with Cosmos-based chains or other types of chains.
export const getCommandId = (messageId: string, sourceEventIndex: number, chainId: number) => {
if (messageId.includes("-")) {
return keccak256(concat([stringToCharcodeArray(messageId), hexlify(chainId)]));
} else {
return keccak256(
concat([
messageId,
arrayify(hexZeroPad(hexlify(sourceEventIndex), 8)).reverse(),
hexlify(chainId),
])
);
}
};
41 changes: 38 additions & 3 deletions src/libs/test/AxelarQueryAPI.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ const MOCK_EXECUTE_DATA =
"0x1a98b2e0e68ba0eb84262d4bcf91955ec2680b37bcedd59a1f48e18d183dac9961bf9d1400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000d40000000000000000000000000000000000000000000000000000000000deac2c6000000000000000000000000000000000000000000000000000000000000000762696e616e636500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a307863653136463639333735353230616230313337376365374238386635424138433438463844363636000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004607cad6135d7a119185ebe062d3b369b1b536ef000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc800000000000000000000000000000000000000000000000000000000000000640000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd3000000000000000000000000000000000000000000000000000000000deac2c6000000000000000000000000000000000000000000000000000000000dc647500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f40521500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc800000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab100000000000000000000000000000000000000000000000000000000000000640000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd3000000000000000000000000000000000000000000000000000000000de83dbf000000000000000000000000000000000000000000000000015d8c7908dbe7130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000242e1a7d4d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000004607cad6135d7a119185ebe062d3b369b1b536ef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000761786c5553444300000000000000000000000000000000000000000000000000";

describe("AxelarQueryAPI", () => {
const api = new AxelarQueryAPI({ environment: Environment.TESTNET });
const api = new AxelarQueryAPI({
environment: Environment.TESTNET,
axelarRpcUrl: "https://axelar-testnet-rpc.qubelabs.io:443",
});

beforeEach(() => {
vitest.clearAllMocks();
Expand Down Expand Up @@ -222,6 +225,32 @@ describe("AxelarQueryAPI", () => {
}
});

test("It should include L1 fee for L2 destination chain for cosmos source chains", async () => {
// Mainnet
const mainnetL2Chains = ["optimism"];
const mainnetApi = new AxelarQueryAPI({ environment: Environment.MAINNET });
const mainnetQueries = [];
for (const mainnetL2Chain of mainnetL2Chains) {
const query = await mainnetApi.estimateGasFee(
"osmosis",
mainnetL2Chain as EvmChain,
500000,
"auto",
undefined,
undefined,
undefined
);
mainnetQueries.push(query);
}

const mainnetResponses = await Promise.all(mainnetQueries);

mainnetResponses.forEach((response) => {
expect(response).toBeDefined();
expect(String(response).length).toBeLessThanOrEqual(6);
});
});

test("It should return estimated gas amount that makes sense for native token", async () => {
const gasAmount = await api.estimateGasFee(
CHAINS.TESTNET.AVALANCHE as EvmChain,
Expand Down Expand Up @@ -378,7 +407,10 @@ describe("AxelarQueryAPI", () => {
let api: AxelarQueryAPI;

beforeEach(async () => {
api = new AxelarQueryAPI({ environment: Environment.TESTNET });
api = new AxelarQueryAPI({
environment: Environment.TESTNET,
axelarRpcUrl: "https://axelar-testnet-lcd.qubelabs.io",
});
});

test("it should retrieve the gas receiver address remotely", async () => {
Expand All @@ -392,7 +424,10 @@ describe("AxelarQueryAPI", () => {
let api: AxelarQueryAPI;

beforeEach(async () => {
api = new AxelarQueryAPI({ environment: Environment.TESTNET });
api = new AxelarQueryAPI({
environment: Environment.TESTNET,
axelarRpcUrl: "https://axelar-testnet-rpc.qubelabs.io:443",
});
vitest.clearAllMocks();

/**
Expand Down
26 changes: 26 additions & 0 deletions src/libs/test/TransactionRecoveryAPI/AxelarGMPRecoveryAPI.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,32 @@ describe("AxelarGMPRecoveryAPI", () => {
});
});

describe("getCidFromSrcTxHash", () => {
const mainnetApi = new AxelarGMPRecoveryAPI({ environment: Environment.MAINNET });

// https://axelarscan.io/gmp/0x3828bf893801f337e08d15b89efc9c3c2d9196fe7f83f3b7640425b24d122cb2:12
it("should return the correct commandId from evm -> evm for ContractCallWithToken event", () => {
expect(
mainnetApi.getCidFromSrcTxHash(
"celo",
"0x3828bf893801f337e08d15b89efc9c3c2d9196fe7f83f3b7640425b24d122cb2",
8
)
).toEqual("0xa45da101fcfed541b8251cb8a288b5b7dd84086377eb9cf3f8d4a99f11e062e0");
});

// https://axelarscan.io/gmp/0x92f676751feccab46a048a16aaf81b26620a3683933b56a722ce742de8ea7429:349
it("should return the correct commandId from evm -> evm for ContractCall event", () => {
expect(
mainnetApi.getCidFromSrcTxHash(
"blast",
"0x92f676751feccab46a048a16aaf81b26620a3683933b56a722ce742de8ea7429-5",
5
)
).toEqual("0xe6868c6e94240fa6a37cc71d265106a00ad8fa0652319f145e3235f703046574");
});
});

describe.skip("calculateNativeGasFee", () => {
const api = new AxelarGMPRecoveryAPI({ environment: Environment.TESTNET });

Expand Down
2 changes: 0 additions & 2 deletions src/libs/test/TransactionRecoveryAPI/EncodingTests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ describe("AxelarDepositRecoveryAPI", () => {
const txHash = "0x2c9083bebd1f82b86b7b0d3298885f90767b584742df9ec3a9c9f15872a1fff9";
const eventIndex = await api.getEventIndex("ethereum-2" as EvmChain, txHash);
const res = await api.getCidFromSrcTxHash(EvmChain.MOONBEAM, txHash, eventIndex as number);
console.log("eventIndex", eventIndex);
console.log("res", res);
expect(res).toEqual("58c46960e6483f61bf206d1bd1819917d2b009f58d7050e05b4be1d13247b4ed");
}, 60000);
});
Expand Down

0 comments on commit de261a9

Please sign in to comment.