@atomiqlabs/sdk
Version:
atomiq labs SDK for cross-chain swaps between smart chains and bitcoin
139 lines (138 loc) • 5.96 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UnifiedSwapEventListener = void 0;
const base_1 = require("@atomiqlabs/base");
const Logger_1 = require("../utils/Logger");
function chainEventToEscrowHash(event) {
if (event instanceof base_1.SwapEvent)
return event.escrowHash;
if (event instanceof base_1.SpvVaultFrontEvent ||
event instanceof base_1.SpvVaultClaimEvent ||
event instanceof base_1.SpvVaultCloseEvent)
return event.btcTxId;
}
const logger = (0, Logger_1.getLogger)("UnifiedSwapEventListener: ");
class UnifiedSwapEventListener {
constructor(unifiedStorage, events) {
this.listeners = {};
this.storage = unifiedStorage;
this.events = events;
}
async processEvents(events) {
const escrowHashesDeduped = new Set();
events.forEach(event => {
const escrowHash = chainEventToEscrowHash(event);
if (escrowHash != null)
escrowHashesDeduped.add(escrowHash);
});
const escrowHashes = Array.from(escrowHashesDeduped);
logger.debug("processEvents(): Processing events with escrow hashes: ", escrowHashes);
const swaps = await this.storage.query([
[{ key: "escrowHash", value: escrowHashes }]
], (val) => {
const obj = this.listeners?.[val.type];
if (obj == null)
return null;
return new obj.reviver(val);
});
const swapsByEscrowHash = {};
swaps.forEach(swap => {
const escrowHash = swap._getEscrowHash();
if (escrowHash != null)
swapsByEscrowHash[escrowHash] = swap;
});
//We need to do this because FromBTCLNAutoSwaps might not yet know its escrowHash
// hence we try to get the claimHash and try to query based on that, FromBTCLNAutoSwaps
// will use their claimHash as escrowHash before they know the real escrowHash
const htlcCheckInitializeEvents = {};
for (let event of events) {
const escrowHash = chainEventToEscrowHash(event);
const eventVersion = event.contractVersion ?? "v1";
if (escrowHash != null) {
const swap = swapsByEscrowHash[escrowHash];
if (swap != null && (swap._contractVersion ?? "v1") === eventVersion) {
const obj = this.listeners[swap.getType()];
if (obj == null)
continue;
await obj.listener(event, swap);
continue;
}
}
if (event instanceof base_1.InitializeEvent) {
if (event.swapType === base_1.ChainSwapType.HTLC) {
const swapData = await event.swapData();
htlcCheckInitializeEvents[swapData.getClaimHash()] = event;
}
}
}
logger.debug("processEvents(): Additionally checking HTLC claim hashes: ", Object.keys(htlcCheckInitializeEvents));
if (Object.keys(htlcCheckInitializeEvents).length === 0)
return;
//Try to query based on claimData
const claimDataSwaps = await this.storage.query([
[{ key: "escrowHash", value: Object.keys(htlcCheckInitializeEvents) }]
], (val) => {
const obj = this.listeners?.[val.type];
if (obj == null)
return null;
return new obj.reviver(val);
});
const swapsByClaimDataHash = {};
claimDataSwaps.forEach(swap => {
const escrowHash = swap._getEscrowHash();
if (escrowHash != null)
swapsByClaimDataHash[escrowHash] = swap;
});
logger.debug("processEvents(): Additional HTLC swaps founds: ", swapsByClaimDataHash);
for (let claimData in htlcCheckInitializeEvents) {
const event = htlcCheckInitializeEvents[claimData];
const eventVersion = event.contractVersion ?? "v1";
const swap = swapsByClaimDataHash[claimData];
if (swap != null && (swap._contractVersion ?? "v1") === eventVersion) {
const obj = this.listeners[swap.getType()];
if (obj == null)
continue;
await obj.listener(event, swap);
}
}
}
async start(noAutomaticPoll) {
if (this.listener != null)
return;
logger.info("start(): Starting unified swap event listener");
await this.storage.init();
logger.debug("start(): Storage initialized");
await this.events.init(noAutomaticPoll);
this.noAutomaticPoll = noAutomaticPoll;
logger.debug("start(): Events initialized");
this.events.registerListener(this.listener = async (events) => {
await this.processEvents(events);
return true;
});
logger.info("start(): Successfully initiated the unified swap event listener!");
}
poll(previousState) {
if (!this.noAutomaticPoll)
throw new Error("Only supported when no automatic events polling is configured!");
return this.events.poll(previousState);
}
stop() {
logger.info("stop(): Stopping unified swap event listener");
if (this.listener != null)
this.events.unregisterListener(this.listener);
return this.events.stop();
}
registerListener(type, listener, reviver) {
this.listeners[type] = {
listener,
reviver
};
}
unregisterListener(type) {
if (this.listeners[type])
return false;
delete this.listeners[type];
return true;
}
}
exports.UnifiedSwapEventListener = UnifiedSwapEventListener;