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

Token trade plugin added #521

Merged
merged 32 commits into from
Aug 31, 2020
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3c4c842
[WIP] Token trade plugin added but not tested yet
namesty Jul 28, 2020
98605c8
Eliminate indexed 'proposal' field on TokenTrade proposal type
namesty Jul 28, 2020
22ac365
[WIP] TokenTrade Proposal tests
namesty Jul 29, 2020
f8aee15
Names and types tweaks
namesty Jul 31, 2020
00b7a59
Updated packages with new migration version
namesty Aug 5, 2020
4519907
updated test env version
namesty Aug 5, 2020
d736292
Token trade tests (haven't run yet) and type changes
namesty Aug 6, 2020
7a47625
Comparison fix on trade test
namesty Aug 6, 2020
7a893c9
[WIP] Test missing redeem step
namesty Aug 9, 2020
f1737f8
tests works
cbrzn Aug 10, 2020
6c34993
fix lint error
cbrzn Aug 10, 2020
9f70fa2
removing logs
cbrzn Aug 10, 2020
87d384b
improving tests
cbrzn Aug 10, 2020
bd9a15d
[WIP] Approve tokens method
namesty Aug 10, 2020
323006a
Merge remote-tracking branch 'dOrgTech/token-trade' into token-trade
namesty Aug 10, 2020
9e3ebfe
trying to make approve work
cbrzn Aug 10, 2020
9ae640a
Token approval fix
namesty Aug 11, 2020
3c22550
Merge branch 'client-2-0' into token-trade
namesty Aug 16, 2020
0f8a902
Build fixes
namesty Aug 16, 2020
fdc1801
creating token trade on test
cbrzn Aug 17, 2020
51585c0
tests fixed
cbrzn Aug 17, 2020
99a4c16
lint fixed
cbrzn Aug 17, 2020
2a04fab
waiting for plugin to be index
cbrzn Aug 17, 2020
c9e03b7
trying to fix test
cbrzn Aug 17, 2020
6c68572
Plugin Address fix
namesty Aug 17, 2020
4b63073
test env updated
cbrzn Aug 21, 2020
8e046cf
Merge branch 'token-trade' of github.com:dOrgTech/client into token-t…
cbrzn Aug 21, 2020
5c5c700
removing old changes
cbrzn Aug 21, 2020
b83ae19
hardcoding erc20 token abi based on Oren's feedback
cbrzn Aug 30, 2020
2f59022
tests for approve tokens created
cbrzn Aug 30, 2020
fdfce3d
improving approval test
cbrzn Aug 30, 2020
154f1a1
bump version
cbrzn Aug 31, 2020
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-experimental-ipfs:4.0.18
image: daostack/test-env-experimental-ipfs:4.0.19
ports:
- 5001:5001

postgres:
image: daostack/test-env-experimental-postgres:4.0.18
image: daostack/test-env-experimental-postgres:4.0.19
ports:
- 9432:5432
environment:
POSTGRES_PASSWORD: 'letmein'

ganache:
image: daostack/test-env-experimental-ganache:4.0.18
image: daostack/test-env-experimental-ganache:4.0.19
ports:
- 8545:8545
43 changes: 26 additions & 17 deletions 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
Expand Up @@ -73,7 +73,7 @@
},
"devDependencies": {
"@daostack/migration-experimental": "0.1.2-rc.6-v2",
"@daostack/test-env-experimental": "4.0.18",
"@daostack/test-env-experimental": "4.0.19",
"@types/graphql": "^14.2.2",
"@types/isomorphic-fetch": "^0.0.34",
"@types/jest": "^24.0.15",
Expand Down
26 changes: 26 additions & 0 deletions src/arc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import BN from 'bn.js'
import { Contract, Signer } from 'ethers'
import { providers } from 'ethers'
import 'ethers/dist/shims'
import { JsonRpcProvider } from 'ethers/providers'
import { BigNumber } from 'ethers/utils'
import gql from 'graphql-tag'
import { Observable, Observer, of } from 'rxjs'
Expand Down Expand Up @@ -627,6 +628,31 @@ export class Arc extends GraphNodeObserver {
Logger.debug(`Data saved successfully as ${descriptionHash}`)
return descriptionHash
}

public approveTokens(tokenAddress: Address, spender: Address, amount: BN) {
cbrzn marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any test which cover that ?

const signer = (this.web3 as JsonRpcProvider).getSigner(this.defaultAccount as any)
const abi = [
{
constant: false,
inputs: [
{ name: '_spender', type: 'address' },
{ name: '_value', type: 'uint256' }
],
name: 'approve',
outputs: [{ name: '', type: 'bool' }],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
}
]
const tokenContract = new Contract(tokenAddress, abi, signer)

return this.sendTransaction({
contract: tokenContract,
method: 'approve',
args: [spender, amount.toString()]
})
}
}

export interface IContractInfo {
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './plugins/proposal'
export * from './plugins/proposalPlugin'
export * from './plugins/contributionReward'
export * from './plugins/contributionRewardExt'
export * from './plugins/tokenTrade'
export * from './plugins/join'
export * from './plugins/competition'
export * from './plugins/fundingRequest'
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/pluginManager/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export type IProposalCreateOptionsPM =
IProposalCreateOptions<'Join'> |
IProposalCreateOptions<'SchemeRegistrar'> |
IProposalCreateOptions<'SchemeFactory'> |
IProposalCreateOptions<'ReputationFromToken'>
IProposalCreateOptions<'ReputationFromToken'> |
IProposalCreateOptions<'TokenTrade'>

export interface IProposalCreateOptions<TName extends keyof IInitParams>
extends IProposalBaseCreateOptions {
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/tokenTrade/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './plugin'
export * from './proposal'
175 changes: 175 additions & 0 deletions src/plugins/tokenTrade/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import BN from 'bn.js'
import { DocumentNode } from 'graphql'
import gql from 'graphql-tag'
import {
Address,
Arc,
getEventArgs,
IGenesisProtocolParams,
IPluginState,
IProposalBaseCreateOptions,
ITransaction,
ITransactionReceipt,
mapGenesisProtocolParams,
Plugin,
ProposalPlugin,
transactionErrorHandler,
transactionResultHandler
} from '../../index'
import { ITokenTradeProposalState, TokenTradeProposal } from './proposal'

export interface ITokenTradeState extends IPluginState {
pluginParams: {
votingMachine: Address
voteParams: IGenesisProtocolParams
}
}

export interface IProposalCreateOptionsTokenTrade extends IProposalBaseCreateOptions {
sendTokenAddress: Address,
sendTokenAmount: number,
receiveTokenAddress: Address,
receiveTokenAmount: number,
descriptionHash: string
}

export interface IInitParamsTT {
daoId: string
votingMachine: string
votingParams: number[]
voteOnBehalf: string
voteParamsHash: string
}

export class TokenTrade extends ProposalPlugin<
ITokenTradeState,
ITokenTradeProposalState,
IProposalCreateOptionsTokenTrade> {

public static get fragment() {
if (!this.fragmentField) {
this.fragmentField = {
name: 'TokenTradeParams',
fragment: gql` fragment TokenTradeParams on ControllerScheme {
tokenTradeParams {
id
votingMachine
voteParams {
id
queuedVoteRequiredPercentage
queuedVotePeriodLimit
boostedVotePeriodLimit
preBoostedVotePeriodLimit
thresholdConst
limitExponentValue
quietEndingPeriod
proposingRepReward
votersReputationLossRatio
minimumDaoBounty
daoBountyConst
activationTime
voteOnBehalf
}
}
}`
}
}

return this.fragmentField
}

public static initializeParamsMap(initParams: IInitParamsTT) {

Object.keys(initParams).forEach((key) => {
if (initParams[key] === undefined) {
throw new Error(`TokenTrade's initialize parameter '${key}' cannot be undefined`)
}
})

return [
initParams.daoId,
initParams.votingMachine,
initParams.votingParams,
initParams.voteOnBehalf,
initParams.voteParamsHash
]
}

public static itemMap(context: Arc, item: any, queriedId?: string): ITokenTradeState | null {
if (!item) {
return null
}

if (!item.tokenTradeParams) {
throw new Error(`Plugin ${queriedId ? `with id '${queriedId}'` : ''}wrongly instantiated as TokenTrade Plugin`)
}

const baseState = Plugin.itemMapToBaseState(context, item)

const tokenTradeParams = {
voteParams: mapGenesisProtocolParams(item.tokenTradeParams.voteParams),
votingMachine: item.tokenTradeParams.votingMachine
}

return {
...baseState,
pluginParams: tokenTradeParams
}
}

private static fragmentField: { name: string, fragment: DocumentNode } | undefined

public async createProposalTransaction(options: IProposalCreateOptionsTokenTrade): Promise<ITransaction> {

if (options.plugin === undefined) {
throw new Error(`Missing argument "plugin" for TokenTrade in Proposal.create()`)
}
if (!options.receiveTokenAddress) {
throw new Error(`Missing argument "receiveTokenAddress" for TokenTrade in Proposal.create()`)
}
if (!options.sendTokenAddress) {
throw new Error(`Missing argument "sendTokenAddress" for TokenTrade in Proposal.create()`)
}
if (options.receiveTokenAmount <= 0) {
throw new Error(`Argument "receiveTokenAmount" must be greater than 0 for TokenTrade in Proposal.create()`)
}
if (options.sendTokenAmount <= 0) {
throw new Error(`Argument "sendTokenAmount" must be greater than 0 for TokenTrade in Proposal.create()`)
}

if (!options.descriptionHash) {
options.descriptionHash = await this.context.saveIPFSData(options)
}

const { address: pluginAddress } = await this.fetchState()

await this.context.approveTokens(options.sendTokenAddress, pluginAddress, new BN(options.sendTokenAmount)).send()

return {
contract: this.context.getContract(pluginAddress),
method: 'proposeTokenTrade',
args: [
options.sendTokenAddress,
options.sendTokenAmount,
options.receiveTokenAddress,
options.receiveTokenAmount,
options.descriptionHash
]
}
}

public createProposalTransactionMap(): transactionResultHandler<any> {
return async (receipt: ITransactionReceipt) => {
const args = getEventArgs(receipt, 'TokenTradeProposed', 'TokenTrade.createProposal')
const proposalId = args[1]
return new TokenTradeProposal(this.context, proposalId)
}
}

public createProposalErrorHandler(options: IProposalCreateOptionsTokenTrade): transactionErrorHandler {
return async (err) => {
throw err
}
}

}
Loading