Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 76 additions & 2 deletions tests/unit/handlers/finance.handlers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,34 @@ test('processTailLogData - processes power and hashrate', (t) => {
t.pass()
})

test('processTailLogData - drills into .val (production shape)', (t) => {
const results = [
[
{
type: 'powermeter',
data: [
{ ts: 1700006400000, val: { site_power_w: 5000 } },
{ ts: 1700092800000, val: { site_power_w: 6000 } }
]
},
{
type: 'miner',
data: [
{ ts: 1700006400000, val: { hashrate_mhs_5m_sum_aggr: 100000 } },
{ ts: 1700092800000, val: { hashrate_mhs_5m_sum_aggr: 120000 } }
]
}
]
]

const daily = processTailLogData(results)
t.is(daily[1700006400000].powerW, 5000, 'extracts powerW from .val on day 1')
t.is(daily[1700006400000].hashrateMhs, 100000, 'extracts hashrateMhs from .val on day 1')
t.is(daily[1700092800000].powerW, 6000, 'extracts powerW from .val on day 2')
t.is(daily[1700092800000].hashrateMhs, 120000, 'extracts hashrateMhs from .val on day 2')
t.pass()
})

test('processTailLogData - handles error results', (t) => {
const results = [{ error: 'timeout' }]
const daily = processTailLogData(results)
Expand All @@ -371,6 +399,19 @@ test('processEbitdaPrices - processes valid data', (t) => {
t.pass()
})

test('processEbitdaPrices - flat per-ork items with priceUSD (production shape)', (t) => {
const results = [
[
{ ts: 1700006400000, priceUSD: 40000 },
{ ts: 1700092800000, priceUSD: 41500 }
]
]
const daily = processEbitdaPrices(results)
t.is(daily[1700006400000], 40000, 'should extract priceUSD for first day')
t.is(daily[1700092800000], 41500, 'should extract priceUSD for second day')
t.pass()
})

test('calculateEbitdaSummary - calculates from log entries', (t) => {
const log = [
{ revenueBTC: 0.5, revenueUSD: 20000, totalCostsUSD: 5000, ebitdaSelling: 15000, ebitdaHodl: 15000 },
Expand Down Expand Up @@ -569,16 +610,18 @@ test('getSubsidyFees - empty ork results', async (t) => {

test('calculateSubsidyFeesSummary - calculates from log entries', (t) => {
const log = [
{ blockReward: 6.25, blockTotalFees: 0.5 },
{ blockReward: 6.25, blockTotalFees: 0.3 }
{ blockReward: 6.25, blockTotalFees: 0.5, blockSize: 1500000 },
{ blockReward: 6.25, blockTotalFees: 0.3, blockSize: 1300000 }
]

const summary = calculateSubsidyFeesSummary(log)
t.is(summary.totalBlockReward, 12.5, 'should sum block rewards')
t.is(summary.totalBlockTotalFees, 0.8, 'should sum block fees')
t.is(summary.totalBlockSize, 2800000, 'should sum block sizes')
t.ok(summary.avgBlockReward !== null, 'should calculate avg block reward')
t.is(summary.avgBlockReward, 6.25, 'should calculate correct avg block reward')
t.ok(summary.avgBlockTotalFees !== null, 'should calculate avg block fees')
t.is(summary.avgBlockSize, 1400000, 'should calculate correct avg block size')
t.pass()
})

Expand Down Expand Up @@ -990,6 +1033,24 @@ test('processHashrateData - processes array data', (t) => {
t.pass()
})

test('processHashrateData - drills into .val (production shape)', (t) => {
const results = [
[
{
type: 'miner',
data: [
{ ts: 1700006400000, val: { hashrate_mhs_5m_sum_aggr: 500000 } },
{ ts: 1700092800000, val: { hashrate_mhs_5m_sum_aggr: 600000 } }
]
}
]
]
const daily = processHashrateData(results)
t.is(daily[1700006400000], 500000, 'extracts hashrate from .val on day 1')
t.is(daily[1700092800000], 600000, 'extracts hashrate from .val on day 2')
t.pass()
})

test('processHashrateData - handles error results', (t) => {
const results = [{ error: 'timeout' }]
const daily = processHashrateData(results)
Expand All @@ -1010,6 +1071,19 @@ test('processNetworkHashrateData - processes array data', (t) => {
t.pass()
})

test('processNetworkHashrateData - flat per-ork items (production shape)', (t) => {
const results = [
[
{ ts: 1700006400000, avgHashrateMHs: 1019725948656278 },
{ ts: 1700092800000, avgHashrateMHs: 1029591824888537 }
]
]
const daily = processNetworkHashrateData(results)
t.is(daily[1700006400000], 1019725948656278, 'extracts avgHashrateMHs day 1')
t.is(daily[1700092800000], 1029591824888537, 'extracts avgHashrateMHs day 2')
t.pass()
})

test('processNetworkHashrateData - processes object-keyed data', (t) => {
const results = [
[{ data: { 1700006400000: { avgHashrateMHs: 500000000000000 } } }]
Expand Down
19 changes: 18 additions & 1 deletion tests/unit/handlers/finance.utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,31 @@ test('processBlockData - array items', (t) => {
blocks: [{
ts: 1700006400000,
blockReward: 6.25,
blockTotalFees: 0.5
blockTotalFees: 0.5,
blockSize: 1500000
}]
}]
]
const daily = processBlockData(results)
const key = Object.keys(daily)[0]
t.is(daily[key].blockReward, 6.25, 'should extract blockReward')
t.is(daily[key].blockTotalFees, 0.5, 'should extract blockTotalFees')
t.is(daily[key].blockSize, 1500000, 'should extract blockSize')
t.pass()
})

test('processBlockData - flat per-ork items (production shape)', (t) => {
const results = [
[
{ ts: 1700006400000, blockSize: 1500000, blockHash: 'abc', blockReward: 6.25, blockTotalFees: 0.5 },
{ ts: 1700006400000, blockSize: 1200000, blockHash: 'def', blockReward: 6.25, blockTotalFees: 0.3 }
]
]
const daily = processBlockData(results)
const key = Object.keys(daily)[0]
t.is(daily[key].blockReward, 12.5, 'should sum blockReward across same-day items')
t.is(daily[key].blockTotalFees, 0.8, 'should sum blockTotalFees across same-day items')
t.is(daily[key].blockSize, 2700000, 'should sum blockSize across same-day items')
t.pass()
})

Expand Down
46 changes: 29 additions & 17 deletions workers/lib/server/handlers/finance.handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,9 @@ function processTailLogData (results) {
for (const item of items) {
const ts = getStartOfDay(item.ts || item.timestamp)
if (!daily[ts]) daily[ts] = { powerW: 0, hashrateMhs: 0 }
daily[ts].powerW += (item[AGGR_FIELDS.SITE_POWER] || 0)
daily[ts].hashrateMhs += (item[AGGR_FIELDS.HASHRATE_SUM] || 0)
const val = item.val || item
daily[ts].powerW += (val[AGGR_FIELDS.SITE_POWER] || 0)
daily[ts].hashrateMhs += (val[AGGR_FIELDS.HASHRATE_SUM] || 0)
}
}
}
Expand All @@ -449,19 +450,21 @@ function processEbitdaPrices (results) {
if (!Array.isArray(data)) continue
for (const entry of data) {
if (!entry) continue
const items = entry.data || entry.prices || entry
const rawTs = entry.ts || entry.timestamp || entry.time
const items = rawTs ? [entry] : (entry.data || entry.prices || entry)
if (Array.isArray(items)) {
for (const item of items) {
const ts = getStartOfDay(item.ts || item.timestamp || item.time)
if (ts && item.price) {
daily[ts] = item.price
const price = item.priceUSD || item.price
if (ts && price) {
daily[ts] = price
}
}
} else if (typeof items === 'object' && !Array.isArray(items)) {
} else if (typeof items === 'object') {
for (const [key, val] of Object.entries(items)) {
const ts = getStartOfDay(Number(key))
if (ts) {
daily[ts] = typeof val === 'object' ? (val.USD || val.price || 0) : Number(val) || 0
daily[ts] = typeof val === 'object' ? (val.USD || val.priceUSD || val.price || 0) : Number(val) || 0
}
}
}
Expand Down Expand Up @@ -518,7 +521,7 @@ async function getCostSummary (ctx, req) {

(cb) => ctx.dataProxy.requestData(RPC_METHODS.GET_WRK_EXT_DATA, {
type: WORKER_TYPES.MEMPOOL,
query: { key: 'prices', start, end }
query: { key: 'HISTORICAL_PRICES', start, end }
}).then(r => cb(null, r)).catch(cb),

(cb) => ctx.dataProxy.requestData(RPC_METHODS.TAIL_LOG_RANGE_AGGR, {
Expand Down Expand Up @@ -628,7 +631,8 @@ async function getSubsidyFees (ctx, req) {
log.push({
ts,
blockReward: block.blockReward,
blockTotalFees: block.blockTotalFees
blockTotalFees: block.blockTotalFees,
blockSize: block.blockSize
})
}

Expand All @@ -643,22 +647,27 @@ function calculateSubsidyFeesSummary (log) {
return {
totalBlockReward: 0,
totalBlockTotalFees: 0,
totalBlockSize: 0,
avgBlockReward: null,
avgBlockTotalFees: null
avgBlockTotalFees: null,
avgBlockSize: null
}
}

const totals = log.reduce((acc, entry) => {
acc.blockReward += entry.blockReward || 0
acc.blockTotalFees += entry.blockTotalFees || 0
acc.blockSize += entry.blockSize || 0
return acc
}, { blockReward: 0, blockTotalFees: 0 })
}, { blockReward: 0, blockTotalFees: 0, blockSize: 0 })

return {
totalBlockReward: totals.blockReward,
totalBlockTotalFees: totals.blockTotalFees,
totalBlockSize: totals.blockSize,
avgBlockReward: safeDiv(totals.blockReward, log.length),
avgBlockTotalFees: safeDiv(totals.blockTotalFees, log.length)
avgBlockTotalFees: safeDiv(totals.blockTotalFees, log.length),
avgBlockSize: safeDiv(totals.blockSize, log.length)
}
}

Expand Down Expand Up @@ -879,6 +888,7 @@ async function getRevenueSummary (ctx, req) {
hashRevenueUSDPerPHsPerDay: safeDiv(revenueUSD, hashratePhs),
blockReward: block.blockReward || 0,
blockTotalFees: block.blockTotalFees || 0,
blockSize: block.blockSize || 0,
curtailmentMWh,
curtailmentRate,
operationalIssuesRate,
Expand Down Expand Up @@ -1087,7 +1097,8 @@ function processHashrateData (results) {
const ts = getStartOfDay(item.ts || item.timestamp)
if (!ts) continue
if (!daily[ts]) daily[ts] = 0
daily[ts] += (item[AGGR_FIELDS.HASHRATE_SUM] || 0)
const val = item.val || item
daily[ts] += (val[AGGR_FIELDS.HASHRATE_SUM] || 0)
}
}
}
Expand All @@ -1103,18 +1114,19 @@ function processNetworkHashrateData (results) {
if (!Array.isArray(data)) continue
for (const entry of data) {
if (!entry) continue
const items = entry.data || entry
const rawTs = entry.ts || entry.timestamp || entry.time
const items = rawTs ? [entry] : (entry.data || entry)
if (Array.isArray(items)) {
for (const item of items) {
if (!item) continue
const rawTs = item.ts || item.timestamp || item.time
const ts = getStartOfDay(normalizeTimestampMs(rawTs))
const itemTs = item.ts || item.timestamp || item.time
const ts = getStartOfDay(normalizeTimestampMs(itemTs))
if (!ts) continue
if (item.avgHashrateMHs) {
daily[ts] = item.avgHashrateMHs
}
}
} else if (typeof items === 'object' && !Array.isArray(items)) {
} else if (typeof items === 'object') {
for (const [key, val] of Object.entries(items)) {
const ts = getStartOfDay(Number(key))
if (!ts) continue
Expand Down
15 changes: 9 additions & 6 deletions workers/lib/server/handlers/finance.utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,25 +94,28 @@ function processBlockData (results) {
if (!Array.isArray(data)) continue
for (const entry of data) {
if (!entry) continue
const items = entry.data || entry.blocks || entry
const rawTs = entry.ts || entry.timestamp || entry.time
const items = rawTs ? [entry] : (entry.data || entry.blocks || entry)
if (Array.isArray(items)) {
for (const item of items) {
if (!item) continue
const rawTs = item.ts || item.timestamp || item.time
const ts = getStartOfDay(normalizeTimestampMs(rawTs))
const itemTs = item.ts || item.timestamp || item.time
const ts = getStartOfDay(normalizeTimestampMs(itemTs))
if (!ts) continue
if (!daily[ts]) daily[ts] = { blockReward: 0, blockTotalFees: 0 }
if (!daily[ts]) daily[ts] = { blockReward: 0, blockTotalFees: 0, blockSize: 0 }
daily[ts].blockReward += (item.blockReward || item.block_reward || item.subsidy || 0)
daily[ts].blockTotalFees += (item.blockTotalFees || item.block_total_fees || item.totalFees || item.total_fees || 0)
daily[ts].blockSize += (item.blockSize || item.block_size || item.size || 0)
}
} else if (typeof items === 'object' && !Array.isArray(items)) {
} else if (typeof items === 'object') {
for (const [key, val] of Object.entries(items)) {
const ts = getStartOfDay(Number(key))
if (!ts) continue
if (!daily[ts]) daily[ts] = { blockReward: 0, blockTotalFees: 0 }
if (!daily[ts]) daily[ts] = { blockReward: 0, blockTotalFees: 0, blockSize: 0 }
if (typeof val === 'object') {
daily[ts].blockReward += (val.blockReward || val.block_reward || val.subsidy || 0)
daily[ts].blockTotalFees += (val.blockTotalFees || val.block_total_fees || val.totalFees || val.total_fees || 0)
daily[ts].blockSize += (val.blockSize || val.block_size || val.size || 0)
}
}
}
Expand Down
Loading