7import { EtherscanProvider } from 'ethers' 11const assertEq = <T,>(actual: T, expected: T, label?: string) => { 12 if (actual !== expected) throw new Error(`${label ? label + ': ' : ''}Expected ${expected}, got ${actual}`) 15// Known payment address that received test txs on Arbitrum (getEtherTxs filters for incoming txs) 16const knownArbPaymentAddr = peatTestfundAddr 17// Known tx to this address on Arbitrum at block 454580315 18const knownArbTxBlock = 454580315 19const knownArbTxHash = '0xccaadf2ed1268dcbe2294f5eb082e0cc96f787bbbb9af2e4cdb512d0ec33da0c' 24 test('seededShuffle: deterministic for same seed', async () => { 25 const addrs = ['0xAAA', '0xBBB', '0xCCC', '0xDDD'] 27 return {passed: true, msg: ''} 29 test('seededShuffle: single element always returns that element', async () => { 30 for (const email of ['a@b.com', 'x@y.com', 'foo@bar.com']) { 33 return {passed: true, msg: ''} 35 test('findFreeGwei: returns target when no collisions', async () => { 36 assertEq(findFreeGwei({tgtGwei: 1000000, pendingGweis: []}), 1000000) 37 return {passed: true, msg: ''} 39 test('findFreeGwei: avoids collisions', async () => { 40 const pendingGweis = [1000000, 999000, 1001000] 42 if (pendingGweis.includes(result)) return {passed: false, msg: `Result ${result} collides with pending`} 43 if (result !== 998000 && result !== 1002000) return {passed: false, msg: `Expected 998000 or 1002000, got ${result}`} 44 return {passed: true, msg: ''} 46 test('usdToTargetGwei: converts correctly', async () => { 47 assertEq(usdToTargetGwei({totalUsd: 10, ethPrice: 2000}), Math.round(10 / 2000 * 1e9 / gweiStep) * gweiStep) 48 return {passed: true, msg: ''} 50 test('roundedGwei: rounds bigint to gwei', async () => { 51 assertEq(roundedGwei({value: BigInt('1000000000000000')}), 1000000) 52 return {passed: true, msg: ''} 55 // Live integration tests for getEtherTxs - verifies provider wrappers work end-to-end 56 // These would have caught: Etherscan V2 migration, endblock bugs, normalization issues 57 const getArbProv = () => { 59 return apiKey ? new EtherscanProvider('arbitrum', apiKey) : null 62 test('getEtherTxs: Etherscan finds txs with startBlock on arbitrum', async () => { 63 const prov = getArbProv() 64 if (!prov) return skipTest('no etherscan_api secret') 65 const txs = await getEtherTxs({address: knownArbPaymentAddr, startBlock: knownArbTxBlock - 100, endBlock: undefined, ethersProvider: prov}) 66 if (!txs.length) return {passed: false, msg: 'No txs returned - startBlock filtering may be broken'} 67 const found = txs.find((tx: {hash?: string}) => tx.hash === knownArbTxHash) 68 if (!found) return {passed: false, msg: `Known tx ${knownArbTxHash.slice(0, 16)}... not found in ${txs.length} results`} 69 if (!found.eth_gwei) return {passed: false, msg: 'tx missing eth_gwei - normalization broken'} 70 return {passed: true, msg: `found ${txs.length} txs incl ${knownArbTxHash.slice(0, 10)}...`} 73 test('getEtherTxs: returns empty array for unused address', async () => { 74 const prov = getArbProv() 75 if (!prov) return skipTest('no etherscan_api secret') 76 const randomAddr = '0x' + 'ab'.repeat(20) 77 const txs = await getEtherTxs({address: randomAddr, startBlock: 445000000, endBlock: undefined, ethersProvider: prov}) 78 if (!Array.isArray(txs)) return {passed: false, msg: `Expected array, got ${typeof txs}`} 79 return {passed: true, msg: `${txs.length} txs (expected 0)`} 85export const ethpaySuiteConfig = { name: 'ethpay', runner: runEthpaySuite, deps: [] } as const