Swaps provides a status endpoint you can use to track your transactions. The endpoint provides status updates and key transaction data for any transaction type. Key transaction data includes the USD value of the transaction, transaction fees, execution path, and other useful on-chain information.
For transactions originating on alt VMs (e.g., Bitcoin, Ripple), you will need to register your transaction by submitting a POST
request containing the transaction’s chainId
and txHash
.
Get status
API Reference: Get Status
The status endpoint supports three query parameters:
Parameter | Description |
---|
chainId | Source chain ID of the transaction |
txHash | Source or destination transaction hash |
txId | Unique identifier applied to each transaction by the Swaps protocol |
We recommend using the source chain ID and the transaction hash. The example below assumes this approach.
The status endpoint will return a TxDetails
object.
async function getStatus(
srcChainId: ChainId,
srcTxHash: string
): Promise<TxDetails> {
const url = `https://ghost.swaps.xyz/api/v2/getStatus?chainId=${srcChainId}&txHash=${srcTxHash}`;
const options = {
method: "GET",
headers: { "x-api-key": SWAPS_API_KEY },
};
const response = await fetch(url, options);
const txDetails = await response.json();
}
Register transaction
API Reference: Register Transaction
Registering a transaction triggers indexing after it is broadcasted on the source chain.
This is required for non EVM transactions. The Get Action request used to generate the transaction will return a vmId
in the response. If the vmId
is alt-vm
or solana
, you know you will need to register your transaction. This is covered in the alt VM broadcast guide. Swaps will automatically register any transaction submitted to a named VM. If you believe we have missed a transaction, calling the register transaction endpoint will trigger indexing.
This endpoint does support registering multiple transactions in a single call.
Parameter | Description |
---|
chainId | Source chain ID of the transaction |
txHash | Source chain transaction hash |
async function registerTx(
srcChainId: ChainId,
srcTxHash: string
): Promise<{ success: true; error: string | null }> {
const url = "https://ghost.swaps.xyz/api/v2/webhooks/registerTxs";
const options = {
method: "POST",
headers: {
"x-api-key": SWAPS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ txHash: srcTxHash, chainId: srcChainId }),
};
const response = await fetch(url, options);
const data = await response.json();
}
Webhooks
Swaps can emit webhooks on transaction creation and completion (success or failure) events. To use webhooks, please register a webhook URL in the developer console. Webhook URLs should correspond to a certain API key — each API key represents a unique appId
. Each appId
can have its own webhook URL.
🚧 The Console does not yet support webhook URL registration. 🚧 Please
contact the Swaps team to register a URL.
Swaps’ webhooks are sent with a x-signature-256
header that hashes the raw request body and delivery timestamp. This signature ensures that neither the request body nor the timestamp were modified and can be trusted as sent from Swaps.
The webhook body mirrors the TxDetails
object returned from the /getStatus
endpoint. The schema is:
type WebhookBody = {
event: "created" | "updated"; // "updated" is emitted on tx completion
txStatus: StatusDetails;
timestamp: number;
};
To verify the webhook signature, hash the payload with your webhook secret using SHA256 and confirm that the timestamp is within an expected buffer. Please see a reference implementation below:
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
const receivedSignature = signature.replace("sha256=", "");
// Use constant-time comparison
const sigBuffer = Buffer.from(receivedSignature, "hex");
const expectedBuffer = Buffer.from(expectedSignature, "hex");
if (sigBuffer.length !== expectedBuffer.length) {
return false;
}
return crypto.timingSafeEqual(sigBuffer, expectedBuffer);
}
// Sample usage in Express handler
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-signature-256"];
const payload = req.body.toString();
if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
// Process webhook...
res.status(200).send("OK");
});