Skip to content

support ctl4rep #574

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

Merged
merged 1 commit into from
Jan 6, 2021
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
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ services:
GRAPH_GRAPHQL_MAX_FIRST: '1000'

ipfs:
image: daostack/test-env-ipfs:3.0.42
image: daostack/test-env-ipfs:3.0.43
ports:
- 5001:5001

postgres:
image: daostack/test-env-postgres:3.0.42
image: daostack/test-env-postgres:3.0.43
ports:
- 9432:5432
environment:
POSTGRES_PASSWORD: 'letmein'

ganache:
image: daostack/test-env-ganache:3.0.42
image: daostack/test-env-ganache:3.0.43
ports:
- 8545:8545
343 changes: 170 additions & 173 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@daostack/arc.js",
"version": "0.2.82",
"version": "0.2.83",
"description": "",
"keywords": [],
"main": "dist/lib/index.js",
Expand Down Expand Up @@ -67,7 +67,7 @@
]
},
"devDependencies": {
"@daostack/migration": "0.0.1-rc.53-v0",
"@daostack/migration": "0.0.1-rc.55-v1",
"@daostack/subgraph-test-env": "0.0.39-8",
"@types/graphql": "^14.2.2",
"@types/isomorphic-fetch": "^0.0.34",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { Reputation, IReputationState, IReputationQueryOptions } from './reputat
export { Reward, IRewardState, IRewardStaticState, IRewardQueryOptions } from './reward'
export { Scheme, ISchemeState, ISchemeStaticState, ISchemeQueryOptions } from './scheme'
export { ReputationFromTokenScheme } from './schemes/reputationFromToken'
export { CTL4RScheme } from './schemes/ctl4rep'
export { IContributionReward} from './schemes/contributionReward'
export { hasCompetitionContract, isCompetitionScheme,
IProposalCreateOptionsCompetition,
Expand Down
5 changes: 5 additions & 0 deletions src/scheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { CompetitionScheme, isCompetitionScheme } from './schemes/competition'
import * as Competition from './schemes/competition'
import * as ContributionReward from './schemes/contributionReward'
import * as ContributionRewardExt from './schemes/contributionRewardExt'
import { CTL4RScheme } from './schemes/ctl4rep'
import * as GenericScheme from './schemes/genericScheme'
import * as GenericSchemeMultiCall from './schemes/genericSchemeMultiCall'
import { ReputationFromTokenScheme } from './schemes/reputationFromToken'
Expand Down Expand Up @@ -184,6 +185,7 @@ export class Scheme extends SchemeBase {
public id: Address
public staticState: ISchemeStaticState | null = null
public ReputationFromToken: ReputationFromTokenScheme | null = null
public CTL4R: CTL4RScheme | null = null

constructor(idOrOpts: Address | ISchemeStaticState, public context: Arc) {
super(idOrOpts, context)
Expand All @@ -202,6 +204,9 @@ export class Scheme extends SchemeBase {
if (this.staticState.name === 'ReputationFromToken') {
this.ReputationFromToken = new ReputationFromTokenScheme(this)
}
if (this.staticState.name === 'ContinuousLocking4Reputation') {
this.CTL4R = new CTL4RScheme(this)
}
}

/**
Expand Down
5 changes: 5 additions & 0 deletions src/schemes/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IProposalCreateOptions,
IProposalQueryOptions, Proposal } from '../proposal'
import { Address, ICommonQueryOptions, IStateful } from '../types'
import { CTL4RScheme } from './ctl4rep'
import { ReputationFromTokenScheme } from './reputationFromToken'

export interface ISchemeStaticState {
Expand Down Expand Up @@ -248,6 +249,7 @@ export abstract class SchemeBase implements IStateful<ISchemeState> {
public id: Address
public staticState: ISchemeStaticState | null = null
public ReputationFromToken: ReputationFromTokenScheme | null = null
public CTL4R: CTL4RScheme | null = null

constructor(idOrOpts: Address | ISchemeStaticState, public context: Arc) {
this.context = context
Expand Down Expand Up @@ -283,6 +285,9 @@ export abstract class SchemeBase implements IStateful<ISchemeState> {
if (this.staticState.name === 'ReputationFromToken') {
this.ReputationFromToken = new ReputationFromTokenScheme(this)
}
if (this.staticState.name === 'ContinuousLocking4Reputation') {
this.CTL4R = new CTL4RScheme(this)
}
return state
}
}
Expand Down
124 changes: 124 additions & 0 deletions src/schemes/ctl4rep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import BN = require('bn.js')
import { from } from 'rxjs'
import { concatMap } from 'rxjs/operators'

import {
Operation,
toIOperationObservable
} from '../operation'

import { Address } from '../types'

import { Scheme } from '../scheme'

export class CTL4RScheme {

constructor(public scheme: Scheme) {

}

public async getAgreementHash(): Promise<string> {
const contract = await this.getContract()
const result = await contract.methods.getAgreementHash().call()
return result
}

public lock(amount: BN, period: number, batchIndexToLockIn: number, agreementHash: string): Operation<any> {
const mapReceipt = (receipt: any) => {
return receipt
}

const observable = from(this.getContract())
.pipe(
concatMap((contract) => {
let transaction: any
transaction = contract.methods.lock(
amount,
period,
batchIndexToLockIn,
agreementHash
)
const errorHandler = async (error: Error) => {
try {
await transaction.call()
} catch (err) {
throw err
}
return error
}
return this.scheme.context.sendTransaction(transaction, mapReceipt, errorHandler)
})
)
return toIOperationObservable(observable)
}

public extendLocking(extendPeriod: number,
batchIndexToLockIn: number,
lockingId: number,
agreementHash: string): Operation<any> {
const mapReceipt = (receipt: any) => {
return receipt
}

const observable = from(this.getContract())
.pipe(
concatMap((contract) => {
let transaction: any
transaction = contract.methods.extendLocking(
extendPeriod,
batchIndexToLockIn,
lockingId,
agreementHash
)
const errorHandler = async (error: Error) => {
try {
await transaction.call()
} catch (err) {
throw err
}
return error
}
return this.scheme.context.sendTransaction(transaction, mapReceipt, errorHandler)
})
)
return toIOperationObservable(observable)
}
public release(beneficiary: Address, lockingId: number): Operation<any> {
const mapReceipt = (receipt: any) => {
return receipt
}

const observable = from(this.getContract())
.pipe(
concatMap((contract) => {
let transaction: any
transaction = contract.methods.release(
beneficiary,
lockingId
)
const errorHandler = async (error: Error) => {
try {
await transaction.call()
} catch (err) {
throw err
}
return error
}
return this.scheme.context.sendTransaction(transaction, mapReceipt, errorHandler)
})
)
return toIOperationObservable(observable)
}

public async getContract() {
const state = await this.scheme.fetchStaticState()
await this.scheme.context.fetchContractInfos({fetchPolicy: 'network-only'})
const contract = this.scheme.context.getContract(state.address)
return contract
}

public getScheme() {
return this.scheme
}

}
118 changes: 118 additions & 0 deletions test/scheme-ctl4rep.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { first } from 'rxjs/operators'
import { Arc, CTL4RScheme } from '../src'
import { newArc } from './utils'
import BN = require('bn.js')
import { createAProposal, getTestAddresses, getTestDAO, voteToPassProposal, waitUntilTrue} from './utils'
import {
IProposalState,
IProposalType,
IProposalStage
} from '../src/proposal'
jest.setTimeout(60000)
/**
* Scheme test
*/
describe('Scheme', () => {

let arc: Arc
let accounts: any

const agreementHash = '0x0000000000000000000000000000000000000001000000000000000000000000'
let continuousLocking4ReputationAddress : any
let dao : any
let proposalToAdd :any
let token :any
beforeAll(async () => {
arc = await newArc()
token = arc.GENToken()

accounts = arc.web3.eth.accounts.wallet
const contractInfoFactory = arc.getContractInfoByName('ContinuousLocking4ReputationFactory', '0.0.1-rc.55')
const continuousLocking4ReputationFactory = arc.getContract(contractInfoFactory.address)

// Avatar _avatar,
// uint256 _reputationReward,
// uint256 _startTime,
// uint256 _batchTime,
// uint256 _redeemEnableTime,
// uint256 _maxLockingBatches,
// uint256 _repRewardConstA,
// uint256 _repRewardConstB,
// uint256 _batchesIndexCap,
// IERC20 _token,
// bytes32 _agreementHash
dao = await getTestDAO()
const startTime = (await arc.web3.eth.getBlock('latest')).timestamp
const redeemEnableTime = startTime + 1000

continuousLocking4ReputationAddress = await continuousLocking4ReputationFactory.methods.createCL4R(
dao.id,
new BN('10000000'),
startTime,
new BN('1000'),
redeemEnableTime,
new BN('12'),
new BN('85000'),
new BN('900'),
new BN('5'),
token.address,
agreementHash
).call()

await continuousLocking4ReputationFactory.methods.createCL4R(
dao.id,
new BN('10000000'),
startTime,
new BN('1000'),
redeemEnableTime,
new BN('12'),
new BN('85000'),
new BN('900'),
new BN('5'),
token.address,
agreementHash
).send({gas: 2000000, from:accounts[0].address})
//now register that to a dao

proposalToAdd = await createAProposal(dao, {
descriptionHash: '',
parametersHash: '0x0000000000000000000000000000000000000000000000000000000000001234',
permissions: '0x0000001f',
scheme: getTestAddresses(arc).base.SchemeRegistrar,
schemeToRegister: continuousLocking4ReputationAddress,
type: IProposalType.SchemeRegistrarAdd
})
// accept the proposal by voting the hell out of it
await voteToPassProposal(proposalToAdd)
await proposalToAdd.execute()

})

it('lock and extend lock', async () => {
// check if proposal is indeed accepted etc
const states: IProposalState[] = []
const lastState = () => states[states.length - 1]
proposalToAdd.state().subscribe(((next: any) => states.push(next)))

await waitUntilTrue(() => {
return lastState() && lastState().stage === IProposalStage.Executed
})
const schemes = await dao.schemes({ where: { address: continuousLocking4ReputationAddress.toLowerCase() } }).pipe(first()).toPromise()
const scheme = schemes[0]
expect(scheme.CTL4R).not.toBeFalsy()
const ctl4r = scheme.CTL4R as CTL4RScheme
await ctl4r.getScheme().context.fetchContractInfos({fetchPolicy: 'network-only'})
expect(await ctl4r.getAgreementHash()).toEqual(agreementHash)
const lockAmount = new BN('300')
await token.approveForStaking(continuousLocking4ReputationAddress.toLowerCase(), lockAmount).send()
await token.mint(accounts[0].address, lockAmount).send()
await arc.fetchContractInfos({fetchPolicy: 'network-only'})
const continuousLocking4ReputationContract = arc.getContract(continuousLocking4ReputationAddress.toLowerCase())
const lockCounterBefore = await continuousLocking4ReputationContract.methods.lockCounter().call()
await ctl4r.lock(lockAmount,1,0,agreementHash).send()
const lockCounterAfter = await continuousLocking4ReputationContract.methods.lockCounter().call()
expect(Number(lockCounterBefore)+1).toEqual(Number(lockCounterAfter))
await ctl4r.extendLocking(2,0,lockCounterAfter,agreementHash).send()

})
})