diff --git a/src/json.lua b/src/json.lua index d8ee08e..af533ec 100644 --- a/src/json.lua +++ b/src/json.lua @@ -104,7 +104,13 @@ local function encode_number(val) if val ~= val or val <= -math.huge or val >= math.huge then error("unexpected number value '" .. tostring(val) .. "'") end - return string.format("%.14g", val) + -- Handle integer values separately to avoid floating-point conversion + if math.type(val) == "integer" then + return string.format("%d", val) -- Format as an integer + else + -- Use 20 significant digits for non-integer numbers + return string.format("%.20g", val) + end end local type_func_map = { diff --git a/src/main.lua b/src/main.lua index 4c515a2..560576f 100644 --- a/src/main.lua +++ b/src/main.lua @@ -246,6 +246,9 @@ end, function(msg) lastKnownCirculatingSupply = lastKnownCirculatingSupply + (pruneGatewayResults.delegateStakeReturned or 0) + (pruneGatewayResults.gatewayStakeReturned or 0) + lastKnownWithdrawSupply = lastKnownWithdrawSupply + - (pruneGatewayResults.delegateStakeReturned or 0) + - (pruneGatewayResults.gatewayStakeReturned or 0) lastKnownStakedSupply = lastKnownStakedSupply - (pruneGatewayResults.stakeSlashed or 0) local prunedGateways = pruneGatewayResults.prunedGateways or {} @@ -1605,13 +1608,13 @@ addEventingHandler("totalTokenSupply", utils.hasMatchingTag("Action", "Total-Tok ao.send({ Target = msg.From, Action = "Total-Token-Supply-Notice", - ["Total-Token-Supply"] = totalSupply, - ["Circulating-Supply"] = circulatingSupply, - ["Locked-Supply"] = lockedSupply, - ["Staked-Supply"] = stakedSupply, - ["Delegated-Supply"] = delegatedSupply, - ["Withdraw-Supply"] = withdrawSupply, - ["Protocol-Balance"] = protocolBalance, + ["Total-Token-Supply"] = tostring(totalSupply), + ["Circulating-Supply"] = tostring(circulatingSupply), + ["Locked-Supply"] = tostring(lockedSupply), + ["Staked-Supply"] = tostring(stakedSupply), + ["Delegated-Supply"] = tostring(delegatedSupply), + ["Withdraw-Supply"] = tostring(withdrawSupply), + ["Protocol-Balance"] = tostring(protocolBalance), Data = json.encode({ -- TODO: we are losing precision on these values unexpectedly. This has been brought to the AO team - for now the tags should be correct as they are stringified total = totalSupply, diff --git a/tests/monitor/monitor.test.mjs b/tests/monitor/monitor.test.mjs index a6ffd23..bcea7e5 100644 --- a/tests/monitor/monitor.test.mjs +++ b/tests/monitor/monitor.test.mjs @@ -178,78 +178,78 @@ describe('setup', () => { ); // TODO: there is an unknown precision loss on these values, we are discussing why with Forward. Once fixed, uncomment these tests - // const { items: balances } = await io.getBalances({ - // limit: 10_000, - // }); + const { items: balances } = await io.getBalances({ + limit: 10_000, + }); - // const protocolBalance = await io.getBalance({ - // address: processId, - // }); + const protocolBalance = await io.getBalance({ + address: processId, + }); - // assert( - // protocolBalance === supplyData.protocolBalance, - // `Protocol balance is not equal to the balance provided by the contract: ${protocolBalance} !== ${supplyData.protocolBalance}`, - // ); + assert( + protocolBalance === supplyData.protocolBalance, + `Protocol balance is not equal to the balance provided by the contract: ${protocolBalance} !== ${supplyData.protocolBalance}`, + ); - // const totalBalances = balances.reduce( - // (acc, curr) => acc + curr.balance, - // 0, - // ); - // const circulating = totalBalances - protocolBalance; - // assert( - // circulating === supplyData.circulating, - // `Circulating supply is not equal to the sum of the balances minus the protocol balance: ${circulating} !== ${supplyData.circulating}`, - // ); + const totalBalances = balances.reduce( + (acc, curr) => acc + curr.balance, + 0, + ); + const circulating = totalBalances - protocolBalance; + assert( + circulating === supplyData.circulating, + `Circulating supply is not equal to the sum of the balances minus the protocol balance: ${circulating} !== ${supplyData.circulating}`, + ); - // // get the supply staked - // const { items: gateways } = await io.getGateways({ - // limit: 1000, - // }); + // get the supply staked + const { items: gateways } = await io.getGateways({ + limit: 1000, + }); - // const staked = gateways.reduce( - // (acc, curr) => acc + curr.operatorStake, - // 0, - // ); + const staked = gateways.reduce( + (acc, curr) => acc + curr.operatorStake, + 0, + ); - // assert( - // staked === supplyData.staked, - // `Staked supply is not equal to the sum of the operator stakes: ${staked} !== ${supplyData.staked}`, - // ); + assert( + staked === supplyData.staked, + `Staked supply is not equal to the sum of the operator stakes: ${staked} !== ${supplyData.staked}`, + ); - // const delegated = gateways.reduce( - // (acc, curr) => acc + curr.totalDelegatedStake, - // 0, - // ); + const delegated = gateways.reduce( + (acc, curr) => acc + curr.totalDelegatedStake, + 0, + ); - // assert( - // delegated === supplyData.delegated, - // `Delegated supply is not equal to the sum of the total delegated stakes: ${delegated} !== ${supplyData.delegated}`, - // ); + assert( + delegated === supplyData.delegated, + `Delegated supply is not equal to the sum of the total delegated stakes: ${delegated} !== ${supplyData.delegated}`, + ); - // const computedTotal = - // supplyData.circulating + - // supplyData.locked + - // supplyData.withdrawn + - // supplyData.staked + - // supplyData.delegated + - // supplyData.protocolBalance; - // assert( - // supplyData.total === computedTotal && - // computedTotal === 1000000000 * 1000000, - // `Computed total supply (${computedTotal}) is not equal to the sum of protocol balance, circulating, locked, staked, and delegated and withdrawn provided by the contract (${supplyData.total}) and does not match the expected total of 1 billion IO`, - // ); + const computedTotal = + supplyData.circulating + + supplyData.locked + + supplyData.withdrawn + + supplyData.staked + + supplyData.delegated + + supplyData.protocolBalance; + assert( + supplyData.total === computedTotal && + computedTotal === 1000000000 * 1000000, + `Computed total supply (${computedTotal}) is not equal to the sum of protocol balance, circulating, locked, staked, and delegated and withdrawn provided by the contract (${supplyData.total}) and does not match the expected total of 1 billion IO`, + ); - // const computedCirculating = - // supplyData.total - - // supplyData.locked - - // supplyData.staked - - // supplyData.delegated - - // supplyData.withdrawn - - // supplyData.protocolBalance; - // assert( - // supplyData.circulating === computedCirculating, - // `Computed circulating supply (${computedCirculating}) is not equal to the total supply minus protocol balance, locked, staked, delegated, and withdrawn provided by the contract (${supplyData.circulating})`, - // ); + const computedCirculating = + supplyData.total - + supplyData.locked - + supplyData.staked - + supplyData.delegated - + supplyData.withdrawn - + supplyData.protocolBalance; + assert( + supplyData.circulating === computedCirculating, + `Computed circulating supply (${computedCirculating}) is not equal to the total supply minus protocol balance, locked, staked, delegated, and withdrawn provided by the contract (${supplyData.circulating})`, + ); }); }); @@ -369,8 +369,8 @@ describe('setup', () => { ); let cursor = ''; - let countedTotalGateways = 0; let totalGateways = 0; + const uniqueGateways = new Set(); do { const { items: gateways, @@ -380,9 +380,9 @@ describe('setup', () => { cursor, }); totalGateways = totalItems; - countedTotalGateways += gateways.length; for (const gateway of gateways) { if (gateway.status === 'joined') { + uniqueGateways.add(gateway.gatewayAddress); assert( Number.isInteger(gateway.operatorStake), `Gateway ${gateway.gatewayAddress} has an invalid operator stake: ${gateway.operatorStake}`, @@ -477,8 +477,8 @@ describe('setup', () => { cursor = nextCursor; } while (cursor !== undefined); assert( - countedTotalGateways === totalGateways, - `Counted total gateways (${countedTotalGateways}) does not match total gateways (${totalGateways})`, + uniqueGateways.size === totalGateways, + `Counted total gateways (${uniqueGateways.size}) does not match total gateways (${totalGateways})`, ); }); }); @@ -488,8 +488,8 @@ describe('setup', () => { const twoWeeks = 2 * 7 * 24 * 60 * 60 * 1000; it('should not have any arns records older than two weeks', async () => { let cursor = ''; - let countedTotalArns = 0; let totalArns = 0; + const uniqueNames = new Set(); do { const { items: arns, @@ -499,8 +499,8 @@ describe('setup', () => { cursor, }); totalArns = totalItems; - countedTotalArns += arns.length; for (const arn of arns) { + uniqueNames.add(arn.name); assert(arn.processId, `ARNs name '${arn.name}' has no processId`); assert(arn.type, `ARNs name '${arn.name}' has no type`); assert( @@ -536,8 +536,8 @@ describe('setup', () => { cursor = nextCursor; } while (cursor !== undefined); assert( - countedTotalArns === totalArns, - `Counted total ARNs (${countedTotalArns}) does not match total ARNs (${totalArns})`, + uniqueNames.size === totalArns, + `Counted total ARNs (${uniqueNames.size}) does not match total ARNs (${totalArns})`, ); }); });