Skip to content
JavaScript SDK
GMP transaction status and recovery

Query and recover GMP transactions

Occasionally, transactions can get "stuck" in the pipeline from a source to destination chain (e.g. due to one-off issues that arise with relayers that operate on top of the network).

The AxelarGMPRecoveryAPI module in the AxelarJS SDK can be used by your dApp to query the status of any General Message Passing (GMP) transaction (triggered by either callContract or callContractWithToken) on the gateway contract of a source chain and trigger a manual relay from source to destination if necessary. - The GMP status tracker on Axelarscan makes use of this feature.

Install the AxelarJS SDK module (AxelarGMPRecoveryAPI)

Install the AxelarJS SDK:

npm i @axelar-network/axelarjs-sdk

Instantiate the AxelarGMPRecoveryAPI module:

import {
} from "@axelar-network/axelarjs-sdk";
const sdk = new AxelarGMPRecoveryAPI({
  environment: Environment.TESTNET,

Query transaction status by txHash

Invoke queryTransactionStatus:

const txHash: string =
const txStatus: GMPStatusResponse = await sdk.queryTransactionStatus(txHash);

Possible status responses for txStatus are outlined below:

interface GMPStatusResponse {
  status: GMPStatus;
  gasPaidInfo?: GasPaidInfo;
  errors?: any;
  callData?: any;
enum GMPStatus {
  SRC_GATEWAY_CALLED = "source_gateway_called",
  DEST_GATEWAY_APPROVED = "destination_gateway_approved",
  DEST_EXECUTED = "destination_executed",
  DEST_EXECUTE_ERROR = "destination_execute_error",
  DEST_EXECUTING = "executing",
  UNKNOWN_ERROR = "unknown_error",
  CANNOT_FETCH_STATUS = "cannot_fetch_status"
interface GasPaidInfo {
  status: GasPaidStatus;
  details?: any;
enum GasPaidStatus {
  GAS_UNPAID = "gas_unpaid",
  GAS_PAID = "gas_paid",
  GAS_PAID_NOT_ENOUGH_GAS = "gas_paid_not_enough_gas",
  GAS_PAID_ENOUGH_GAS = "gas_paid_enough_gas",

Trigger manual relay of transaction through the Axelar network

The following method, once invoked, will:

  1. Query the current status of the transaction to be in one of the states above.
  2. Recover from source to destination if needed.
const sourceTxHash = "0x..";
const provider = new ethers.providers.JsonRpcProvider(
// Optional
// By default, The sdk uses `window.ethereum` wallet as a sender wallet e.g. Metamask.
// This option allows caller to pass `privateKey` or `provider` to the sdk directly
const senderOptions = { privateKey: "0x", provider };
const response = await sdk.manualRelayToDestChain(
  senderOptions /* can be skipped */

Possible response values are: