mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-23 17:18:32 +02:00
feat: productionize paid modes and PvP capture
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
const RpcService = require('../src/rpc/rpcService');
|
||||
|
||||
const { GENESIS_HASHES } = RpcService;
|
||||
|
||||
function daemonFixture({ cryptoType, network, height = 123, overrides = {} }) {
|
||||
const target = cryptoType === 'WOW' ? 300 : 120;
|
||||
return {
|
||||
count: { count: height },
|
||||
info: {
|
||||
status: 'OK',
|
||||
height,
|
||||
target,
|
||||
nettype: network,
|
||||
offline: false,
|
||||
untrusted: false,
|
||||
synchronized: true,
|
||||
...overrides
|
||||
},
|
||||
header: {
|
||||
status: 'OK',
|
||||
untrusted: false,
|
||||
block_header: { hash: GENESIS_HASHES[`${cryptoType}:${network}`] }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fixtureHttp(fixtures) {
|
||||
return {
|
||||
post: jest.fn(async (url, body) => {
|
||||
const endpoint = url.replace(/\/json_rpc$/, '');
|
||||
const fixture = fixtures[endpoint];
|
||||
if (fixture instanceof Error) throw fixture;
|
||||
if (!fixture) throw new Error('unknown endpoint');
|
||||
if (body.method === 'getblockcount') return { data: { result: fixture.count } };
|
||||
if (body.method === 'get_info') return { data: { result: fixture.info } };
|
||||
if (body.method === 'get_block_header_by_height') {
|
||||
return { data: { result: fixture.header } };
|
||||
}
|
||||
throw new Error(`unexpected method: ${body.method}`);
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
describe('RPCService pinned production identity', () => {
|
||||
test.each([
|
||||
['XMR', 'mainnet'],
|
||||
['XMR', 'stagenet'],
|
||||
['XMR', 'testnet'],
|
||||
['WOW', 'mainnet']
|
||||
])('accepts only the pinned %s %s genesis', async (cryptoType, network) => {
|
||||
const endpoint = 'http://daemon.test';
|
||||
const service = new RpcService({
|
||||
http: fixtureHttp({ [endpoint]: daemonFixture({ cryptoType, network }) }),
|
||||
primaryEndpoint: endpoint,
|
||||
fallbackEndpoint: endpoint,
|
||||
cryptoType,
|
||||
network,
|
||||
identityRequired: true
|
||||
});
|
||||
|
||||
const health = await service.healthCheck();
|
||||
|
||||
expect(health.healthy).toBe(true);
|
||||
expect(health.identity).toMatchObject({
|
||||
required: true,
|
||||
verified: true,
|
||||
expected: { cryptoType, network },
|
||||
actual: { cryptoType, network }
|
||||
});
|
||||
expect(JSON.stringify(health.identity)).not.toContain(GENESIS_HASHES[`${cryptoType}:${network}`]);
|
||||
});
|
||||
|
||||
test('cannot pass WOW identity with an XMR mainnet daemon', async () => {
|
||||
const endpoint = 'http://daemon.test';
|
||||
const service = new RpcService({
|
||||
http: fixtureHttp({ [endpoint]: daemonFixture({ cryptoType: 'XMR', network: 'mainnet' }) }),
|
||||
primaryEndpoint: endpoint,
|
||||
fallbackEndpoint: endpoint,
|
||||
cryptoType: 'WOW',
|
||||
network: 'mainnet',
|
||||
identityRequired: true
|
||||
});
|
||||
|
||||
const health = await service.healthCheck();
|
||||
|
||||
expect(health.healthy).toBe(false);
|
||||
expect(health.identity.verified).toBe(false);
|
||||
expect(health.primary.identityVerified).toBe(false);
|
||||
});
|
||||
|
||||
test('selects a correctly identified fallback when the primary is the wrong network', async () => {
|
||||
const primary = 'http://primary.test';
|
||||
const fallback = 'http://fallback.test';
|
||||
const http = fixtureHttp({
|
||||
[primary]: daemonFixture({ cryptoType: 'XMR', network: 'mainnet' }),
|
||||
[fallback]: daemonFixture({ cryptoType: 'XMR', network: 'stagenet' })
|
||||
});
|
||||
const service = new RpcService({
|
||||
http,
|
||||
primaryEndpoint: primary,
|
||||
fallbackEndpoint: fallback,
|
||||
cryptoType: 'XMR',
|
||||
network: 'stagenet',
|
||||
identityRequired: true
|
||||
});
|
||||
|
||||
const height = await service.getBlockHeight();
|
||||
|
||||
expect(height).toBe(123);
|
||||
expect(service.currentEndpoint).toBe(fallback);
|
||||
expect(service.getIdentityStatus()).toMatchObject({
|
||||
verified: true,
|
||||
actual: { cryptoType: 'XMR', network: 'stagenet' }
|
||||
});
|
||||
});
|
||||
|
||||
test.each([
|
||||
['zero height', { height: 0 }],
|
||||
['offline daemon', { offline: true }],
|
||||
['untrusted response', { untrusted: true }],
|
||||
['unsynchronized daemon', { synchronized: false }],
|
||||
['non-OK status', { status: 'BUSY' }]
|
||||
])('fails closed for %s', async (_label, overrides) => {
|
||||
const endpoint = 'http://daemon.test';
|
||||
const fixture = daemonFixture({ cryptoType: 'XMR', network: 'stagenet', overrides });
|
||||
if (overrides.height !== undefined) fixture.count.count = overrides.height;
|
||||
const service = new RpcService({
|
||||
http: fixtureHttp({ [endpoint]: fixture }),
|
||||
primaryEndpoint: endpoint,
|
||||
fallbackEndpoint: endpoint,
|
||||
cryptoType: 'XMR',
|
||||
network: 'stagenet',
|
||||
identityRequired: true
|
||||
});
|
||||
|
||||
await expect(service.healthCheck()).resolves.toMatchObject({ healthy: false });
|
||||
});
|
||||
|
||||
test('treats an HTTP 200 JSON-RPC error as unhealthy', async () => {
|
||||
const endpoint = 'http://daemon.test';
|
||||
const http = { post: jest.fn().mockResolvedValue({
|
||||
data: { error: { code: -1, message: 'daemon error' } }
|
||||
}) };
|
||||
const service = new RpcService({
|
||||
http,
|
||||
primaryEndpoint: endpoint,
|
||||
fallbackEndpoint: endpoint,
|
||||
cryptoType: 'XMR',
|
||||
network: 'stagenet',
|
||||
identityRequired: true
|
||||
});
|
||||
|
||||
await expect(service.healthCheck()).resolves.toMatchObject({ healthy: false });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user