Files
smom-dbis-138/services/relay/test.js

113 lines
3.6 KiB
JavaScript

#!/usr/bin/env node
/**
* Minimal tests for CCIP Relay Service.
* Run with: npm test
* Does not start the relay or connect to RPC.
* For full tests, set PRIVATE_KEY (or RELAYER_PRIVATE_KEY) and run; config load will then validate.
*/
import { existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { ethers } from 'ethers';
import { MessageQueue } from './src/MessageQueue.js';
import { RelayService } from './src/RelayService.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
function assert(condition, message) {
if (!condition) {
console.error('FAIL:', message);
process.exit(1);
}
}
console.log('Relay service structure tests...');
assert(existsSync(join(__dirname, 'src', 'config.js')), 'src/config.js should exist');
assert(existsSync(join(__dirname, 'src', 'RelayService.js')), 'src/RelayService.js should exist');
assert(existsSync(join(__dirname, 'src', 'healthServer.js')), 'src/healthServer.js should exist');
assert(existsSync(join(__dirname, 'index.js')), 'index.js should exist');
const logger = {
info() {},
warn() {},
error() {},
debug() {},
};
const relay = new RelayService({
sourceChain: {
name: 'Chain 138',
chainId: 138,
rpcUrl: 'http://example.invalid',
routerAddress: '0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817',
bridgeAddress: '0x152ed3e9912161b76bdfd368d0c84b7c31c10de7',
},
destinationChain: {
name: 'Ethereum Mainnet',
chainId: 1,
rpcUrl: 'http://example.invalid',
relayRouterAddress: '0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA',
relayBridgeAddress: '0x2bF74583206A49Be07E0E8A94197C12987AbD7B5',
relayBridgeAllowlist: ['0x2bF74583206A49Be07E0E8A94197C12987AbD7B5'],
chainSelector: 5009297550715157269n,
deliveryMode: 'router',
},
tokenMapping: {},
sourceChainSelector: 138n,
relayer: { privateKey: '', address: '' },
monitoring: {
startBlock: 'latest',
pollInterval: 5000,
confirmationBlocks: 1,
finalityDelayBlocks: 2,
replayWindowBlocks: 32,
},
retry: { maxRetries: 3, retryDelay: 5000 },
skipMessageIds: new Set(),
}, logger);
const cwReceiver = ethers.AbiCoder.defaultAbiCoder().encode(
['address'],
['0x2bF74583206A49Be07E0E8A94197C12987AbD7B5']
);
const scoped = relay.evaluateMessageScope({
sender: '0x152ed3e9912161b76bdfd368d0c84b7c31c10de7',
receiver: cwReceiver,
});
assert(scoped.inScope === true, 'cW message should match the configured worker scope');
assert(
scoped.targetBridge === '0x2bF74583206A49Be07E0E8A94197C12987AbD7B5',
'cW target bridge should decode from receiver bytes'
);
const wethReceiver = ethers.AbiCoder.defaultAbiCoder().encode(
['address'],
['0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939']
);
const rejected = relay.evaluateMessageScope({
sender: '0xcacfd227A040002e49e2e01626363071324f820a',
receiver: wethReceiver,
});
assert(rejected.inScope === false, 'WETH message should be rejected by the cW worker scope');
const queue = new MessageQueue(logger);
const queuedMessage = {
messageId: '0xtest-message',
sender: '0x152ed3e9912161b76bdfd368d0c84b7c31c10de7',
receiver: cwReceiver,
data: '0x',
tokenAmounts: []
};
await queue.add(queuedMessage);
const inFlightMessage = await queue.getNext();
assert(inFlightMessage?.messageId === queuedMessage.messageId, 'getNext should return the queued message');
await queue.retry(queuedMessage.messageId);
const retriedMessage = await queue.getNext();
assert(retriedMessage?.messageId === queuedMessage.messageId, 'retry should requeue the original message payload');
console.log('OK: relay service structure valid');
process.exit(0);