Files
smom-dbis-138/services/etherlink-relay/src/EtherlinkRelayService.js
2026-03-02 12:14:09 -08:00

63 lines
2.3 KiB
JavaScript

/**
* Etherlink custom relay: monitor source for messages to 42793, queue, call EtherlinkRelayReceiver.relayMintOrUnlock.
* When CCIP does not support Etherlink. See docs/bridge/ETHERLINK_RELAY_RUNBOOK.md.
*/
import { ethers } from 'ethers';
import { config } from './config.js';
import { EtherlinkRelayReceiverABI } from './abis.js';
import * as metrics from './metrics.js';
export class EtherlinkRelayService {
constructor(logger) {
this.logger = logger;
this.queue = [];
this.inFlight = 0;
}
async start() {
if (!config.etherlinkRelayBridge) {
throw new Error('ETHERLINK_RELAY_BRIDGE required');
}
if (!config.relayPrivateKey) {
throw new Error('ETHERLINK_RELAY_PRIVATE_KEY or PRIVATE_KEY required');
}
this.etherlinkProvider = new ethers.JsonRpcProvider(config.etherlinkRpcUrl);
this.signer = new ethers.Wallet(config.relayPrivateKey, this.etherlinkProvider);
this.receiver = new ethers.Contract(config.etherlinkRelayBridge, EtherlinkRelayReceiverABI, this.signer);
this.logger.info('Etherlink relay started', { receiver: config.etherlinkRelayBridge });
setInterval(() => this.processQueue(), config.pollIntervalMs);
}
async pushMessage(messageId, token, recipient, amount) {
if (this.queue.length + this.inFlight >= config.queueDepthLimit) {
this.logger.warn('Queue depth limit reached', { limit: config.queueDepthLimit });
return;
}
this.queue.push({ messageId, token, recipient, amount });
metrics.incrementDetected();
metrics.setQueueDepth(this.queue.length + this.inFlight);
}
async processQueue() {
while (this.queue.length > 0 && this.inFlight < config.maxConcurrent) {
const msg = this.queue.shift();
this.inFlight++;
metrics.setQueueDepth(this.queue.length + this.inFlight);
this.submit(msg).finally(() => {
this.inFlight--;
metrics.setQueueDepth(this.queue.length + this.inFlight);
});
}
}
async submit({ messageId, token, recipient, amount }) {
try {
await this.receiver.relayMintOrUnlock(messageId, token, recipient, amount);
metrics.incrementSuccess();
} catch (err) {
this.logger.error('relayMintOrUnlock failed', { messageId, error: err.message });
metrics.incrementFailed();
}
}
}