From 0cc45e07d8331e4bab43c494f65a7fe09fca1bea Mon Sep 17 00:00:00 2001 From: Adam A Date: Fri, 2 Aug 2024 13:33:27 +0300 Subject: [PATCH] refactor(namada): use plain objects for proposal results --- packages/namada/NamadaConnection.ts | 2 +- packages/namada/NamadaGov.ts | 119 +++++++++++++--------------- 2 files changed, 54 insertions(+), 67 deletions(-) diff --git a/packages/namada/NamadaConnection.ts b/packages/namada/NamadaConnection.ts index de213b717e..68891ca327 100644 --- a/packages/namada/NamadaConnection.ts +++ b/packages/namada/NamadaConnection.ts @@ -56,7 +56,7 @@ export default class NamadaConnection extends CW.Connection { return Gov.fetchProposalCount(this) } fetchProposalInfoImpl (id: number|bigint) { - return Gov.Proposal.fetch(this, id) + return Gov.fetchProposalInfo(this, id) } fetchPGFParametersImpl () { diff --git a/packages/namada/NamadaGov.ts b/packages/namada/NamadaGov.ts index 0eeb5055f5..763e16d193 100644 --- a/packages/namada/NamadaGov.ts +++ b/packages/namada/NamadaGov.ts @@ -16,83 +16,70 @@ export async function fetchProposalCount (connection: Pick, id: number|bigint +): Promise { + const proposalResponse = await connection.abciQuery(`/vp/governance/proposal/${id}`) + if (proposalResponse[0] === 0) return null + const [ votesResponse, resultResponse ] = await Promise.all([ + `/vp/governance/proposal/${id}/votes`, + `/vp/governance/stored_proposal_result/${id}`, + ].map(x=>connection.abciQuery(x))) + const proposal = connection.decode.gov_proposal(proposalResponse.slice(1)) as + ReturnType + const votes = connection.decode.gov_votes(votesResponse) as + ReturnType + const result = (resultResponse[0] === 0) ? null + : decodeResultResponse(connection.decode.gov_result(resultResponse.slice(1)) as + Required>) + return { id: BigInt(id), proposal, votes, result } +} + +const decodeResultResponse = ( + decoded: { + result: "Passed"|"Rejected" + tallyType: "TwoThirds"|"OneHalfOverOneThird"|"LessOneHalfOverOneThirdNay" + totalVotingPower: bigint + totalYayPower: bigint + totalNayPower: bigint + totalAbstainPower: bigint + }, + turnout = decoded.totalYayPower! + decoded.totalNayPower! + decoded.totalAbstainPower! +): NamadaGovernanceProposalResult => ({ + ...decoded, + turnout: String(turnout), + turnoutPercent: (decoded.totalVotingPower! > 0) ? percent(turnout, decoded.totalVotingPower!) : '0', + yayPercent: (turnout > 0) ? percent(decoded.totalYayPower!, turnout) : '0', + nayPercent: (turnout > 0) ? percent(decoded.totalNayPower!, turnout) : '0', + abstainPercent: (turnout > 0) ? percent(decoded.totalAbstainPower!, turnout) : '0', +}) + export const INTERNAL_ADDRESS = "tnam1q5qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrw33g6" -class NamadaGovernanceProposal { +interface NamadaGovernanceProposal { readonly id: bigint readonly proposal: ReturnType readonly votes: ReturnType readonly result: NamadaGovernanceProposalResult|null - constructor (props: Pick) { - this.id = props?.id - this.proposal = props?.proposal - this.votes = props?.votes - this.result = props?.result ? new NamadaGovernanceProposalResult(props.result) : null - } - static async fetch ( - connection: Pick, id: number|bigint - ) { - const proposalResponse = await connection.abciQuery(`/vp/governance/proposal/${id}`) - if (proposalResponse[0] === 0) return null - const [ votesResponse, resultResponse ] = await Promise.all([ - `/vp/governance/proposal/${id}/votes`, - `/vp/governance/stored_proposal_result/${id}`, - ].map(x=>connection.abciQuery(x))) - return new this({ - id: - BigInt(id), - proposal: - connection.decode.gov_proposal(proposalResponse.slice(1)) as - ReturnType, - votes: - connection.decode.gov_votes(votesResponse) as - ReturnType, - result: (resultResponse[0] === 0) - ? null - : new NamadaGovernanceProposalResult( - connection.decode.gov_result(resultResponse.slice(1)) - ) - }) - } } -class NamadaGovernanceProposalResult implements ReturnType { - result!: "Passed"|"Rejected" - tallyType!: "TwoThirds"|"OneHalfOverOneThird"|"LessOneHalfOverOneThirdNay" - totalVotingPower!: bigint - totalYayPower!: bigint - totalNayPower!: bigint - totalAbstainPower!: bigint - constructor (properties: Partial = {}) { - assign(this, properties, [ - 'result', - 'tallyType', - 'totalVotingPower', - 'totalYayPower', - 'totalNayPower', - 'totalAbstainPower', - ]) - } - get turnout () { - return this.totalYayPower + this.totalNayPower + this.totalAbstainPower - } - get turnoutPercent () { - return percent(this.turnout, this.totalVotingPower) - } - get yayPercent () { - return percent(this.totalYayPower, this.turnout) - } - get nayPercent () { - return percent(this.totalNayPower, this.turnout) - } - get abstainPercent () { - return percent(this.totalAbstainPower, this.turnout) - } +interface NamadaGovernanceProposalResult { + readonly result: "Passed"|"Rejected" + readonly tallyType: "TwoThirds"|"OneHalfOverOneThird"|"LessOneHalfOverOneThirdNay" + readonly totalVotingPower: bigint + readonly totalYayPower: bigint + readonly totalNayPower: bigint + readonly totalAbstainPower: bigint + readonly turnout: string + readonly turnoutPercent: string + readonly yayPercent: string + readonly nayPercent: string + readonly abstainPercent: string } -const percent = (a: bigint, b: bigint) => - ((Number(a * 1000000n / b) / 10000).toFixed(2) + '%').padStart(7) +const percent = (a: string|number|bigint, b: string|number|bigint) => + ((Number(BigInt(a) * 1000000n / BigInt(b)) / 10000).toFixed(2) + '%').padStart(7) export { NamadaGovernanceProposal as Proposal,