Skip to content

Commit

Permalink
Added listProposals RPC (#486)
Browse files Browse the repository at this point in the history
* Added createCfp RPC

* pass cmd -fortcanningheight=7 as argument to MasterNodeRegTestContainer

* Governance container file with correct configuration

* change CFPData interface property order

* change CFPData interface property order in API documentation

* Added getProposal RPC

* Added createVoc RPC

* Added listProposals RPC

* bump docker image version

* fix JSDoc optional title

* Added listProposals RPC

* Filters -eunospayaheight=7 due to invalid flag
  • Loading branch information
Jouzo authored Jul 29, 2021
1 parent 1c129fb commit fa2df26
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ export class GovernanceMasterNodeRegTestContainer extends MasterNodeRegTestConta
}

protected getCmd (opts: StartOptions): string[] {
const cmd = super.getCmd(opts).filter(cmd => cmd !== '-eunospayaheight=7') // temporary remove -eunospayaheight=7 due to invalid flag
return [
...super.getCmd(opts),
'-fortcanningheight=7'
...cmd,
'-fortcanningheight=8',
'-dummypos=0' // Needed to expire proposals
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { ContainerAdapterClient } from '../../container_adapter_client'
import { ListProposalsStatus, ListProposalsType, ProposalStatus, ProposalType } from '../../../src/category/governance'
import { GovernanceMasterNodeRegTestContainer } from './governance_container'

describe('Governance', () => {
const container = new GovernanceMasterNodeRegTestContainer()
const client = new ContainerAdapterClient(container)

beforeAll(async () => {
await container.start()
await container.waitForReady()
await container.waitForWalletCoinbaseMaturity()

await setup()
})

async function setup (): Promise<void> {
await container.call('createcfp', [{
title: 'First community fund proposal',
amount: 100,
payoutAddress: await container.call('getnewaddress')
}])
await container.generate(200) // Expires proposal

await container.call('createcfp', [{
title: 'Second community fund proposal',
amount: 100,
payoutAddress: await container.call('getnewaddress')
}])
await client.governance.createVoc('first vote of confidence')
await client.governance.createVoc('second vote of confidence')
await container.generate(1)
}

afterAll(async () => {
await container.stop()
})

it('should listProposals', async () => {
const proposals = await client.governance.listProposals()

expect(proposals.length).toStrictEqual(4)
for (const proposal of proposals) {
expect(typeof proposal.proposalId).toStrictEqual('string')
expect(typeof proposal.title).toStrictEqual('string')
expect(typeof proposal.type).toStrictEqual('string')
expect(typeof proposal.status).toStrictEqual('string')
expect(typeof proposal.amount).toStrictEqual('number')
expect(typeof proposal.totalCycles).toStrictEqual('number')
expect(typeof proposal.cyclesPaid).toStrictEqual('number')
expect(typeof proposal.finalizeAfter).toStrictEqual('number')
expect(typeof proposal.payoutAddress).toStrictEqual('string')
}
})

it('should listProposals with type ListProposalsType.VOC', async () => {
const proposals = await client.governance.listProposals({
type: ListProposalsType.VOC
})
expect(proposals.length).toStrictEqual(2)
expect(proposals.every(({ type }) => type === ProposalType.VOTE_OF_CONFIDENCE)).toStrictEqual(true)
})

it('should listProposals with status ListProposalsStatus.VOTING', async () => {
const proposals = await client.governance.listProposals({
status: ListProposalsStatus.VOTING
})
expect(proposals.length).toStrictEqual(3)
expect(proposals.every(({ status }) => status === ProposalStatus.VOTING)).toStrictEqual(true)
})

it('should listProposals with type ListProposalsType.CFP and status ListProposalsStatus.REJECTED', async () => {
const proposals = await client.governance.listProposals({
type: ListProposalsType.CFP,
status: ListProposalsStatus.REJECTED
})

expect(proposals.length).toStrictEqual(1)
expect(proposals[0].type).toStrictEqual(ProposalType.COMMUNITY_FUND_REQUEST)
expect(proposals[0].status).toStrictEqual(ProposalStatus.REJECTED)
})
})

describe('Governance without proposals', () => {
const container = new GovernanceMasterNodeRegTestContainer()
const client = new ContainerAdapterClient(container)

beforeAll(async () => {
await container.start()
await container.waitForReady()
await container.waitForWalletCoinbaseMaturity()
})

afterAll(async () => {
await container.stop()
})

it('should listProposals with empty array if no proposal available', async () => {
const proposals = await client.governance.listProposals()
expect(proposals.length).toStrictEqual(0)
})
})
29 changes: 29 additions & 0 deletions packages/jellyfish-api-core/src/category/governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ export enum ProposalStatus {
COMPLETED = 'Completed'
}

export enum ListProposalsType {
CFP = 'cfp',
BRP = 'brp',
VOC = 'voc',
ALL = 'all'
}

export enum ListProposalsStatus {
VOTING = 'voting',
REJECTED = 'rejected',
COMPLETED = 'completed',
ALL = 'all'
}

/**
* Governance RPCs for DeFi Blockchain
*/
Expand Down Expand Up @@ -65,6 +79,21 @@ export class Governance {
async createVoc (title: string, utxos: UTXO[] = []): Promise<string> {
return await this.client.call('createvoc', [title, utxos], 'number')
}

/**
* Returns list of proposals.
*
* @param {Object} options List proposal filter options
* @param {ListProposalsType} [options.type=ListProposalsType.ALL] type of proposals
* @param {ListProposalsStatus} [options.status=ListProposalsStatus.ALL] status of proposals
* @return {Promise<ProposalInfo[]>}
*/
async listProposals ({
type = ListProposalsType.ALL,
status = ListProposalsStatus.ALL
} = {}): Promise<ProposalInfo[]> {
return await this.client.call('listproposals', [type, status], 'number')
}
}

export interface CFPData {
Expand Down
51 changes: 51 additions & 0 deletions website/docs/jellyfish/api/governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,54 @@ interface UTXO {
vout: number
}
```

## listProposals

Returns list of proposals.

```ts title="client.governance.listProposals()"
interface governance {
async listProposals ({
type = ListProposalsType.ALL,
status = ListProposalsStatus.ALL
} = {}): Promise<ProposalInfo[]>
}

enum ListProposalsType {
CFP = 'cfp',
BRP = 'brp',
VOC = 'voc',
ALL = 'all'
}

enum ListProposalsStatus {
VOTING = 'voting',
REJECTED = 'rejected',
COMPLETED = 'completed',
ALL = 'all'
}

enum ProposalType {
COMMUNITY_FUND_REQUEST = 'CommunityFundRequest',
BLOCK_REWARD_RELLOCATION = 'BlockRewardRellocation',
VOTE_OF_CONFIDENCE = 'VoteOfConfidence'
}

enum ProposalStatus {
VOTING = 'Voting',
REJECTED = 'Rejected',
COMPLETED = 'Completed'
}

interface ProposalInfo {
proposalId: string
title: string
type: ProposalType
status: ProposalStatus
amount: number
cyclesPaid: number
totalCycles: number
finalizeAfter: number
payoutAddress: string
}
```

0 comments on commit fa2df26

Please sign in to comment.