102 lines
5.3 KiB
JavaScript
102 lines
5.3 KiB
JavaScript
// Testele SDK-ului: rutele contra unui server FALS (deterministe, offline) + verifyWebhook cu
|
|
// perechea negativa + o proba VIE optionala contra productiei daca AERE_CHEIE e in mediu.
|
|
import assert from 'node:assert';
|
|
import crypto from 'node:crypto';
|
|
import { AereCloud, AereCloudError, verifyWebhook } from '../index.mjs';
|
|
|
|
let treceri = 0;
|
|
async function test(nume, fn) {
|
|
try { await fn(); treceri++; console.log(' OK ' + nume); }
|
|
catch (e) { console.log(' ESEC ' + nume + ' — ' + e.message); process.exitCode = 1; }
|
|
}
|
|
|
|
// ---- server fals: raspunde dupa cale, ca sa testam constructia cererii si maparea erorilor ----
|
|
function fetchFals(rute) {
|
|
return async (url, opts = {}) => {
|
|
const u = new URL(url);
|
|
const cale = u.pathname.replace(/^\/v1/, ''); // baseUrl de test include /v1
|
|
const cheie = opts.method + ' ' + cale + u.search;
|
|
const r = rute[cheie] || rute[opts.method + ' ' + cale];
|
|
if (!r) return { ok: false, status: 404, json: async () => ({ error: 'not_found' }) };
|
|
r._vazut = { headers: opts.headers, body: opts.body ? JSON.parse(opts.body) : undefined };
|
|
return { ok: r.status < 400, status: r.status, json: async () => r.corp };
|
|
};
|
|
}
|
|
// AERE-SINTETIC: cheile de mai jos (ak2800.0xAAA.secret, secretul-meu) sunt FICTIVE, pentru
|
|
// testul offline; nu sunt chei ale retelei. Marcajul spune portii de secrete exact asta.
|
|
const BAZA_TEST = 'https://x.test/v1';
|
|
|
|
await test('constructorul cere cheia', () => {
|
|
assert.throws(() => new AereCloud({}), /apiKey is required/);
|
|
});
|
|
|
|
await test('cheia merge in antetul x-api-key, health e fara cheie', async () => {
|
|
const rute = { 'GET /health': { status: 200, corp: { ok: true, chainId: 2800, block: 5 } },
|
|
'GET /account': { status: 200, corp: { address: '0xabc', planId: 5 } } };
|
|
const c = new AereCloud({ apiKey: 'ak2800.0xAAA.AERE-SINTETIC-secret', baseUrl: BAZA_TEST, fetch: fetchFals(rute) });
|
|
const h = await c.health();
|
|
assert.equal(h.block, 5);
|
|
assert.equal(rute['GET /health']._vazut.headers['x-api-key'], undefined, 'health nu trimite cheie');
|
|
await c.account();
|
|
assert.equal(rute['GET /account']._vazut.headers['x-api-key'], 'ak2800.0xAAA.AERE-SINTETIC-secret');
|
|
});
|
|
|
|
await test('rpc impacheteaza corect si ridica eroarea RPC', async () => {
|
|
const rute = {
|
|
'POST /rpc': { status: 200, corp: { jsonrpc: '2.0', id: 1, result: '0x10' } },
|
|
};
|
|
const c = new AereCloud({ apiKey: 'ak2800.0xAAA.AERE-SINTETIC-s', baseUrl: BAZA_TEST, fetch: fetchFals(rute) });
|
|
assert.equal(await c.blockNumber(), 16);
|
|
assert.deepEqual(rute['POST /rpc']._vazut.body, { jsonrpc: '2.0', id: 1, method: 'eth_blockNumber', params: [] });
|
|
// eroare RPC in plic -> AereCloudError
|
|
const rute2 = { 'POST /rpc': { status: 200, corp: { error: { code: -32601, message: 'nope' } } } };
|
|
const c2 = new AereCloud({ apiKey: 'ak2800.0xAAA.AERE-SINTETIC-s', baseUrl: BAZA_TEST, fetch: fetchFals(rute2) });
|
|
await assert.rejects(() => c2.rpc('qbft_proposeValidatorVote'), (e) => e instanceof AereCloudError && e.body.error.code === -32601);
|
|
});
|
|
|
|
await test('un status HTTP de eroare devine AereCloudError cu corpul serverului', async () => {
|
|
const rute = { 'POST /pq/verify': { status: 400, corp: { error: 'bad_publicKey', hint: '0x hex' } } };
|
|
const c = new AereCloud({ apiKey: 'ak2800.0xAAA.AERE-SINTETIC-s', baseUrl: BAZA_TEST, fetch: fetchFals(rute) });
|
|
await assert.rejects(() => c.pqVerify({ scheme: 'ml-dsa-44', publicKey: 'nu-e-hex' }),
|
|
(e) => e instanceof AereCloudError && e.status === 400 && e.body.error === 'bad_publicKey');
|
|
});
|
|
|
|
await test('rutele de date construiesc corect query-ul', async () => {
|
|
const rute = {
|
|
'GET /data/anchors?limit=3': { status: 200, corp: { anchors: [] } },
|
|
'GET /data/transfers?address=0xBeef&limit=25': { status: 200, corp: { tokenTransfers: [], nativeTransfers: [] } },
|
|
};
|
|
const c = new AereCloud({ apiKey: 'ak2800.0xAAA.AERE-SINTETIC-s', baseUrl: BAZA_TEST, fetch: fetchFals(rute) });
|
|
await c.anchors(3);
|
|
await c.transfers('0xBeef', 25);
|
|
// daca reperele nu s-ar potrivi, fetchFals ar da 404 si _req ar arunca
|
|
});
|
|
|
|
await test('verifyWebhook: semnatura buna trece, una gresita pica, o litera in plus pica', async () => {
|
|
const secret = 'AERE-SINTETIC-secretul-meu';
|
|
const corp = JSON.stringify({ event: 'pq-anchor', data: { height: 42 } });
|
|
const bun = crypto.createHmac('sha256', secret).update(corp).digest('hex'); // ca serverul
|
|
assert.equal(await verifyWebhook(corp, bun, secret), true);
|
|
assert.equal(await verifyWebhook(corp, bun.slice(0, -1) + (bun.slice(-1) === 'a' ? 'b' : 'a'), secret), false);
|
|
assert.equal(await verifyWebhook(corp, bun + 'x', secret), false);
|
|
assert.equal(await verifyWebhook(corp + ' ', bun, secret), false, 'corp modificat = alta semnatura');
|
|
});
|
|
|
|
// ---- proba VIE optionala ----
|
|
if (process.env.AERE_CHEIE) {
|
|
await test('LIVE: health + account + anchors prin productie', async () => {
|
|
const c = new AereCloud({ apiKey: process.env.AERE_CHEIE });
|
|
const h = await c.health();
|
|
assert.equal(h.chainId, 2800);
|
|
assert.ok(h.block > 0);
|
|
const a = await c.anchors(1);
|
|
assert.ok(a.anchors[0].falconSeals >= 6, 'ancora vie sub cvorum');
|
|
const acc = await c.account();
|
|
assert.ok(acc.usageLast31Days);
|
|
});
|
|
} else {
|
|
console.log(' (sar proba LIVE: AERE_CHEIE nu e in mediu)');
|
|
}
|
|
|
|
console.log('\n' + treceri + ' teste trecute');
|