@@ -20,6 +20,7 @@ import { EventClaimSettledProps } from "../../types/models/EventClaimSettled";
2020import { EventClaimUpdatedProps } from "../../types/models/EventClaimUpdated" ;
2121import { EventProofUpdatedProps } from "../../types/models/EventProofUpdated" ;
2222import { EventProofValidityCheckedProps } from "../../types/models/EventProofValidityChecked" ;
23+ import { EventValidatorRewardDistributionProps } from "../../types/models/EventValidatorRewardDistribution" ;
2324import { MsgCreateClaimProps } from "../../types/models/MsgCreateClaim" ;
2425import { MsgSubmitProofProps } from "../../types/models/MsgSubmitProof" ;
2526import { CoinSDKType } from "../../types/proto-interfaces/cosmos/base/v1beta1/coin" ;
@@ -232,7 +233,8 @@ export function getAttributes(attributes: CosmosEvent["event"]["attributes"]) {
232233 chainNumEstimatedRelays : bigint | undefined ,
233234 mintedUpokt : CoinSDKType | undefined ,
234235 overservicingLossUpokt : CoinSDKType | undefined ,
235- deflationLossUpokt : CoinSDKType | undefined ;
236+ deflationLossUpokt : CoinSDKType | undefined ,
237+ supplierStakeAfterSlash : CoinSDKType | undefined ;
236238
237239 // eslint-disable-next-line @typescript-eslint/ban-ts-comment
238240 // @ts -ignore
@@ -341,6 +343,11 @@ export function getAttributes(attributes: CosmosEvent["event"]["attributes"]) {
341343 proofMissingPenalty = getDenomAndAmount ( attribute . value as string ) ;
342344 }
343345
346+ // EventSupplierSlashed field 9 (v0.1.34+): post-slash stake as a coin string.
347+ if ( attribute . key === "supplier_stake_after_slash" ) {
348+ supplierStakeAfterSlash = getDenomAndAmount ( attribute . value as string ) ;
349+ }
350+
344351 if ( attribute . key === "failure_reason" ) {
345352 failureReason = parseAttribute ( attribute . value as string ) ;
346353 }
@@ -414,6 +421,7 @@ export function getAttributes(attributes: CosmosEvent["event"]["attributes"]) {
414421 mintedUpokt,
415422 overservicingLossUpokt,
416423 deflationLossUpokt,
424+ supplierStakeAfterSlash,
417425 } ;
418426}
419427
@@ -520,14 +528,20 @@ function _handleMsgCreateClaim(msg: CosmosMessage<MsgCreateClaim>): MsgCreateCla
520528 */
521529
522530 const {
531+ chainNumEstimatedRelays,
523532 claimed,
524533 numClaimedComputedUnits,
525534 numEstimatedComputedUnits,
526535 numRelays,
527536 } = getAttributes ( eventClaimCreated . attributes ) ;
528537
529- const CUPR = Math . floor ( Number ( numClaimedComputedUnits ) / Number ( numRelays ) )
530- const numEstimatedRelays = BigInt ( Math . round ( Number ( numEstimatedComputedUnits ) / CUPR ) )
538+ // Prefer the chain-emitted num_estimated_relays (EventClaimCreated field 13,
539+ // v0.1.34+); fall back to deriving it from compute units for pre-upgrade blocks.
540+ // The helper also avoids the divide-by-zero that the raw CUPR math hits when
541+ // numRelays == 0.
542+ const numEstimatedRelays = _computeNumEstimatedRelays (
543+ chainNumEstimatedRelays , numEstimatedComputedUnits , numClaimedComputedUnits , numRelays ,
544+ ) ;
531545
532546 return {
533547 id : messageId ( msg ) ,
@@ -963,6 +977,7 @@ function _handleEventClaimSettled(
963977
964978function _handleEventClaimExpired ( event : CosmosEvent ) : EventClaimExpiredProps {
965979 const {
980+ chainNumEstimatedRelays,
966981 claim,
967982 claimed,
968983 expirationReason,
@@ -973,8 +988,12 @@ function _handleEventClaimExpired(event: CosmosEvent): EventClaimExpiredProps {
973988
974989 const { proof_validation_status, session_header, supplier_operator_address } = claim ;
975990
976- const CUPR = Math . floor ( Number ( numClaimedComputedUnits ) / Number ( numRelays ) )
977- const numEstimatedRelays = BigInt ( Math . round ( Number ( numEstimatedComputedUnits ) / CUPR ) )
991+ // Prefer the chain-emitted num_estimated_relays (EventClaimExpired field 13,
992+ // v0.1.34+); fall back to deriving it for pre-upgrade blocks (also avoids the
993+ // divide-by-zero in the raw CUPR math when numRelays == 0).
994+ const numEstimatedRelays = _computeNumEstimatedRelays (
995+ chainNumEstimatedRelays , numEstimatedComputedUnits , numClaimedComputedUnits , numRelays ,
996+ ) ;
978997
979998 return {
980999 supplierId : supplier_operator_address ,
@@ -1576,3 +1595,90 @@ export async function handleEventSettlementBatch(events: Array<CosmosEvent>): Pr
15761595 ] ) ;
15771596 }
15781597}
1598+
1599+ // EventValidatorRewardDistribution (v0.1.34+) is emitted once per bonded
1600+ // validator per settlement op_reason per settlement block. It carries the
1601+ // canonical per-validator commission/delegator split, which is the correct
1602+ // source for "VALIDATOR vs DELEGATOR" reward totals — see the entity comment in
1603+ // schema.graphql for the cross-delegation accounting caveat that makes summing
1604+ // from EventSettlementBatch alone over-count the validator side.
1605+ function _handleEventValidatorRewardDistribution ( event : CosmosEvent ) : EventValidatorRewardDistributionProps {
1606+ let sessionEndBlockHeight = BigInt ( 0 ) ,
1607+ opReason = "" ,
1608+ validatorOperatorAddress = "" ,
1609+ validatorAccountAddress = "" ,
1610+ commissionRate = "" ,
1611+ poolShareAmount = BigInt ( 0 ) ,
1612+ commissionAmount = BigInt ( 0 ) ,
1613+ selfDelegationRewardAmount = BigInt ( 0 ) ,
1614+ delegatorsRewardAmount = BigInt ( 0 ) ,
1615+ totalDelegatedStakeAmount = BigInt ( 0 ) ,
1616+ numDelegators = 0 ;
1617+
1618+ for ( const attribute of event . event . attributes ) {
1619+ switch ( attribute . key ) {
1620+ case "session_end_block_height" :
1621+ sessionEndBlockHeight = BigInt ( parseAttribute ( attribute . value ) ) ;
1622+ break ;
1623+ case "op_reason" :
1624+ opReason = parseAttribute ( attribute . value ) ;
1625+ break ;
1626+ case "validator_operator_address" :
1627+ validatorOperatorAddress = parseAttribute ( attribute . value ) ;
1628+ break ;
1629+ case "validator_account_address" :
1630+ validatorAccountAddress = parseAttribute ( attribute . value ) ;
1631+ break ;
1632+ case "commission_rate" :
1633+ commissionRate = parseAttribute ( attribute . value ) ;
1634+ break ;
1635+ // *_upokt fields are emitted as bare integer strings (no denom).
1636+ case "pool_share_upokt" :
1637+ poolShareAmount = BigInt ( parseAttribute ( attribute . value ) ) ;
1638+ break ;
1639+ case "commission_upokt" :
1640+ commissionAmount = BigInt ( parseAttribute ( attribute . value ) ) ;
1641+ break ;
1642+ case "self_delegation_reward_upokt" :
1643+ selfDelegationRewardAmount = BigInt ( parseAttribute ( attribute . value ) ) ;
1644+ break ;
1645+ case "delegators_reward_upokt" :
1646+ delegatorsRewardAmount = BigInt ( parseAttribute ( attribute . value ) ) ;
1647+ break ;
1648+ case "total_delegated_stake_upokt" :
1649+ totalDelegatedStakeAmount = BigInt ( parseAttribute ( attribute . value ) ) ;
1650+ break ;
1651+ case "num_delegators" :
1652+ numDelegators = Number ( parseAttribute ( attribute . value ) ) ;
1653+ break ;
1654+ default :
1655+ break ;
1656+ }
1657+ }
1658+
1659+ return {
1660+ // getEventId includes the event index, so per-validator/op_reason emissions
1661+ // within the same settlement block get distinct ids.
1662+ id : getEventId ( event ) ,
1663+ blockId : getBlockId ( event . block ) ,
1664+ sessionEndBlockHeight,
1665+ opReason : getSettlementOpReasonFromSDK ( opReason ) ,
1666+ validatorOperatorAddress,
1667+ validatorAccountAddress,
1668+ commissionRate,
1669+ poolShareAmount,
1670+ commissionAmount,
1671+ selfDelegationRewardAmount,
1672+ delegatorsRewardAmount,
1673+ totalDelegatedStakeAmount,
1674+ numDelegators,
1675+ } ;
1676+ }
1677+
1678+ export async function handleEventValidatorRewardDistribution ( events : Array < CosmosEvent > ) : Promise < void > {
1679+ await optimizedBulkCreate (
1680+ "EventValidatorRewardDistribution" ,
1681+ events . map ( _handleEventValidatorRewardDistribution ) ,
1682+ "block_id" ,
1683+ ) ;
1684+ }
0 commit comments