import { Keyring } from "@polkadot/api" ; import ApiHandler from "./ApiHandler" ; import { ClaimerConfig , EraReward , Stash } from "./types" ; import Database from "./db" ; import { KeyringPair } from "@polkadot/keyring/types" ; import { SubmittableExtrinsic } from "@polkadot/api/types" ; import logger from "./logger" ; import { sleep } from "./util" ; import MatrixBot from "./matrix" ; export default class Claimer { private db : Database ; private handler : ApiHandler ; private signer : KeyringPair ; private bot : any ; constructor ( handler , db , cfg , networkPrefix = 2 , bot ? ) { this . handler = handler ; this . db = db ; this . bot = bot ; const keyring = new Keyring ( { type : "sr25519" , } ) ; keyring . setSS58Format ( networkPrefix ) ; this . signer = keyring . createFromUri ( cfg . seed ) ; logger . info ( `(Claimer::constructor) claimer signer spawned: ${ this . address }` ) ; } public async claim ( unclaimedEras ) { const api = await this . handler . getApi ( ) ; for ( const era of unclaimedEras ) { const tx = api . tx . staking . payoutStakers ( era . stash , era . era ) ; await this . sendClaimTx ( tx , era ) ; const candidate = await this . db . getCandidate ( era . stash ) ; if ( this . bot ) { await this . bot . sendMessage ( `Claimer claimed era ${ era . era } for validator ${ candidate . name } - ${ era . stash }` ) ; } await sleep ( 12000 ) ; } return true ; } public get address ( ) : string { return this . signer . address ; } sendClaimTx = async ( tx , unclaimedEras ) : Promise < boolean > => { try { const unsub = await tx . signAndSend ( this . signer , async ( result ) => { const { status } = result ; logger . info ( `(Claimer::sendClaimTx) Status now: ${ status . type }` ) ; if ( status . isFinalized ) { const finalizedBlockHash = status . asFinalized ; logger . info ( `(Claimer::sendClaimTx) Included in block ${ finalizedBlockHash }` ) ; const faultReason = `Era ${ unclaimedEras . era } had to be claimed` ; const faultExists = await this . db . pushFaultEvent ( unclaimedEras . stash , faultReason ) ; if ( ! faultExists ) { await this . dockPoints ( unclaimedEras . stash , unclaimedEras . era ) ; await this . db . setBotClaimEvent ( unclaimedEras . stash , unclaimedEras . era , finalizedBlockHash ) ; } unsub ( ) ; } } ) ; return true ; } catch ( err ) { logger . warn ( `Nominate tx failed: ${ err }` ) ; return false ; } return true ; } ; async dockPoints ( stash , era ) { await this . db . dockPointsUnclaimedReward ( stash ) ; const candidate = await this . db . getCandidate ( stash ) ; logger . info ( `${ candidate . name } docked points for not claiming era: ${ era }. New rank: ${ candidate . rank }` ) ; if ( this . bot ) { await this . bot . sendMessage ( `${ candidate . name } docked points for not claiming era: ${ era }. New rank: ${ candidate . rank }` ) ; } return true ; } }