Introduce actor mixin pattern
This commit is contained in:
parent
93b02e93b9
commit
4210477e71
54
contracts/integrations/test/actors/base.ts
Normal file
54
contracts/integrations/test/actors/base.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
||||||
|
import { constants } from '@0x/contracts-test-utils';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
import { DeploymentManager } from '../deployment/deployment_mananger';
|
||||||
|
|
||||||
|
export type Constructor<T = {}> = new (...args: any[]) => T;
|
||||||
|
|
||||||
|
export interface ActorConfig {
|
||||||
|
address: string;
|
||||||
|
name?: string;
|
||||||
|
deployment: DeploymentManager;
|
||||||
|
[subclassProperty: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Actor {
|
||||||
|
public readonly address: string;
|
||||||
|
public readonly name: string;
|
||||||
|
public readonly deployment: DeploymentManager;
|
||||||
|
|
||||||
|
constructor(config: ActorConfig) {
|
||||||
|
this.address = config.address;
|
||||||
|
this.name = config.name || config.address;
|
||||||
|
this.deployment = config.deployment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a balance for an ERC20 token and approves a spender (defaults to the ERC20 asset proxy)
|
||||||
|
* to transfer the token.
|
||||||
|
*/
|
||||||
|
public async configureERC20TokenAsync(
|
||||||
|
token: DummyERC20TokenContract | WETH9Contract,
|
||||||
|
spender?: string,
|
||||||
|
amount?: BigNumber,
|
||||||
|
): Promise<void> {
|
||||||
|
if (token instanceof DummyERC20TokenContract) {
|
||||||
|
await token.setBalance.awaitTransactionSuccessAsync(
|
||||||
|
this.address,
|
||||||
|
amount || constants.INITIAL_ERC20_BALANCE,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await token.deposit.awaitTransactionSuccessAsync({
|
||||||
|
from: this.address,
|
||||||
|
value: amount || constants.ONE_ETHER,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await token.approve.awaitTransactionSuccessAsync(
|
||||||
|
spender || this.deployment.assetProxies.erc20Proxy.address,
|
||||||
|
constants.MAX_UINT256,
|
||||||
|
{ from: this.address },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
5
contracts/integrations/test/actors/hybrids.ts
Normal file
5
contracts/integrations/test/actors/hybrids.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Actor } from './base';
|
||||||
|
import { Maker } from './maker';
|
||||||
|
import { PoolOperator } from './pool_operator';
|
||||||
|
|
||||||
|
export const OperatorAndMaker = PoolOperator(Maker(Actor));
|
3
contracts/integrations/test/actors/index.ts
Normal file
3
contracts/integrations/test/actors/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export { MakerActor } from './maker';
|
||||||
|
export { PoolOperatorActor } from './pool_operator';
|
||||||
|
export * from './hybrids';
|
52
contracts/integrations/test/actors/maker.ts
Normal file
52
contracts/integrations/test/actors/maker.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { constants, OrderFactory } from '@0x/contracts-test-utils';
|
||||||
|
import { Order, SignedOrder } from '@0x/types';
|
||||||
|
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||||
|
|
||||||
|
import { Actor, ActorConfig, Constructor } from './base';
|
||||||
|
|
||||||
|
export interface MakerConfig extends ActorConfig {
|
||||||
|
orderConfig: Partial<Order>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Maker<TBase extends Constructor>(Base: TBase) {
|
||||||
|
return class extends Base {
|
||||||
|
public readonly actor: Actor;
|
||||||
|
public readonly orderFactory: OrderFactory;
|
||||||
|
|
||||||
|
constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
this.actor = (this as any) as Actor;
|
||||||
|
|
||||||
|
const { orderConfig } = args[0] as MakerConfig;
|
||||||
|
const defaultOrderParams = {
|
||||||
|
...constants.STATIC_ORDER_PARAMS,
|
||||||
|
makerAddress: this.actor.address,
|
||||||
|
exchangeAddress: this.actor.deployment.exchange.address,
|
||||||
|
chainId: this.actor.deployment.chainId,
|
||||||
|
...orderConfig,
|
||||||
|
};
|
||||||
|
const privateKey =
|
||||||
|
constants.TESTRPC_PRIVATE_KEYS[this.actor.deployment.accounts.indexOf(this.actor.address)];
|
||||||
|
this.orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs an order (optionally, with custom parameters) as the maker.
|
||||||
|
*/
|
||||||
|
public async signOrderAsync(customOrderParams: Partial<Order> = {}): Promise<SignedOrder> {
|
||||||
|
return this.orderFactory.newSignedOrderAsync(customOrderParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins the staking pool specified by the given ID.
|
||||||
|
*/
|
||||||
|
public async joinStakingPoolAsync(poolId: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
|
const stakingContract = this.actor.deployment.staking.stakingWrapper;
|
||||||
|
return stakingContract.joinStakingPoolAsMaker.awaitTransactionSuccessAsync(poolId, {
|
||||||
|
from: this.actor.address,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MakerActor = Maker(Actor);
|
60
contracts/integrations/test/actors/pool_operator.ts
Normal file
60
contracts/integrations/test/actors/pool_operator.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||||
|
|
||||||
|
import { Actor, ActorConfig, Constructor } from './base';
|
||||||
|
|
||||||
|
export interface PoolOperatorConfig extends ActorConfig {
|
||||||
|
operatorShare: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PoolOperator<TBase extends Constructor>(Base: TBase) {
|
||||||
|
return class extends Base {
|
||||||
|
public readonly operatorShare: number;
|
||||||
|
public readonly poolIds: string[] = [];
|
||||||
|
public readonly actor: Actor;
|
||||||
|
|
||||||
|
constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
this.actor = (this as any) as Actor;
|
||||||
|
|
||||||
|
const { operatorShare } = args[0] as PoolOperatorConfig;
|
||||||
|
this.operatorShare = operatorShare;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a staking pool and returns the ID of the new pool.
|
||||||
|
*/
|
||||||
|
public async createStakingPoolAsync(
|
||||||
|
operatorShare: number,
|
||||||
|
addOperatorAsMaker: boolean = false,
|
||||||
|
): Promise<string> {
|
||||||
|
const stakingContract = this.actor.deployment.staking.stakingWrapper;
|
||||||
|
const txReceipt = await stakingContract.createStakingPool.awaitTransactionSuccessAsync(
|
||||||
|
operatorShare,
|
||||||
|
addOperatorAsMaker,
|
||||||
|
{ from: this.actor.address },
|
||||||
|
);
|
||||||
|
|
||||||
|
const createStakingPoolLog = txReceipt.logs[0];
|
||||||
|
const poolId = (createStakingPoolLog as any).args.poolId;
|
||||||
|
this.poolIds.push(poolId);
|
||||||
|
return poolId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins the staking pool specified by the given ID.
|
||||||
|
*/
|
||||||
|
public async decreaseOperatorShareAsync(
|
||||||
|
poolId: string,
|
||||||
|
newOperatorShare: number,
|
||||||
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
|
const stakingContract = this.actor.deployment.staking.stakingWrapper;
|
||||||
|
return stakingContract.decreaseStakingPoolOperatorShare.awaitTransactionSuccessAsync(
|
||||||
|
poolId,
|
||||||
|
newOperatorShare,
|
||||||
|
{ from: this.actor.address },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PoolOperatorActor = PoolOperator(Actor);
|
@ -124,12 +124,6 @@ export interface DeploymentOptions {
|
|||||||
export class DeploymentManager {
|
export class DeploymentManager {
|
||||||
public static protocolFeeMultiplier = new BigNumber(150000);
|
public static protocolFeeMultiplier = new BigNumber(150000);
|
||||||
|
|
||||||
public assetProxies: AssetProxyContracts;
|
|
||||||
public governor: ZeroExGovernorContract;
|
|
||||||
public exchange: ExchangeContract;
|
|
||||||
public staking: StakingContracts;
|
|
||||||
public tokens: TokenContracts;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fully deploy the 0x exchange and staking contracts and configure the system with the
|
* Fully deploy the 0x exchange and staking contracts and configure the system with the
|
||||||
* asset proxy owner multisig.
|
* asset proxy owner multisig.
|
||||||
@ -141,6 +135,8 @@ export class DeploymentManager {
|
|||||||
options: Partial<DeploymentOptions> = {},
|
options: Partial<DeploymentOptions> = {},
|
||||||
): Promise<DeploymentManager> {
|
): Promise<DeploymentManager> {
|
||||||
const chainId = await environment.getChainIdAsync();
|
const chainId = await environment.getChainIdAsync();
|
||||||
|
const accounts = await environment.getAccountAddressesAsync();
|
||||||
|
|
||||||
const owner = options.owner || (await environment.getAccountAddressesAsync())[0];
|
const owner = options.owner || (await environment.getAccountAddressesAsync())[0];
|
||||||
const txDefaults = {
|
const txDefaults = {
|
||||||
...environment.txDefaults,
|
...environment.txDefaults,
|
||||||
@ -204,7 +200,7 @@ export class DeploymentManager {
|
|||||||
staking.stakingProxy,
|
staking.stakingProxy,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return new DeploymentManager(assetProxies, governor, exchange, staking, tokens);
|
return new DeploymentManager(assetProxies, governor, exchange, staking, tokens, chainId, accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -411,21 +407,18 @@ export class DeploymentManager {
|
|||||||
txDefaults: Partial<TxData>,
|
txDefaults: Partial<TxData>,
|
||||||
options: Partial<DeploymentOptions>,
|
options: Partial<DeploymentOptions>,
|
||||||
): Promise<TokenContracts> {
|
): Promise<TokenContracts> {
|
||||||
const numErc20TokensToDeploy = _.get(
|
const numErc20TokensToDeploy =
|
||||||
options,
|
options.numErc20TokensToDeploy !== undefined
|
||||||
['numErc20TokensToDeploy'],
|
? options.numErc20TokensToDeploy
|
||||||
constants.NUM_DUMMY_ERC20_CONTRACTS_TO_DEPLOY,
|
: constants.NUM_DUMMY_ERC20_TO_DEPLOY;
|
||||||
);
|
const numErc721TokensToDeploy =
|
||||||
const numErc721TokensToDeploy = _.get(
|
options.numErc721TokensToDeploy !== undefined
|
||||||
options,
|
? options.numErc721TokensToDeploy
|
||||||
['numErc721TokensToDeploy'],
|
: constants.NUM_DUMMY_ERC721_TO_DEPLOY;
|
||||||
constants.NUM_DUMMY_ERC721_CONTRACTS_TO_DEPLOY,
|
const numErc1155TokensToDeploy =
|
||||||
);
|
options.numErc1155TokensToDeploy !== undefined
|
||||||
const numErc1155TokensToDeploy = _.get(
|
? options.numErc1155TokensToDeploy
|
||||||
options,
|
: constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY;
|
||||||
['numErc1155TokensToDeploy'],
|
|
||||||
constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY,
|
|
||||||
);
|
|
||||||
|
|
||||||
const erc20 = await Promise.all(
|
const erc20 = await Promise.all(
|
||||||
_.times(
|
_.times(
|
||||||
@ -493,16 +486,12 @@ export class DeploymentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
assetProxies: AssetProxyContracts,
|
public assetProxies: AssetProxyContracts,
|
||||||
governor: ZeroExGovernorContract,
|
public governor: ZeroExGovernorContract,
|
||||||
exchange: ExchangeContract,
|
public exchange: ExchangeContract,
|
||||||
staking: StakingContracts,
|
public staking: StakingContracts,
|
||||||
tokens: TokenContracts,
|
public tokens: TokenContracts,
|
||||||
) {
|
public chainId: number,
|
||||||
this.assetProxies = assetProxies;
|
public accounts: string[],
|
||||||
this.governor = governor;
|
) {}
|
||||||
this.exchange = exchange;
|
|
||||||
this.staking = staking;
|
|
||||||
this.tokens = tokens;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user