mango-token-sale/scripts/governance-notifier.ts

110 lines
3.1 KiB
TypeScript

import { PublicKey } from '@solana/web3.js'
import axios from 'axios'
import { RealmInfo } from '../@types/types'
import { getAccountTypes, Governance, Proposal } from '../models/accounts'
import { ParsedAccount } from '../models/serialisation'
import { ENDPOINTS } from '../stores/useWalletStore'
import { getGovernanceAccounts, pubkeyFilter } from './api'
const fiveMinutesSeconds = 5 * 60
const toleranceSeconds = 30
// run every 5 mins, checks if a mngo governance proposal just opened in the last 5 mins
// and notifies on WEBHOOK_URL
async function runNotifier() {
const nowInSeconds = new Date().getTime() / 1000
const REALMS: RealmInfo[] = [
{
symbol: 'MNGO',
programId: new PublicKey('GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J'),
realmId: new PublicKey('DPiH3H3c7t47BMxqTxLsuPQpEC6Kne8GA9VXbxpnZxFE'),
},
]
const CLUSTER = 'mainnet-beta'
const ENDPOINT = ENDPOINTS.find((e) => e.name === CLUSTER)
const realmInfo = REALMS.find((r) => r.symbol === 'MNGO')
const governances = await getGovernanceAccounts<Governance>(
realmInfo.programId,
ENDPOINT.url,
Governance,
getAccountTypes(Governance),
[pubkeyFilter(1, realmInfo.realmId)]
)
const governanceIds = Object.keys(governances).map((k) => new PublicKey(k))
const proposalsByGovernance = await Promise.all(
governanceIds.map((governanceId) => {
return getGovernanceAccounts<Proposal>(
realmInfo.programId,
ENDPOINT.url,
Proposal,
getAccountTypes(Proposal),
[pubkeyFilter(1, governanceId)]
)
})
)
const proposals: {
[proposal: string]: ParsedAccount<Proposal>
} = Object.assign({}, ...proposalsByGovernance)
const realmGovernances = Object.fromEntries(
Object.entries(governances).filter(([_k, v]) =>
v.info.realm.equals(realmInfo.realmId)
)
)
const realmProposals = Object.fromEntries(
Object.entries(proposals).filter(([_k, v]) =>
Object.keys(realmGovernances).includes(v.info.governance.toBase58())
)
)
console.log(`- scanning all proposals`)
let countJustOpenedForVoting = 0
let countVotingNotStartedYet = 0
let countClosed = 0
for (const k in realmProposals) {
const proposal = realmProposals[k]
if (
// voting is closed
proposal.info.votingCompletedAt
) {
countClosed++
continue
}
if (
// voting has not started yet
!proposal.info.votingAt
) {
countVotingNotStartedYet++
continue
}
if (
// proposal opened in last 5 mins
nowInSeconds - proposal.info.votingAt.toNumber() <=
fiveMinutesSeconds + toleranceSeconds
) {
countJustOpenedForVoting++
const msg = `--- ${proposal.info.name} proposal just opened for voting`
console.log(msg)
if (process.env.WEBHOOK_URL) {
axios.post(process.env.WEBHOOK_URL, { msg })
}
}
}
console.log(
`-- countJustOpenedForVoting: ${countJustOpenedForVoting}, countVotingNotStartedYet: ${countVotingNotStartedYet}, countClosed: ${countClosed}`
)
}
setInterval(runNotifier, fiveMinutesSeconds * 1000)