chore: sync submodule state (parent ref update)

Made-with: Cursor
This commit is contained in:
defiQUG
2026-03-02 12:14:09 -08:00
parent 50ab378da9
commit 5efe36b1e0
1100 changed files with 155024 additions and 8674 deletions

View File

@@ -0,0 +1,62 @@
/**
* 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();
}
}
}

View File

@@ -0,0 +1,4 @@
export const EtherlinkRelayReceiverABI = [
"function relayMintOrUnlock(bytes32 messageId, address token, address recipient, uint256 amount) external",
"event RelayMintOrUnlock(bytes32 indexed messageId, address indexed token, address indexed recipient, uint256 amount)",
];

View File

@@ -0,0 +1,21 @@
import dotenv from 'dotenv';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Load PRIVATE_KEY from dotenv: smom-dbis-138/.env then service .env
dotenv.config({ path: path.resolve(__dirname, '../../.env') });
dotenv.config({ path: path.resolve(__dirname, '../.env') });
const cwd = process.cwd();
dotenv.config({ path: path.resolve(cwd, 'smom-dbis-138/.env') });
dotenv.config({ path: path.resolve(cwd, '.env') });
export const config = {
sourceChain: { rpcUrl: process.env.RPC_URL_138 || process.env.RPC_URL || "http://127.0.0.1:8545" },
etherlinkRpcUrl: process.env.ETHERLINK_RPC_URL || "https://node.mainnet.etherlink.com",
etherlinkRelayBridge: process.env.ETHERLINK_RELAY_BRIDGE || "",
relayPrivateKey: process.env.ETHERLINK_RELAY_PRIVATE_KEY || process.env.PRIVATE_KEY,
pollIntervalMs: parseInt(process.env.POLL_INTERVAL_MS || "5000", 10),
maxConcurrent: parseInt(process.env.ETHERLINK_RELAY_MAX_CONCURRENT || "5", 10),
queueDepthLimit: parseInt(process.env.ETHERLINK_RELAY_QUEUE_DEPTH || "100", 10),
};

View File

@@ -0,0 +1,11 @@
export const metrics = {
etherlink_relay_messages_detected_total: 0,
etherlink_relay_submissions_success_total: 0,
etherlink_relay_submissions_failed_total: 0,
etherlink_relay_queue_depth: 0,
};
export function incrementDetected() { metrics.etherlink_relay_messages_detected_total++; }
export function incrementSuccess() { metrics.etherlink_relay_submissions_success_total++; }
export function incrementFailed() { metrics.etherlink_relay_submissions_failed_total++; }
export function setQueueDepth(n) { metrics.etherlink_relay_queue_depth = n; }
export function getMetrics() { return { ...metrics }; }