Skip to content

Commit 0eae9cf

Browse files
committed
pre-rebase
1 parent cdddcbc commit 0eae9cf

File tree

6 files changed

+400
-370
lines changed

6 files changed

+400
-370
lines changed

evm/ts/src/axelar.ts

Lines changed: 110 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
import { Chain, Network } from "@wormhole-foundation/sdk-base";
2-
import {
3-
AxelarGMPRecoveryAPI,
4-
Environment,
5-
GMPStatusResponse,
6-
} from "@axelar-network/axelarjs-sdk";
72

8-
// See: https://github.com/axelarnetwork/axelarjs-sdk/blob/main/src/constants/EvmChain.ts
3+
// Using direct API calls instead of importing the entire @axelar-network/axelarjs-sdk to stay lightweight
4+
// Axelar chains: https://github.com/axelarnetwork/axelarjs-sdk/blob/53a957deb1209325b1e3d109e0985a64db6d9901/src/constants/EvmChain.ts#L1
95
export const axelarChains: Partial<Record<Chain, string>> = {
106
Ethereum: "ethereum",
117
Monad: "monad",
128
Sepolia: "ethereum-sepolia",
139
// add more as needed
1410
};
1511

12+
// https://github.com/axelarnetwork/axelarjs-sdk/blob/53a957deb1209325b1e3d109e0985a64db6d9901/src/libs/TransactionRecoveryApi/AxelarRecoveryApi.ts#L16
13+
export enum GMPStatus {
14+
SRC_GATEWAY_CALLED = "source_gateway_called",
15+
DEST_GATEWAY_APPROVED = "destination_gateway_approved",
16+
DEST_EXECUTED = "destination_executed",
17+
EXPRESS_EXECUTED = "express_executed",
18+
DEST_EXECUTE_ERROR = "error",
19+
DEST_EXECUTING = "executing",
20+
APPROVING = "approving",
21+
FORECALLED = "forecalled",
22+
FORECALLED_WITHOUT_GAS_PAID = "forecalled_without_gas_paid",
23+
NOT_EXECUTED = "not_executed",
24+
NOT_EXECUTED_WITHOUT_GAS_PAID = "not_executed_without_gas_paid",
25+
INSUFFICIENT_FEE = "insufficient_fee",
26+
UNKNOWN_ERROR = "unknown_error",
27+
CANNOT_FETCH_STATUS = "cannot_fetch_status",
28+
SRC_GATEWAY_CONFIRMED = "confirmed",
29+
}
30+
31+
export interface GMPError {
32+
txHash: string;
33+
chain: string;
34+
message: string;
35+
}
36+
1637
export async function getAxelarGasFee(
1738
network: Network,
1839
sourceChain: Chain,
@@ -27,12 +48,14 @@ export async function getAxelarGasFee(
2748

2849
const axelarSourceChain = axelarChains[sourceChain];
2950
if (!axelarSourceChain) {
30-
throw new Error(`Unsupported source chain: ${sourceChain}`);
51+
throw new Error(`Unsupported axelar source chain: ${sourceChain}`);
3152
}
3253

3354
const axelarDestinationChain = axelarChains[destinationChain];
3455
if (!axelarDestinationChain) {
35-
throw new Error(`Unsupported destination chain: ${destinationChain}`);
56+
throw new Error(
57+
`Unsupported axelar destination chain: ${destinationChain}`
58+
);
3659
}
3760

3861
const controller = new AbortController();
@@ -47,7 +70,6 @@ export async function getAxelarGasFee(
4770
body: JSON.stringify({
4871
sourceChain: axelarSourceChain,
4972
destinationChain: axelarDestinationChain,
50-
sourceTokenAddress: "0x0000000000000000000000000000000000000000",
5173
gasMultiplier: "auto",
5274
gasLimit: gasLimit.toString(),
5375
}),
@@ -71,14 +93,85 @@ export async function getAxelarGasFee(
7193

7294
export async function getAxelarTransactionStatus(
7395
network: Network,
74-
txHash: string
75-
): Promise<GMPStatusResponse> {
76-
const api = new AxelarGMPRecoveryAPI({
77-
environment:
78-
network === "Mainnet" ? Environment.MAINNET : Environment.TESTNET,
79-
});
80-
const status = await api.queryTransactionStatus(txHash);
81-
return status;
96+
sourceChain: Chain,
97+
txHash: string,
98+
timeoutMs = 10000
99+
): Promise<{ status: GMPStatus | string; error?: GMPError }> {
100+
const baseUrl =
101+
network === "Mainnet"
102+
? "https://api.axelarscan.io"
103+
: "https://testnet.api.axelarscan.io";
104+
105+
const axelarSourceChain = axelarChains[sourceChain];
106+
if (!axelarSourceChain) {
107+
throw new Error(`Unsupported axelar source chain: ${sourceChain}`);
108+
}
109+
110+
const controller = new AbortController();
111+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
112+
113+
try {
114+
const response = await fetch(`${baseUrl}/gmp/searchGMP`, {
115+
method: "POST",
116+
headers: {
117+
"Content-Type": "application/json",
118+
},
119+
body: JSON.stringify({
120+
sourceChain: axelarSourceChain,
121+
txHash: txHash,
122+
}),
123+
signal: controller.signal,
124+
});
125+
126+
if (!response.ok) {
127+
const errorText = await response.text();
128+
throw new Error(
129+
`Failed to get transaction status: ${response.status} ${errorText}`
130+
);
131+
}
132+
133+
const result = await response.json();
134+
if (!result.data || result.data.length === 0) {
135+
throw new Error("No transaction details found");
136+
}
137+
138+
const txDetails = result.data[0];
139+
return {
140+
status: parseGMPStatus(txDetails),
141+
error: parseGMPError(txDetails),
142+
};
143+
} finally {
144+
clearTimeout(timeoutId);
145+
}
146+
}
147+
148+
export function parseGMPStatus(response: any): GMPStatus | string {
149+
const { error, status } = response;
150+
151+
if (status === "error" && error) return GMPStatus.DEST_EXECUTE_ERROR;
152+
else if (status === "executed") return GMPStatus.DEST_EXECUTED;
153+
else if (status === "approved") return GMPStatus.DEST_GATEWAY_APPROVED;
154+
else if (status === "called") return GMPStatus.SRC_GATEWAY_CALLED;
155+
else if (status === "executing") return GMPStatus.DEST_EXECUTING;
156+
else {
157+
return status;
158+
}
159+
}
160+
161+
export function parseGMPError(response: any): GMPError | undefined {
162+
if (response.error) {
163+
return {
164+
message: response.error.error.message,
165+
txHash: response.error.sourceTransactionHash,
166+
chain: response.error.chain,
167+
};
168+
} else if (response.is_insufficient_fee) {
169+
return {
170+
message: "Insufficient gas",
171+
txHash: response.call.transaction.hash,
172+
chain: response.call.chain,
173+
};
174+
}
82175
}
83176

84177
export function getAxelarExplorerUrl(network: Network, txHash: string): string {

sdk/route/src/executor/executor.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,7 @@ import {
3737
} from "@wormhole-foundation/sdk-connect";
3838
import "@wormhole-foundation/sdk-definitions-ntt";
3939
import { NttRoute } from "../types.js";
40-
import {
41-
calculateReferrerFee,
42-
fetchCapabilities,
43-
fetchSignedQuote,
44-
fetchStatus,
45-
RelayStatus,
46-
} from "./utils.js";
40+
import { calculateReferrerFee } from "./utils.js";
4741
import { Ntt, NttWithExecutor } from "@wormhole-foundation/sdk-definitions-ntt";
4842
import {
4943
isNative,

0 commit comments

Comments
 (0)