UNPKG

@noves/noves-sdk

Version:
244 lines (216 loc) 10.4 kB
/** * 1.5.0 Release Test — Core Translate APIs (regression) * * Validates that all existing Translate ecosystems still work: * - EVM, SVM, UTXO, Cosmos, TVM, Polkadot, XRPL * - Factory pattern, getChains(), getTransaction(), pagination * - Uses real hashes obtained dynamically from getTransactions() */ import { Translate, TranslateEVM, TransactionsPage, ErrorType, TransactionError } from '../dist/index'; import { section, pass, fail, runTest, skip } from './helpers'; const API_KEY = process.env.NOVES_API_KEY!; /** Extract a tx hash from a transaction object, trying multiple field paths */ function extractHash(tx: any, debug?: string): string | null { const hash = tx?.rawTransactionData?.transactionHash || tx?.rawTransactionData?.txHash || tx?.rawTransactionData?.hash || tx?.rawTransactionData?.digest || tx?.rawTransactionData?.signature || tx?.txHash || tx?.transactionHash || tx?.hash || tx?.digest || tx?.signature || null; if (!hash && debug) { console.log(` DEBUG ${debug} tx keys: ${JSON.stringify(Object.keys(tx || {}))}`); if (tx?.rawTransactionData) { console.log(` DEBUG ${debug} rawTxData keys: ${JSON.stringify(Object.keys(tx.rawTransactionData))}`); } } return hash; } export async function testCoreTranslate() { section('CORE: Translate APIs (Regression)'); // ===== EVM ===== await runTest('EVM.getChains()', async () => { const translate = Translate.evm(API_KEY); const chains = await translate.getChains(); if (!chains || (Array.isArray(chains) && chains.length === 0)) { throw new Error('EVM getChains() empty'); } pass('EVM.getChains()', `OK`); }); await runTest('EVM.getTransactions(eth, pagination)', async () => { const translate = Translate.evm(API_KEY); const address = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; // vitalik.eth const page = await translate.getTransactions('eth', address, { pageSize: 3 }); const txs = page.getTransactions(); if (!txs || txs.length === 0) throw new Error('No EVM transactions'); pass('EVM.getTransactions()', `Got ${txs.length} txs, hasNext=${page.hasNext()}`); }); // EVM getTransaction — get a real hash first await runTest('EVM.getTransaction(eth, real hash)', async () => { const translate = Translate.evm(API_KEY); const address = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; const page = await translate.getTransactions('eth', address, { pageSize: 1 }); const txs = page.getTransactions(); if (!txs || txs.length === 0) throw new Error('No txs to get hash'); const hash = extractHash(txs[0]); if (!hash) throw new Error('Could not extract hash'); const tx = await translate.getTransaction('eth', hash); if (!tx || !tx.classificationData) throw new Error('getTransaction returned invalid'); pass('EVM.getTransaction()', `type="${tx.classificationData.type}", hash=${hash.substring(0, 18)}...`); }); await runTest('EVM.getTransaction(v5 format, real hash)', async () => { const translate = Translate.evm(API_KEY); const address = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; const page = await translate.getTransactions('eth', address, { pageSize: 1 }); const txs = page.getTransactions(); const hash = extractHash(txs[0]); if (!hash) throw new Error('No hash'); const tx = await translate.getTransaction('eth', hash, 5); if (!tx) throw new Error('v5 returned null'); pass('EVM.getTransaction(v5)', `keys: ${Object.keys(tx).join(', ').substring(0, 80)}`); }); // ===== SVM (Solana) ===== await runTest('SVM.getChains()', async () => { const translate = Translate.svm(API_KEY); const chains = await translate.getChains(); if (!chains) throw new Error('SVM getChains() empty'); pass('SVM.getChains()', `OK`); }); await runTest('SVM.getTransaction(solana, real hash)', async () => { const translate = Translate.svm(API_KEY); // Get a real hash from getTransactions const address = 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK'; // known active const page = await translate.getTransactions('solana', address, { pageSize: 1 }); const txs = page.getTransactions(); if (!txs || txs.length === 0) throw new Error('No SVM transactions found'); const hash = extractHash(txs[0], 'SVM'); if (!hash) throw new Error('No SVM hash'); const tx = await translate.getTransaction('solana', hash); if (!tx) throw new Error('SVM getTransaction returned null'); pass('SVM.getTransaction()', `hash=${hash.substring(0, 18)}..., type="${(tx as any).classificationData?.type || (tx as any).type}"`); }); // ===== UTXO (Bitcoin) ===== await runTest('UTXO.getChains()', async () => { const translate = Translate.utxo(API_KEY); const chains = await translate.getChains(); if (!chains || chains.length === 0) throw new Error('UTXO getChains() empty'); pass('UTXO.getChains()', `Got ${chains.length} chains`); }); await runTest('UTXO.getAddressesByMasterKey()', async () => { const translate = Translate.utxo(API_KEY); const result = await translate.getAddressesByMasterKey( 'xpub6CUGRUonZSQ4TWtTMmzXdrXDtypWKiKrhko4egpiMZbpiaQL2jkwSB1icqYh2cfDfVxdx4df189oLKnC5fSwqPfgyP3hooxujYzAu3fDVmz', { count: 3, addressType: 'Legacy' } ); if (!result) throw new Error('getAddressesByMasterKey returned null'); pass('UTXO.getAddressesByMasterKey()', `Result keys: ${Object.keys(result).join(', ')}`); }); // ===== Cosmos ===== await runTest('Cosmos.getChains()', async () => { const translate = Translate.cosmos(API_KEY); const chains = await translate.getChains(); if (!chains) throw new Error('Cosmos getChains() empty'); pass('Cosmos.getChains()', `OK`); }); // ===== TVM (Tron) ===== await runTest('TVM.getChains()', async () => { const translate = Translate.tvm(API_KEY); const chains = await translate.getChains(); if (!chains) throw new Error('TVM getChains() empty'); pass('TVM.getChains()', `OK`); }); // ===== Polkadot ===== await runTest('Polkadot.getChains()', async () => { const translate = Translate.polkadot(API_KEY); const chains = await translate.getChains(); if (!chains) throw new Error('Polkadot getChains() empty'); pass('Polkadot.getChains()', `OK`); }); // ===== XRPL ===== await runTest('XRPL.getChains()', async () => { const translate = Translate.xrpl(API_KEY); const chains = await translate.getChains(); if (!chains) throw new Error('XRPL getChains() empty'); pass('XRPL.getChains()', `OK`); }); await runTest('XRPL.getTransactions(xrpl)', async () => { const translate = Translate.xrpl(API_KEY); const address = 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe'; const page = await translate.getTransactions('xrpl', address, { pageSize: 2 }); const txs = page.getTransactions(); if (!txs || txs.length === 0) throw new Error('No XRPL transactions'); pass('XRPL.getTransactions()', `Got ${txs.length} txs, hasNext=${page.hasNext()}`); }); await runTest('XRPL.getTransaction(xrpl, real hash)', async () => { const translate = Translate.xrpl(API_KEY); const address = 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe'; const page = await translate.getTransactions('xrpl', address, { pageSize: 1 }); const txs = page.getTransactions(); if (!txs || txs.length === 0) throw new Error('No XRPL transactions'); // XRPL uses 'signature' in rawTransactionData instead of 'transactionHash' const tx0 = txs[0] as any; const hash = tx0?.rawTransactionData?.signature || tx0?.rawTransactionData?.transactionHash || tx0?.rawTransactionData?.hash; if (!hash) { const keys = tx0?.rawTransactionData ? Object.keys(tx0.rawTransactionData).join(', ') : 'no rawTxData'; throw new Error(`No hash found in XRPL tx. rawTransactionData keys: ${keys}`); } const tx = await translate.getTransaction('xrpl', hash); if (!tx) throw new Error('XRPL getTransaction returned null'); pass('XRPL.getTransaction()', `type="${(tx as any).classificationData?.type}", hash=${hash.substring(0, 16)}...`); }); // ===== Factory pattern with SDKOptions ===== await runTest('Factory: SDKOptions with retryConfig string', async () => { const translate = Translate.evm({ apiKey: API_KEY, retryConfig: 'PRODUCTION' }); const chains = await translate.getChains(); if (!chains) throw new Error('Factory with PRODUCTION preset failed'); pass('Factory: SDKOptions', 'retryConfig="PRODUCTION" works'); }); await runTest('Factory: SDKOptions with environment', async () => { const translate = Translate.evm({ apiKey: API_KEY, environment: 'production' }); const chains = await translate.getChains(); if (!chains) throw new Error('Factory with environment failed'); pass('Factory: environment', 'environment="production" works'); }); // ===== Direct class instantiation ===== await runTest('Direct: new TranslateEVM()', async () => { const translate = new TranslateEVM(API_KEY); const chains = await translate.getChains(); if (!chains) throw new Error('Direct class instantiation failed'); pass('Direct: TranslateEVM', 'Direct class instantiation works'); }); // ===== Error types ===== await runTest('ErrorType: exports are available', async () => { if (!ErrorType || !TransactionError) { throw new Error('ErrorType or TransactionError not exported'); } const types = [ ErrorType.UNAUTHORIZED, ErrorType.RATE_LIMIT_EXCEEDED, ErrorType.NETWORK_ERROR, ErrorType.UNKNOWN_ERROR ]; if (types.some(t => t === undefined)) { throw new Error('Some ErrorType values are undefined'); } pass('ErrorType: exports', `Available: ${Object.keys(ErrorType).length} error types`); }); // ===== TransactionsPage export ===== await runTest('TransactionsPage: export and static methods', async () => { if (!TransactionsPage) { throw new Error('TransactionsPage not exported'); } if (typeof TransactionsPage.fromCursor !== 'function') { throw new Error('TransactionsPage.fromCursor not available'); } if (typeof TransactionsPage.decodeCursor !== 'function') { throw new Error('TransactionsPage.decodeCursor not available'); } pass('TransactionsPage', 'Exported with fromCursor() and decodeCursor()'); }); }