chore: sync submodule state (parent ref update)
Made-with: Cursor
This commit is contained in:
94
services/tezos-relay/src/TezosRelayService.js
Normal file
94
services/tezos-relay/src/TezosRelayService.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Tezos relay: listen TezosBridgeInitiated -> (mock) Tezos mint/transfer -> confirmTransaction.
|
||||
*/
|
||||
import { ethers } from 'ethers';
|
||||
import { config } from './config.js';
|
||||
import { TezosAdapterABI } from './abis.js';
|
||||
import * as metrics from './metrics.js';
|
||||
|
||||
export class TezosRelayService {
|
||||
constructor(logger) {
|
||||
this.logger = logger;
|
||||
this.provider = null;
|
||||
this.adapter = null;
|
||||
this.signer = null;
|
||||
this.queue = [];
|
||||
this.inFlight = 0;
|
||||
}
|
||||
|
||||
async start() {
|
||||
if (!config.tezosAdapterAddress) {
|
||||
throw new Error('TEZOS_ADAPTER_ADDRESS required');
|
||||
}
|
||||
if (!config.oraclePrivateKey) {
|
||||
throw new Error('TEZOS_RELAY_ORACLE_KEY or PRIVATE_KEY required');
|
||||
}
|
||||
this.provider = new ethers.JsonRpcProvider(config.sourceChain.rpcUrl);
|
||||
this.signer = new ethers.Wallet(config.oraclePrivateKey, this.provider);
|
||||
this.adapter = new ethers.Contract(config.tezosAdapterAddress, TezosAdapterABI, this.signer);
|
||||
this.logger.info('Tezos relay started', { adapter: config.tezosAdapterAddress });
|
||||
this.adapter.on('TezosBridgeInitiated', (requestId, sender, token, amount, destination) => {
|
||||
this.queue.push({ requestId, sender, token, amount, destination });
|
||||
metrics.incrementEventsDetected();
|
||||
metrics.setPendingRequests(this.queue.length + this.inFlight);
|
||||
this.processQueue();
|
||||
});
|
||||
}
|
||||
|
||||
async processQueue() {
|
||||
while (this.queue.length > 0 && this.inFlight < config.maxConcurrent) {
|
||||
const item = this.queue.shift();
|
||||
this.inFlight++;
|
||||
metrics.setPendingRequests(this.queue.length + this.inFlight);
|
||||
this.handleRequest(item).finally(() => {
|
||||
this.inFlight--;
|
||||
metrics.setPendingRequests(this.queue.length + this.inFlight);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async handleRequest({ requestId, sender, token, amount, destination }) {
|
||||
try {
|
||||
let tezosTxHash;
|
||||
if (config.mockTezosRelay) {
|
||||
tezosTxHash = `mock_${requestId.slice(0, 10)}_${Date.now()}`;
|
||||
this.logger.info('Mock Tezos tx', { requestId, destination, tezosTxHash });
|
||||
} else {
|
||||
tezosTxHash = await this.performTezosMintOrTransfer(requestId, sender, token, amount, destination);
|
||||
}
|
||||
await this.adapter.confirmTransaction(requestId, tezosTxHash);
|
||||
metrics.incrementConfirmationsSubmitted();
|
||||
} catch (err) {
|
||||
this.logger.error('confirmTransaction failed', { requestId, error: err.message });
|
||||
metrics.incrementConfirmationsFailed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform actual Tezos mint/transfer via Taquito or Tezos RPC.
|
||||
* Real mint: set MOCK_TEZOS_RELAY=false, TEZOS_MINTER_ADDRESS, TEZOS_RPC_URL, TEZOS_ORACLE_SECRET_KEY (edsk...).
|
||||
* When @taquito/taquito is installed and config is set, calls minter contract mintOrTransfer(destination, amount); otherwise returns mock hash.
|
||||
*/
|
||||
async performTezosMintOrTransfer(requestId, sender, token, amount, destination) {
|
||||
const { config } = await import('./config.js');
|
||||
if (!config.tezosRpcUrl) {
|
||||
return `mock_${requestId.slice(0, 10)}_${Date.now()}`;
|
||||
}
|
||||
try {
|
||||
const { Tezos } = await import('@taquito/taquito');
|
||||
const { InMemorySigner } = await import('@taquito/signer');
|
||||
const tezosSecret = process.env.TEZOS_ORACLE_SECRET_KEY || config.oraclePrivateKey;
|
||||
if (config.tezosMinterAddress && tezosSecret) {
|
||||
Tezos.setProvider({ rpc: config.tezosRpcUrl });
|
||||
Tezos.setSignerProvider(await InMemorySigner.fromSecretKey(tezosSecret));
|
||||
const contract = await Tezos.wallet.at(config.tezosMinterAddress);
|
||||
const op = await contract.methods.mintOrTransfer(destination, amount.toString()).send();
|
||||
await op.confirmation(1);
|
||||
return op.hash;
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.warn('Taquito mint/transfer failed, using mock hash', { error: e.message });
|
||||
}
|
||||
return `mock_${requestId.slice(0, 10)}_${Date.now()}`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user