Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

competitions continued #366

Merged
merged 3 commits into from
Jan 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@daostack/client",
"version": "0.2.40",
"version": "0.2.41",
"description": "",
"keywords": [],
"main": "dist/lib/index.js",
Expand Down
32 changes: 29 additions & 3 deletions src/schemes/competition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,17 @@ export class CompetitionScheme extends SchemeBase {
return SchemeBase.prototype.createProposal.call(this, options)
}

public voteSuggestion(options: {
public async getCompetitionContract() {
const schemeState = await this.state().pipe(first()).toPromise()
const contract = getCompetitionContract(schemeState, this.context)
return contract
}

public voteSuggestion(options: {
suggestionId: number // this is the suggestion COUNTER
}): Operation<CompetitionVote> {
const createTransaction = async () => {
const schemeState = await this.state().pipe(first()).toPromise()
const contract = getCompetitionContract(schemeState, this.context)
const contract = await this.getCompetitionContract()
const transaction = contract.methods.vote(options.suggestionId)
return transaction
}
Expand Down Expand Up @@ -644,6 +649,27 @@ export class CompetitionSuggestion {
return CompetitionVote.search(this.context, options, apolloQueryOptions)
}

public async getPosition() {
const suggestionState = await this.state().pipe(first()).toPromise()
const proposal = new Proposal(suggestionState.proposal, this.context)
const proposalState = await proposal.state().pipe(first()).toPromise()
const scheme = new CompetitionScheme(proposalState.scheme.id, this.context)
const competitionContract = await scheme.getCompetitionContract()
const transaction = competitionContract.methods.getOrderedIndexOfSuggestion(suggestionState.suggestionId)
const result = await transaction.call()
const index = Number(result)
return index
}
public async isWinner() {
const position = await this.getPosition()
const suggestionState = await this.state().pipe(first()).toPromise()
const proposal = await new Proposal(suggestionState.proposal, this.context)
const proposalState = await proposal.state().pipe(first()).toPromise()
const competitionState = proposalState.competition as ICompetitionProposal
const numberOfWinners = competitionState.numberOfWinners
return position < numberOfWinners
}

public redeem(beneficiary: Address = NULL_ADDRESS): Operation<boolean> {
const observable = this.state().pipe(
first(),
Expand Down
188 changes: 182 additions & 6 deletions test/proposal-competition.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ describe('Competition Proposal', () => {
let dao: DAO
let contributionRewardExt: CompetitionScheme
let contributionRewardExtState: ISchemeState
let address0: string
let address1: string
let suggestion1: any
let suggestion2: any
let suggestion3: any
let suggestion4: any
// let snapshotId: any

function addSeconds(date: Date, seconds: number) {
Expand Down Expand Up @@ -62,6 +68,8 @@ describe('Competition Proposal', () => {
contributionRewardExt = contributionRewardExts[0] as CompetitionScheme
contributionRewardExtState = await contributionRewardExt.state().pipe(first()).toPromise()
dao = new DAO(contributionRewardExtState.dao, arc)
address0 = arc.web3.eth.accounts.wallet[0].address.toLowerCase()
address1 = arc.web3.eth.accounts.wallet[1].address.toLowerCase()
})

afterEach(async () => {
Expand Down Expand Up @@ -133,7 +141,7 @@ describe('Competition Proposal', () => {
expect(contributionRewardExt).toBeInstanceOf(CompetitionScheme)
const scheme = new CompetitionScheme(contributionRewardExt.id, arc)

const ethReward = new BN(1000)
const ethReward = new BN(1000000)
// make sure that the DAO has enough Ether to pay forthe reward
await arc.web3.eth.sendTransaction({
gas: 4000000,
Expand Down Expand Up @@ -236,19 +244,17 @@ describe('Competition Proposal', () => {
url: 'https://somewhere.some.place'
}

const address0 = arc.web3.eth.accounts.wallet[0].address.toLowerCase()
const address1 = arc.web3.eth.accounts.wallet[1].address.toLowerCase()
// submit a suggestion by address1
arc.setAccount(address1)
const receipt1 = await competition.createSuggestion(suggestion1Options).send()
arc.setAccount(address0)
const suggestion1 = receipt1.result
suggestion1 = receipt1.result
expect(suggestion1).toBeDefined()
expect(suggestion1).toBeInstanceOf(CompetitionSuggestion)
expect(suggestion1.id).toBeDefined()
const suggestion2Options = { ...suggestion1Options, title: 'suggestion nr 2'}
const receipt2 = await competition.createSuggestion(suggestion2Options).send()
const suggestion2 = receipt2.result
suggestion2 = receipt2.result

// we now should find 2 suggestions
let suggestionIds: string[] = []
Expand Down Expand Up @@ -319,13 +325,183 @@ describe('Competition Proposal', () => {
await suggestion1.redeem().send()
const balanceAfter = new BN(await arc.web3.eth.getBalance(address1))
const balanceDelta = balanceAfter.sub(balanceBefore)
expect(balanceDelta.toString()).not.toEqual('0')
expect(balanceDelta.toString()).not.toEqual(new BN(0))
// TODO: write some tests for winners and their balances
// console.log(balanceDelta.toString())
// console.log(ethReward.toString())
// expect(balanceDelta).toEqual(ethReward.muln(97).divn(100))
})

async function createCompetition() {
const scheme = new CompetitionScheme(contributionRewardExt.id, arc)
const ethReward = new BN(10000000000)
// make sure that the DAO has enough Ether to pay forthe reward
await arc.web3.eth.sendTransaction({
gas: 4000000,
gasPrice: 100000000000,
to: dao.id,
value: ethReward
})
const reputationReward = new BN(10101010)
const externalTokenReward = new BN(0)
const nativeTokenReward = new BN(0)
const now = await getBlockTime(arc.web3)
const startTime = addSeconds(now, 2)
const rewardSplit = [80, 20]
const proposalOptions = {
dao: dao.id,
endTime: addSeconds(startTime, 200),
ethReward,
externalTokenAddress: undefined,
externalTokenReward,
nativeTokenReward,
numberOfVotesPerVoter: 3,
proposalType: 'competition',
reputationReward,
rewardSplit,
startTime,
suggestionsEndTime: addSeconds(startTime, 100),
value: 0,
votingStartTime: addSeconds(startTime, 0)
}

// CREATE PROPOSAL
const tx = await scheme.createProposal(proposalOptions).send()
const proposal = tx.result

// accept the proposal by voting for et
await voteToPassProposal(proposal)
await proposal.claimRewards().send()

// find the competition
const competitions = await scheme.competitions({ where: {id: proposal.id}}).pipe(first()).toPromise()
const competition = competitions[0]

// lets create some suggestions
const suggestion1Options = {
description: 'descxription',
proposal: proposal.id,
// tags: ['tag1', 'tag2'],
title: 'title',
url: 'https://somewhere.some.place'
}
const suggestion2Options = { ...suggestion1Options, title: 'suggestion nr 2'}
const suggestion3Options = { ...suggestion1Options, title: 'suggestion nr 3'}
const suggestion4Options = { ...suggestion1Options, title: 'suggestion nr 4'}

// submit a suggestion by address1
arc.setAccount(address1)
const receipt1 = await competition.createSuggestion(suggestion1Options).send()
arc.setAccount(address0)
suggestion1 = receipt1.result
const receipt2 = await competition.createSuggestion(suggestion2Options).send()
suggestion2 = receipt2.result
const receipt3 = await competition.createSuggestion(suggestion3Options).send()
suggestion3 = receipt3.result
const receipt4 = await competition.createSuggestion(suggestion4Options).send()
suggestion4 = receipt4.result
// wait until suggestions are properly indexed
let suggestionIds: string[] = []
competition.suggestions()
.subscribe((ls: CompetitionSuggestion[]) => {
suggestionIds = ls.map((x: CompetitionSuggestion) => x.id)
})

await waitUntilTrue(() => suggestionIds.indexOf(suggestion2.id) > -1)
await waitUntilTrue(() => suggestionIds.indexOf(suggestion3.id) > -1)
await waitUntilTrue(() => suggestionIds.indexOf(suggestion4.id) > -1)

// const schemeState = await scheme.state().pipe(first()).toPromise()
// const competitionContract = getCompetitionContract(schemeState, arc)
}
it(`No votes is no winners`, async () => {
// before any votes are cast, all suggesitons are winnners
await createCompetition()
expect(await suggestion1.getPosition()).toEqual(0)
expect(await suggestion4.getPosition()).toEqual(0)
// let's try to redeem
await advanceTimeAndBlock(2000)
expect(suggestion1.redeem().send()).rejects.toThrow('not in winners list')
})
it('position is calculated correctly', async () => {
await createCompetition()
await suggestion1.vote().send()
expect(await suggestion1.getPosition()).toEqual(0)
expect(await suggestion4.getPosition()).toEqual(1)
await suggestion2.vote().send()
expect(await suggestion1.getPosition()).toEqual(0)
expect(await suggestion2.getPosition()).toEqual(0)
expect(await suggestion3.getPosition()).toEqual(2)
expect(await suggestion4.getPosition()).toEqual(2)

await advanceTimeAndBlock(2000)

const beneficiary = '0xd97BacCC5001efE003d4D8a110261AdF96166F35'.toLowerCase()

let balanceBefore = new BN(await arc.web3.eth.getBalance(beneficiary))
// const tx = await suggestion1.redeem(beneficiary).send()
// console.log(tx.receipt.events)
await suggestion1.redeem(beneficiary).send()
let balanceAfter = new BN(await arc.web3.eth.getBalance(beneficiary))
let balanceDelta = balanceAfter.sub(balanceBefore)
// TODO: why does this fail??
// expect(balanceDelta.toString()).toEqual('5000000000')

balanceBefore = new BN(await arc.web3.eth.getBalance(beneficiary))
await suggestion2.redeem(beneficiary).send()
balanceAfter = new BN(await arc.web3.eth.getBalance(beneficiary))
balanceDelta = balanceAfter.sub(balanceBefore)
expect(balanceDelta.toString()).toEqual('5000000000')
console.log(balanceDelta.toString())

expect(await suggestion1.isWinner()).toEqual(true)
expect(await suggestion2.isWinner()).toEqual(true)
expect(await suggestion3.isWinner()).toEqual(false)
expect(await suggestion4.isWinner()).toEqual(false)
})

it('position is calculated correctly', async () => {
await createCompetition()
await suggestion1.vote().send()
await suggestion2.vote().send()
arc.setAccount(address0)
await suggestion3.vote().send()
arc.setAccount(address1)
await suggestion3.vote().send()
arc.setAccount(address0)
expect(await suggestion1.getPosition()).toEqual(1)
expect(await suggestion2.getPosition()).toEqual(1)
expect(await suggestion3.getPosition()).toEqual(0)
expect(await suggestion4.getPosition()).toEqual(2)

await advanceTimeAndBlock(2000)

const beneficiary = '0xd97BacCC5001efE003d4D8a110261AdF96166F35'.toLowerCase()

let balanceBefore = new BN(await arc.web3.eth.getBalance(beneficiary))
await suggestion3.redeem(beneficiary).send()
let balanceAfter = new BN(await arc.web3.eth.getBalance(beneficiary))
let balanceDelta = balanceAfter.sub(balanceBefore)
expect(balanceDelta.toString()).toEqual((new BN(8000000000)).toString())
console.log(balanceDelta.toString())

balanceBefore = new BN(await arc.web3.eth.getBalance(beneficiary))
await suggestion1.redeem(beneficiary).send()
balanceAfter = new BN(await arc.web3.eth.getBalance(beneficiary))
balanceDelta = balanceAfter.sub(balanceBefore)
// this fails, but should not!
// expect(balanceDelta.toString()).not.toEqual('0')
console.log(balanceDelta.toString())

expect(suggestion4.redeem(beneficiary).send()).rejects.toThrow('not in winners list')

expect(await suggestion1.isWinner()).toEqual(true)
expect(await suggestion2.isWinner()).toEqual(true)
expect(await suggestion3.isWinner()).toEqual(true)
expect(await suggestion4.isWinner()).toEqual(false)

})

it('CompetionScheme is recognized', async () => {
// we'll get a `ContributionRewardExt` contract that has a Compietion contract as a rewarder
const ARC_VERSION = '0.0.1-rc.36'
Expand Down
2 changes: 1 addition & 1 deletion test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export async function getOptions(web3: any) {
}
}

export async function newArc(options: { [key: string]: string} = {}): Promise<Arc> {
export async function newArc(options: { [key: string]: any} = {}): Promise<Arc> {
const defaultOptions = {
graphqlHttpProvider,
graphqlWsProvider,
Expand Down