Merge pull request #368 from 0xProject/feature/abigen/addNetworkId
Add CLI option for networkId, add abi-gen to contracts package
This commit is contained in:
commit
12d62e1157
@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* This file is auto-generated using abi-gen. Don't edit directly.
|
* This file is auto-generated using abi-gen. Don't edit directly.
|
||||||
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates.
|
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates.
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-consecutive-blank-lines
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
import { TxData, TxDataPayable } from '@0xproject/types';
|
import { TxData, TxDataPayable } from '@0xproject/types';
|
||||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
||||||
@ -9,6 +10,24 @@ import * as Web3 from 'web3';
|
|||||||
|
|
||||||
import {BaseContract} from './base_contract';
|
import {BaseContract} from './base_contract';
|
||||||
|
|
||||||
|
{{#if events}}
|
||||||
|
export type {{contractName}}ContractEventArgs =
|
||||||
|
{{#each events}}
|
||||||
|
| {{name}}ContractEventArgs{{#if @last}};{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
export enum {{contractName}}Events {
|
||||||
|
{{#each events}}
|
||||||
|
{{name}} = '{{name}}',
|
||||||
|
{{/each}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#each events}}
|
||||||
|
{{> event}}
|
||||||
|
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
export class {{contractName}}Contract extends BaseContract {
|
export class {{contractName}}Contract extends BaseContract {
|
||||||
{{#each methods}}
|
{{#each methods}}
|
||||||
{{#this.constant}}
|
{{#this.constant}}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
export interface {{name}}ContractEventArgs {
|
||||||
|
{{#each inputs}}
|
||||||
|
{{name}}: {{#returnType type}}{{/returnType}};
|
||||||
|
{{/each}}
|
||||||
|
}
|
@ -5,19 +5,11 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { artifacts } from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import {
|
import { BlockRange, EventCallback, IndexedFilterValues, TransactionOpts, ZeroExError } from '../types';
|
||||||
BlockRange,
|
|
||||||
EtherTokenContractEventArgs,
|
|
||||||
EtherTokenEvents,
|
|
||||||
EventCallback,
|
|
||||||
IndexedFilterValues,
|
|
||||||
TransactionOpts,
|
|
||||||
ZeroExError,
|
|
||||||
} from '../types';
|
|
||||||
import { assert } from '../utils/assert';
|
import { assert } from '../utils/assert';
|
||||||
|
|
||||||
import { ContractWrapper } from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import { EtherTokenContract } from './generated/ether_token';
|
import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token';
|
||||||
import { TokenWrapper } from './token_wrapper';
|
import { TokenWrapper } from './token_wrapper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,10 +12,7 @@ import {
|
|||||||
EventCallback,
|
EventCallback,
|
||||||
ExchangeContractErrCodes,
|
ExchangeContractErrCodes,
|
||||||
ExchangeContractErrs,
|
ExchangeContractErrs,
|
||||||
ExchangeContractEventArgs,
|
|
||||||
ExchangeEvents,
|
|
||||||
IndexedFilterValues,
|
IndexedFilterValues,
|
||||||
LogErrorContractEventArgs,
|
|
||||||
MethodOpts,
|
MethodOpts,
|
||||||
Order,
|
Order,
|
||||||
OrderAddresses,
|
OrderAddresses,
|
||||||
@ -33,7 +30,12 @@ import { OrderValidationUtils } from '../utils/order_validation_utils';
|
|||||||
import { utils } from '../utils/utils';
|
import { utils } from '../utils/utils';
|
||||||
|
|
||||||
import { ContractWrapper } from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import { ExchangeContract } from './generated/exchange';
|
import {
|
||||||
|
ExchangeContract,
|
||||||
|
ExchangeContractEventArgs,
|
||||||
|
ExchangeEvents,
|
||||||
|
LogErrorContractEventArgs,
|
||||||
|
} from './generated/exchange';
|
||||||
import { TokenWrapper } from './token_wrapper';
|
import { TokenWrapper } from './token_wrapper';
|
||||||
|
|
||||||
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
||||||
|
@ -5,21 +5,12 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { artifacts } from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import {
|
import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, TransactionOpts, ZeroExError } from '../types';
|
||||||
BlockRange,
|
|
||||||
EventCallback,
|
|
||||||
IndexedFilterValues,
|
|
||||||
MethodOpts,
|
|
||||||
TokenContractEventArgs,
|
|
||||||
TokenEvents,
|
|
||||||
TransactionOpts,
|
|
||||||
ZeroExError,
|
|
||||||
} from '../types';
|
|
||||||
import { assert } from '../utils/assert';
|
import { assert } from '../utils/assert';
|
||||||
import { constants } from '../utils/constants';
|
import { constants } from '../utils/constants';
|
||||||
|
|
||||||
import { ContractWrapper } from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import { TokenContract } from './generated/token';
|
import { TokenContract, TokenContractEventArgs, TokenEvents } from './generated/token';
|
||||||
import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
|
import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,26 +9,13 @@ export {
|
|||||||
ExchangeContractErrs,
|
ExchangeContractErrs,
|
||||||
ContractEvent,
|
ContractEvent,
|
||||||
Token,
|
Token,
|
||||||
ExchangeEvents,
|
|
||||||
TokenEvents,
|
|
||||||
IndexedFilterValues,
|
IndexedFilterValues,
|
||||||
BlockRange,
|
BlockRange,
|
||||||
OrderCancellationRequest,
|
OrderCancellationRequest,
|
||||||
OrderFillRequest,
|
OrderFillRequest,
|
||||||
LogErrorContractEventArgs,
|
|
||||||
LogCancelContractEventArgs,
|
|
||||||
LogFillContractEventArgs,
|
|
||||||
ExchangeContractEventArgs,
|
|
||||||
TransferContractEventArgs,
|
|
||||||
ApprovalContractEventArgs,
|
|
||||||
TokenContractEventArgs,
|
|
||||||
EtherTokenContractEventArgs,
|
|
||||||
WithdrawalContractEventArgs,
|
|
||||||
DepositContractEventArgs,
|
|
||||||
ContractEventArgs,
|
ContractEventArgs,
|
||||||
Web3Provider,
|
Web3Provider,
|
||||||
ZeroExConfig,
|
ZeroExConfig,
|
||||||
EtherTokenEvents,
|
|
||||||
MethodOpts,
|
MethodOpts,
|
||||||
OrderTransactionOpts,
|
OrderTransactionOpts,
|
||||||
TransactionOpts,
|
TransactionOpts,
|
||||||
@ -50,4 +37,26 @@ export {
|
|||||||
TransactionReceiptWithDecodedLogs,
|
TransactionReceiptWithDecodedLogs,
|
||||||
} from '@0xproject/types';
|
} from '@0xproject/types';
|
||||||
|
|
||||||
|
export {
|
||||||
|
EtherTokenContractEventArgs,
|
||||||
|
WithdrawalContractEventArgs,
|
||||||
|
DepositContractEventArgs,
|
||||||
|
EtherTokenEvents,
|
||||||
|
} from './contract_wrappers/generated/ether_token';
|
||||||
|
|
||||||
|
export {
|
||||||
|
TransferContractEventArgs,
|
||||||
|
ApprovalContractEventArgs,
|
||||||
|
TokenContractEventArgs,
|
||||||
|
TokenEvents,
|
||||||
|
} from './contract_wrappers/generated/token';
|
||||||
|
|
||||||
|
export {
|
||||||
|
LogErrorContractEventArgs,
|
||||||
|
LogCancelContractEventArgs,
|
||||||
|
LogFillContractEventArgs,
|
||||||
|
ExchangeContractEventArgs,
|
||||||
|
ExchangeEvents,
|
||||||
|
} from './contract_wrappers/generated/exchange';
|
||||||
|
|
||||||
export { TransactionReceipt } from '@0xproject/types';
|
export { TransactionReceipt } from '@0xproject/types';
|
||||||
|
@ -6,26 +6,32 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
import { ZeroEx } from '../0x';
|
import { ZeroEx } from '../0x';
|
||||||
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||||
|
import {
|
||||||
|
DepositContractEventArgs,
|
||||||
|
EtherTokenEvents,
|
||||||
|
WithdrawalContractEventArgs,
|
||||||
|
} from '../contract_wrappers/generated/ether_token';
|
||||||
|
import {
|
||||||
|
ExchangeEvents,
|
||||||
|
LogCancelContractEventArgs,
|
||||||
|
LogFillContractEventArgs,
|
||||||
|
} from '../contract_wrappers/generated/exchange';
|
||||||
|
import {
|
||||||
|
ApprovalContractEventArgs,
|
||||||
|
TokenEvents,
|
||||||
|
TransferContractEventArgs,
|
||||||
|
} from '../contract_wrappers/generated/token';
|
||||||
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||||
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||||
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
|
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
|
||||||
import {
|
import {
|
||||||
ApprovalContractEventArgs,
|
|
||||||
ContractEventArgs,
|
ContractEventArgs,
|
||||||
DepositContractEventArgs,
|
|
||||||
EtherTokenEvents,
|
|
||||||
ExchangeContractErrs,
|
ExchangeContractErrs,
|
||||||
ExchangeEvents,
|
|
||||||
LogCancelContractEventArgs,
|
|
||||||
LogEvent,
|
LogEvent,
|
||||||
LogFillContractEventArgs,
|
|
||||||
OnOrderStateChangeCallback,
|
OnOrderStateChangeCallback,
|
||||||
OrderState,
|
OrderState,
|
||||||
OrderStateWatcherConfig,
|
OrderStateWatcherConfig,
|
||||||
SignedOrder,
|
SignedOrder,
|
||||||
TokenEvents,
|
|
||||||
TransferContractEventArgs,
|
|
||||||
WithdrawalContractEventArgs,
|
|
||||||
ZeroExError,
|
ZeroExError,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { assert } from '../utils/assert';
|
import { assert } from '../utils/assert';
|
||||||
|
@ -4,6 +4,10 @@ import { BlockParam, BlockParamLiteral, ContractEventArg, LogWithDecodedArgs } f
|
|||||||
|
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token';
|
||||||
|
import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
|
||||||
|
import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token';
|
||||||
|
|
||||||
export enum ZeroExError {
|
export enum ZeroExError {
|
||||||
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
|
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
|
||||||
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
|
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
|
||||||
@ -101,60 +105,6 @@ export interface ContractEvent {
|
|||||||
args: ContractEventArgs;
|
args: ContractEventArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LogFillContractEventArgs {
|
|
||||||
maker: string;
|
|
||||||
taker: string;
|
|
||||||
feeRecipient: string;
|
|
||||||
makerToken: string;
|
|
||||||
takerToken: string;
|
|
||||||
filledMakerTokenAmount: BigNumber;
|
|
||||||
filledTakerTokenAmount: BigNumber;
|
|
||||||
paidMakerFee: BigNumber;
|
|
||||||
paidTakerFee: BigNumber;
|
|
||||||
tokens: string;
|
|
||||||
orderHash: string;
|
|
||||||
}
|
|
||||||
export interface LogCancelContractEventArgs {
|
|
||||||
maker: string;
|
|
||||||
feeRecipient: string;
|
|
||||||
makerToken: string;
|
|
||||||
takerToken: string;
|
|
||||||
cancelledMakerTokenAmount: BigNumber;
|
|
||||||
cancelledTakerTokenAmount: BigNumber;
|
|
||||||
tokens: string;
|
|
||||||
orderHash: string;
|
|
||||||
}
|
|
||||||
export interface LogErrorContractEventArgs {
|
|
||||||
errorId: BigNumber;
|
|
||||||
orderHash: string;
|
|
||||||
}
|
|
||||||
export type ExchangeContractEventArgs =
|
|
||||||
| LogFillContractEventArgs
|
|
||||||
| LogCancelContractEventArgs
|
|
||||||
| LogErrorContractEventArgs;
|
|
||||||
export interface TransferContractEventArgs {
|
|
||||||
_from: string;
|
|
||||||
_to: string;
|
|
||||||
_value: BigNumber;
|
|
||||||
}
|
|
||||||
export interface ApprovalContractEventArgs {
|
|
||||||
_owner: string;
|
|
||||||
_spender: string;
|
|
||||||
_value: BigNumber;
|
|
||||||
}
|
|
||||||
export interface DepositContractEventArgs {
|
|
||||||
_owner: string;
|
|
||||||
_value: BigNumber;
|
|
||||||
}
|
|
||||||
export interface WithdrawalContractEventArgs {
|
|
||||||
_owner: string;
|
|
||||||
_value: BigNumber;
|
|
||||||
}
|
|
||||||
export type TokenContractEventArgs = TransferContractEventArgs | ApprovalContractEventArgs;
|
|
||||||
export type EtherTokenContractEventArgs =
|
|
||||||
| TokenContractEventArgs
|
|
||||||
| DepositContractEventArgs
|
|
||||||
| WithdrawalContractEventArgs;
|
|
||||||
export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
|
export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
|
||||||
|
|
||||||
export interface Order {
|
export interface Order {
|
||||||
@ -197,24 +147,6 @@ export interface TokenAddressBySymbol {
|
|||||||
[symbol: string]: string;
|
[symbol: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ExchangeEvents {
|
|
||||||
LogFill = 'LogFill',
|
|
||||||
LogCancel = 'LogCancel',
|
|
||||||
LogError = 'LogError',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum TokenEvents {
|
|
||||||
Transfer = 'Transfer',
|
|
||||||
Approval = 'Approval',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum EtherTokenEvents {
|
|
||||||
Transfer = 'Transfer',
|
|
||||||
Approval = 'Approval',
|
|
||||||
Deposit = 'Deposit',
|
|
||||||
Withdrawal = 'Withdrawal',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
|
export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
|
||||||
|
|
||||||
export interface IndexedFilterValues {
|
export interface IndexedFilterValues {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
## v0.2.0 - _???_
|
## v0.2.0 - _???_
|
||||||
|
|
||||||
* Added CLI options for explicit specifying location of partials and main template (#346)
|
* Added CLI options for explicit specifying location of partials and main template (#346)
|
||||||
|
* Added CLI option to specify networkId, adding support for the JSON artifact format found in @0xproject/contracts
|
||||||
|
|
||||||
## v0.1.0 - _January 11, 2018_
|
## v0.1.0 - _January 11, 2018_
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import { utils } from './utils';
|
|||||||
const ABI_TYPE_CONSTRUCTOR = 'constructor';
|
const ABI_TYPE_CONSTRUCTOR = 'constructor';
|
||||||
const ABI_TYPE_METHOD = 'function';
|
const ABI_TYPE_METHOD = 'function';
|
||||||
const ABI_TYPE_EVENT = 'event';
|
const ABI_TYPE_EVENT = 'event';
|
||||||
|
const DEFAULT_NETWORK_ID = 50;
|
||||||
|
|
||||||
const args = yargs
|
const args = yargs
|
||||||
.option('abis', {
|
.option('abis', {
|
||||||
@ -42,6 +43,11 @@ const args = yargs
|
|||||||
demandOption: true,
|
demandOption: true,
|
||||||
normalize: true,
|
normalize: true,
|
||||||
})
|
})
|
||||||
|
.option('network-id', {
|
||||||
|
describe: 'ID of the network where contract ABIs are nested in artifacts',
|
||||||
|
type: 'number',
|
||||||
|
default: DEFAULT_NETWORK_ID,
|
||||||
|
})
|
||||||
.example(
|
.example(
|
||||||
"$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'",
|
"$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'",
|
||||||
'Full usage example',
|
'Full usage example',
|
||||||
@ -58,7 +64,10 @@ function registerPartials(partialsGlob: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writeOutputFile(name: string, renderedTsCode: string): void {
|
function writeOutputFile(name: string, renderedTsCode: string): void {
|
||||||
const fileName = toSnakeCase(name);
|
let fileName = toSnakeCase(name);
|
||||||
|
if (fileName === 'z_r_x_token') {
|
||||||
|
fileName = 'zrx_token';
|
||||||
|
}
|
||||||
const filePath = `${args.output}/${fileName}.ts`;
|
const filePath = `${args.output}/${fileName}.ts`;
|
||||||
fs.writeFileSync(filePath, renderedTsCode);
|
fs.writeFileSync(filePath, renderedTsCode);
|
||||||
utils.log(`Created: ${chalk.bold(filePath)}`);
|
utils.log(`Created: ${chalk.bold(filePath)}`);
|
||||||
@ -87,12 +96,19 @@ for (const abiFileName of abiFileNames) {
|
|||||||
const namedContent = utils.getNamedContent(abiFileName);
|
const namedContent = utils.getNamedContent(abiFileName);
|
||||||
utils.log(`Processing: ${chalk.bold(namedContent.name)}...`);
|
utils.log(`Processing: ${chalk.bold(namedContent.name)}...`);
|
||||||
const parsedContent = JSON.parse(namedContent.content);
|
const parsedContent = JSON.parse(namedContent.content);
|
||||||
const ABI = _.isArray(parsedContent)
|
let ABI;
|
||||||
? parsedContent // ABI file
|
if (_.isArray(parsedContent)) {
|
||||||
: parsedContent.abi; // Truffle contracts file
|
ABI = parsedContent; // ABI file
|
||||||
|
} else if (!_.isUndefined(parsedContent.abi)) {
|
||||||
|
ABI = parsedContent.abi; // Truffle artifact
|
||||||
|
} else if (!_.isUndefined(parsedContent.networks) && !_.isUndefined(parsedContent.networks[args.networkId])) {
|
||||||
|
ABI = parsedContent.networks[args.networkId].abi; // 0x contracts package artifact
|
||||||
|
}
|
||||||
if (_.isUndefined(ABI)) {
|
if (_.isUndefined(ABI)) {
|
||||||
utils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
|
utils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
|
||||||
utils.log(`Please make sure your ABI file is either an array with ABI entries or an object with the abi key`);
|
utils.log(
|
||||||
|
`Please make sure your ABI file is either an array with ABI entries or a truffle artifact or 0x deployer artifact`,
|
||||||
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,10 +119,10 @@ for (const abiFileName of abiFileNames) {
|
|||||||
|
|
||||||
const methodAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_METHOD) as Web3.MethodAbi[];
|
const methodAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_METHOD) as Web3.MethodAbi[];
|
||||||
const methodsData = _.map(methodAbis, methodAbi => {
|
const methodsData = _.map(methodAbis, methodAbi => {
|
||||||
_.map(methodAbi.inputs, input => {
|
_.map(methodAbi.inputs, (input, i: number) => {
|
||||||
if (_.isEmpty(input.name)) {
|
if (_.isEmpty(input.name)) {
|
||||||
// Auto-generated getters don't have parameter names
|
// Auto-generated getters don't have parameter names
|
||||||
input.name = 'index';
|
input.name = `index_${i}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// This will make templates simpler
|
// This will make templates simpler
|
||||||
|
26
packages/contracts/contract_templates/contract.handlebars
Normal file
26
packages/contracts/contract_templates/contract.handlebars
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* This file is auto-generated using abi-gen. Don't edit directly.
|
||||||
|
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates.
|
||||||
|
*/
|
||||||
|
// tslint:disable:async-suffix member-ordering no-consecutive-blank-lines
|
||||||
|
// tslint:disable-next-line:no-unused-variable
|
||||||
|
import { TxData, TxDataPayable } from '@0xproject/types';
|
||||||
|
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
||||||
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import {BaseContract} from './base_contract';
|
||||||
|
|
||||||
|
export class {{contractName}}Contract extends BaseContract {
|
||||||
|
{{#each methods}}
|
||||||
|
{{#this.constant}}
|
||||||
|
{{> call contractName=../contractName}}
|
||||||
|
{{/this.constant}}
|
||||||
|
{{^this.constant}}
|
||||||
|
{{> tx contractName=../contractName}}
|
||||||
|
{{/this.constant}}
|
||||||
|
{{/each}}
|
||||||
|
constructor(web3ContractInstance: Web3.ContractInstance, defaults?: Partial<TxData>) {
|
||||||
|
super(web3ContractInstance, defaults);
|
||||||
|
classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']);
|
||||||
|
}
|
||||||
|
} // tslint:disable:max-file-line-count
|
@ -0,0 +1,10 @@
|
|||||||
|
public async {{this.name}}(
|
||||||
|
{{> typed_params inputs=inputs}}
|
||||||
|
defaultBlock?: Web3.BlockParam,
|
||||||
|
): Promise<{{> return_type outputs=outputs}}> {
|
||||||
|
const self = this as {{contractName}}Contract;
|
||||||
|
const result = await self._web3ContractInstance.{{this.name}}.call(
|
||||||
|
{{> params inputs=inputs}}
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
{{#each inputs}}
|
||||||
|
{{name}},
|
||||||
|
{{/each}}
|
@ -0,0 +1,10 @@
|
|||||||
|
{{#if outputs.length}}
|
||||||
|
{{#singleReturnValue}}
|
||||||
|
{{#returnType outputs.0.type}}{{/returnType}}
|
||||||
|
{{/singleReturnValue}}
|
||||||
|
{{^singleReturnValue}}
|
||||||
|
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||||
|
{{/singleReturnValue}}
|
||||||
|
{{else}}
|
||||||
|
void
|
||||||
|
{{/if}}
|
36
packages/contracts/contract_templates/partials/tx.handlebars
Normal file
36
packages/contracts/contract_templates/partials/tx.handlebars
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
public {{this.name}} = {
|
||||||
|
async sendTransactionAsync(
|
||||||
|
{{> typed_params inputs=inputs}}
|
||||||
|
{{#this.payable}}
|
||||||
|
txData: TxDataPayable = {},
|
||||||
|
{{/this.payable}}
|
||||||
|
{{^this.payable}}
|
||||||
|
txData: TxData = {},
|
||||||
|
{{/this.payable}}
|
||||||
|
): Promise<string> {
|
||||||
|
const self = this as {{contractName}}Contract;
|
||||||
|
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
|
||||||
|
const txHash = await self._web3ContractInstance.{{this.name}}(
|
||||||
|
{{> params inputs=inputs}}
|
||||||
|
txDataWithDefaults,
|
||||||
|
);
|
||||||
|
return txHash;
|
||||||
|
},
|
||||||
|
async callAsync(
|
||||||
|
{{> typed_params inputs=inputs}}
|
||||||
|
{{#this.payable}}
|
||||||
|
txData: TxDataPayable = {},
|
||||||
|
{{/this.payable}}
|
||||||
|
{{^this.payable}}
|
||||||
|
txData: TxData = {},
|
||||||
|
{{/this.payable}}
|
||||||
|
): Promise<{{> return_type outputs=outputs}}> {
|
||||||
|
const self = this as {{contractName}}Contract;
|
||||||
|
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
|
||||||
|
const returnValue = await self._web3ContractInstance.{{this.name}}.call(
|
||||||
|
{{> params inputs=inputs}}
|
||||||
|
txDataWithDefaults,
|
||||||
|
);
|
||||||
|
return returnValue;
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,3 @@
|
|||||||
|
{{#each inputs}}
|
||||||
|
{{name}}: {{#parameterType type}}{{/parameterType}},
|
||||||
|
{{/each}}
|
@ -9,14 +9,15 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:watch": "tsc -w",
|
"build:watch": "tsc -w",
|
||||||
"prebuild": "run-s clean copy_artifacts",
|
"prebuild": "run-s clean copy_artifacts generate_contract_wrappers",
|
||||||
"copy_artifacts": "copyfiles './artifacts/**/*' ./lib",
|
"copy_artifacts": "copyfiles './src/artifacts/**/*' ./lib",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"test": "run-s compile build run_mocha",
|
"test": "run-s compile build run_mocha",
|
||||||
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 10000 --bail --exit",
|
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 10000 --bail --exit",
|
||||||
"compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
|
"compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
|
||||||
"compile": "node ../deployer/lib/src/cli.js compile",
|
"compile": "node ../deployer/lib/src/cli.js compile --contracts-dir src/contracts --artifacts-dir src/artifacts",
|
||||||
"clean": "rm -rf ./lib",
|
"clean": "rm -rf ./lib",
|
||||||
|
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken).json' --template contract_templates/contract.handlebars --partials 'contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated",
|
||||||
"migrate": "node ../deployer/lib/src/cli.js migrate",
|
"migrate": "node ../deployer/lib/src/cli.js migrate",
|
||||||
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
|
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
|
||||||
"test:circleci": "yarn test"
|
"test:circleci": "yarn test"
|
||||||
|
8
packages/contracts/src/contract_wrappers/generated/.gitignore
vendored
Normal file
8
packages/contracts/src/contract_wrappers/generated/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
dummy_token.ts
|
||||||
|
exchange.ts
|
||||||
|
multi_sig_wallet_with_time_lock_except_remove_authorized_address.ts
|
||||||
|
multi_sig_wallet_with_time_lock.ts
|
||||||
|
multi_sig_wallet.ts
|
||||||
|
token_registry.ts
|
||||||
|
token_transfer_proxy.ts
|
||||||
|
zrx_token.ts
|
@ -0,0 +1,35 @@
|
|||||||
|
import {TxData, TxDataPayable} from '@0xproject/types';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
export class BaseContract {
|
||||||
|
public address: string;
|
||||||
|
protected _web3ContractInstance: Web3.ContractInstance;
|
||||||
|
protected _defaults: Partial<TxData>;
|
||||||
|
protected async _applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>(
|
||||||
|
txData: T,
|
||||||
|
estimateGasAsync?: (txData: T) => Promise<number>,
|
||||||
|
): Promise<TxData> {
|
||||||
|
// Gas amount sourced with the following priorities:
|
||||||
|
// 1. Optional param passed in to public method call
|
||||||
|
// 2. Global config passed in at library instantiation
|
||||||
|
// 3. Gas estimate calculation + safety margin
|
||||||
|
const removeUndefinedProperties = _.pickBy;
|
||||||
|
const txDataWithDefaults = {
|
||||||
|
...removeUndefinedProperties(this._defaults),
|
||||||
|
...removeUndefinedProperties(txData as any),
|
||||||
|
// HACK: TS can't prove that T is spreadable.
|
||||||
|
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
|
||||||
|
};
|
||||||
|
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
|
||||||
|
const estimatedGas = await estimateGasAsync(txData);
|
||||||
|
txDataWithDefaults.gas = estimatedGas;
|
||||||
|
}
|
||||||
|
return txDataWithDefaults;
|
||||||
|
}
|
||||||
|
constructor(web3ContractInstance: Web3.ContractInstance, defaults?: Partial<TxData>) {
|
||||||
|
this.address = web3ContractInstance.address;
|
||||||
|
this._web3ContractInstance = web3ContractInstance;
|
||||||
|
this._defaults = defaults || {};
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,9 @@ import * as chai from 'chai';
|
|||||||
import ethUtil = require('ethereumjs-util');
|
import ethUtil = require('ethereumjs-util');
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
||||||
|
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
|
||||||
|
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
|
||||||
import { Balances } from '../../util/balances';
|
import { Balances } from '../../util/balances';
|
||||||
import { constants } from '../../util/constants';
|
import { constants } from '../../util/constants';
|
||||||
import { crypto } from '../../util/crypto';
|
import { crypto } from '../../util/crypto';
|
||||||
@ -37,11 +40,11 @@ describe('Exchange', () => {
|
|||||||
const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
||||||
const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
||||||
|
|
||||||
let rep: Web3.ContractInstance;
|
let rep: DummyTokenContract;
|
||||||
let dgd: Web3.ContractInstance;
|
let dgd: DummyTokenContract;
|
||||||
let zrx: Web3.ContractInstance;
|
let zrx: DummyTokenContract;
|
||||||
let exchange: Web3.ContractInstance;
|
let exchange: ExchangeContract;
|
||||||
let tokenTransferProxy: Web3.ContractInstance;
|
let tokenTransferProxy: TokenTransferProxyContract;
|
||||||
|
|
||||||
let order: Order;
|
let order: Order;
|
||||||
let balances: BalancesByOwner;
|
let balances: BalancesByOwner;
|
||||||
@ -55,14 +58,22 @@ describe('Exchange', () => {
|
|||||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
maker = accounts[0];
|
maker = accounts[0];
|
||||||
[tokenOwner, taker, feeRecipient] = accounts;
|
[tokenOwner, taker, feeRecipient] = accounts;
|
||||||
[rep, dgd, zrx] = await Promise.all([
|
const [repInstance, dgdInstance, zrxInstance] = await Promise.all([
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
]);
|
]);
|
||||||
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
rep = new DummyTokenContract(repInstance);
|
||||||
exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]);
|
dgd = new DummyTokenContract(dgdInstance);
|
||||||
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
|
zrx = new DummyTokenContract(zrxInstance);
|
||||||
|
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
||||||
|
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
|
||||||
|
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
|
||||||
|
zrx.address,
|
||||||
|
tokenTransferProxy.address,
|
||||||
|
]);
|
||||||
|
exchange = new ExchangeContract(exchangeInstance);
|
||||||
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, {
|
zeroEx = new ZeroEx(web3.currentProvider, {
|
||||||
exchangeContractAddress: exchange.address,
|
exchangeContractAddress: exchange.address,
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
@ -83,30 +94,30 @@ describe('Exchange', () => {
|
|||||||
orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams);
|
orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams);
|
||||||
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
|
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: maker,
|
from: maker,
|
||||||
}),
|
}),
|
||||||
rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: taker,
|
from: taker,
|
||||||
}),
|
}),
|
||||||
rep.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }),
|
rep.setBalance.sendTransactionAsync(maker, INITIAL_BALANCE, { from: tokenOwner }),
|
||||||
rep.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }),
|
rep.setBalance.sendTransactionAsync(taker, INITIAL_BALANCE, { from: tokenOwner }),
|
||||||
dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: maker,
|
from: maker,
|
||||||
}),
|
}),
|
||||||
dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: taker,
|
from: taker,
|
||||||
}),
|
}),
|
||||||
dgd.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }),
|
dgd.setBalance.sendTransactionAsync(maker, INITIAL_BALANCE, { from: tokenOwner }),
|
||||||
dgd.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }),
|
dgd.setBalance.sendTransactionAsync(taker, INITIAL_BALANCE, { from: tokenOwner }),
|
||||||
zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: maker,
|
from: maker,
|
||||||
}),
|
}),
|
||||||
zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: taker,
|
from: taker,
|
||||||
}),
|
}),
|
||||||
zrx.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }),
|
zrx.setBalance.sendTransactionAsync(maker, INITIAL_BALANCE, { from: tokenOwner }),
|
||||||
zrx.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }),
|
zrx.setBalance.sendTransactionAsync(taker, INITIAL_BALANCE, { from: tokenOwner }),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -117,19 +128,19 @@ describe('Exchange', () => {
|
|||||||
});
|
});
|
||||||
describe('internal functions', () => {
|
describe('internal functions', () => {
|
||||||
it('should include transferViaTokenTransferProxy', () => {
|
it('should include transferViaTokenTransferProxy', () => {
|
||||||
expect(exchange.transferViaTokenTransferProxy).to.be.undefined();
|
expect((exchange as any).transferViaTokenTransferProxy).to.be.undefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include isTransferable', () => {
|
it('should include isTransferable', () => {
|
||||||
expect(exchange.isTransferable).to.be.undefined();
|
expect((exchange as any).isTransferable).to.be.undefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include getBalance', () => {
|
it('should include getBalance', () => {
|
||||||
expect(exchange.getBalance).to.be.undefined();
|
expect((exchange as any).getBalance).to.be.undefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include getAllowance', () => {
|
it('should include getAllowance', () => {
|
||||||
expect(exchange.getAllowance).to.be.undefined();
|
expect((exchange as any).getAllowance).to.be.undefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -565,9 +576,9 @@ describe('Exchange', () => {
|
|||||||
|
|
||||||
it('should not change balances if maker allowances are too low to fill order and \
|
it('should not change balances if maker allowances are too low to fill order and \
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
||||||
await rep.approve(tokenTransferProxy.address, 0, { from: maker });
|
await rep.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: maker });
|
||||||
await exWrapper.fillOrderAsync(order, taker);
|
await exWrapper.fillOrderAsync(order, taker);
|
||||||
await rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
await rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: maker,
|
from: maker,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -577,22 +588,22 @@ describe('Exchange', () => {
|
|||||||
|
|
||||||
it('should throw if maker allowances are too low to fill order and \
|
it('should throw if maker allowances are too low to fill order and \
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance = true', async () => {
|
shouldThrowOnInsufficientBalanceOrAllowance = true', async () => {
|
||||||
await rep.approve(tokenTransferProxy.address, 0, { from: maker });
|
await rep.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: maker });
|
||||||
expect(
|
expect(
|
||||||
exWrapper.fillOrderAsync(order, taker, {
|
exWrapper.fillOrderAsync(order, taker, {
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance: true,
|
shouldThrowOnInsufficientBalanceOrAllowance: true,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
await rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
await rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: maker,
|
from: maker,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not change balances if taker allowances are too low to fill order and \
|
it('should not change balances if taker allowances are too low to fill order and \
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
||||||
await dgd.approve(tokenTransferProxy.address, 0, { from: taker });
|
await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: taker });
|
||||||
await exWrapper.fillOrderAsync(order, taker);
|
await exWrapper.fillOrderAsync(order, taker);
|
||||||
await dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: taker,
|
from: taker,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -602,13 +613,13 @@ describe('Exchange', () => {
|
|||||||
|
|
||||||
it('should throw if taker allowances are too low to fill order and \
|
it('should throw if taker allowances are too low to fill order and \
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance = true', async () => {
|
shouldThrowOnInsufficientBalanceOrAllowance = true', async () => {
|
||||||
await dgd.approve(tokenTransferProxy.address, 0, { from: taker });
|
await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: taker });
|
||||||
expect(
|
expect(
|
||||||
exWrapper.fillOrderAsync(order, taker, {
|
exWrapper.fillOrderAsync(order, taker, {
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance: true,
|
shouldThrowOnInsufficientBalanceOrAllowance: true,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
await dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
from: taker,
|
from: taker,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -668,7 +679,9 @@ describe('Exchange', () => {
|
|||||||
it('should throw if getBalance or getAllowance attempts to change state and \
|
it('should throw if getBalance or getAllowance attempts to change state and \
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
||||||
const maliciousToken = await deployer.deployAsync(ContractName.MaliciousToken);
|
const maliciousToken = await deployer.deployAsync(ContractName.MaliciousToken);
|
||||||
await maliciousToken.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: taker });
|
await maliciousToken.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
|
||||||
|
from: taker,
|
||||||
|
});
|
||||||
|
|
||||||
order = await orderFactory.newSignedOrderAsync({
|
order = await orderFactory.newSignedOrderAsync({
|
||||||
takerToken: maliciousToken.address,
|
takerToken: maliciousToken.address,
|
||||||
|
@ -5,6 +5,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import ethUtil = require('ethereumjs-util');
|
import ethUtil = require('ethereumjs-util');
|
||||||
|
|
||||||
|
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
|
||||||
import { constants } from '../../util/constants';
|
import { constants } from '../../util/constants';
|
||||||
import { ExchangeWrapper } from '../../util/exchange_wrapper';
|
import { ExchangeWrapper } from '../../util/exchange_wrapper';
|
||||||
import { Order } from '../../util/order';
|
import { Order } from '../../util/order';
|
||||||
@ -38,7 +39,11 @@ describe('Exchange', () => {
|
|||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
]);
|
]);
|
||||||
const exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]);
|
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
|
||||||
|
zrx.address,
|
||||||
|
tokenTransferProxy.address,
|
||||||
|
]);
|
||||||
|
const exchange = new ExchangeContract(exchangeInstance);
|
||||||
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
|
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
|
||||||
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
||||||
exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);
|
exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);
|
||||||
|
@ -6,6 +6,10 @@ import * as chai from 'chai';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
||||||
|
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
|
||||||
|
import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
|
||||||
|
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
|
||||||
import { Balances } from '../../util/balances';
|
import { Balances } from '../../util/balances';
|
||||||
import { constants } from '../../util/constants';
|
import { constants } from '../../util/constants';
|
||||||
import { ExchangeWrapper } from '../../util/exchange_wrapper';
|
import { ExchangeWrapper } from '../../util/exchange_wrapper';
|
||||||
@ -30,12 +34,12 @@ describe('Exchange', () => {
|
|||||||
const INIT_BAL = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
const INIT_BAL = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
||||||
const INIT_ALLOW = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
const INIT_ALLOW = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
|
||||||
|
|
||||||
let rep: Web3.ContractInstance;
|
let rep: DummyTokenContract;
|
||||||
let dgd: Web3.ContractInstance;
|
let dgd: DummyTokenContract;
|
||||||
let zrx: Web3.ContractInstance;
|
let zrx: DummyTokenContract;
|
||||||
let exchange: Web3.ContractInstance;
|
let exchange: ExchangeContract;
|
||||||
let tokenRegistry: Web3.ContractInstance;
|
let tokenRegistry: TokenRegistryContract;
|
||||||
let tokenTransferProxy: Web3.ContractInstance;
|
let tokenTransferProxy: TokenTransferProxyContract;
|
||||||
|
|
||||||
let balances: BalancesByOwner;
|
let balances: BalancesByOwner;
|
||||||
|
|
||||||
@ -47,15 +51,24 @@ describe('Exchange', () => {
|
|||||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
tokenOwner = accounts[0];
|
tokenOwner = accounts[0];
|
||||||
[maker, taker, feeRecipient] = accounts;
|
[maker, taker, feeRecipient] = accounts;
|
||||||
[rep, dgd, zrx] = await Promise.all([
|
const [repInstance, dgdInstance, zrxInstance] = await Promise.all([
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
]);
|
]);
|
||||||
tokenRegistry = await deployer.deployAsync(ContractName.TokenRegistry);
|
rep = new DummyTokenContract(repInstance);
|
||||||
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
dgd = new DummyTokenContract(dgdInstance);
|
||||||
exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]);
|
zrx = new DummyTokenContract(zrxInstance);
|
||||||
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
|
const tokenRegistryInstance = await deployer.deployAsync(ContractName.TokenRegistry);
|
||||||
|
tokenRegistry = new TokenRegistryContract(tokenRegistryInstance);
|
||||||
|
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
||||||
|
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
|
||||||
|
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
|
||||||
|
zrx.address,
|
||||||
|
tokenTransferProxy.address,
|
||||||
|
]);
|
||||||
|
exchange = new ExchangeContract(exchangeInstance);
|
||||||
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
|
||||||
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
||||||
exWrapper = new ExchangeWrapper(exchange, zeroEx);
|
exWrapper = new ExchangeWrapper(exchange, zeroEx);
|
||||||
|
|
||||||
@ -74,18 +87,18 @@ describe('Exchange', () => {
|
|||||||
orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams);
|
orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams);
|
||||||
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
|
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
rep.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
|
rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
|
||||||
rep.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
|
rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
|
||||||
rep.setBalance(maker, INIT_BAL, { from: tokenOwner }),
|
rep.setBalance.sendTransactionAsync(maker, INIT_BAL, { from: tokenOwner }),
|
||||||
rep.setBalance(taker, INIT_BAL, { from: tokenOwner }),
|
rep.setBalance.sendTransactionAsync(taker, INIT_BAL, { from: tokenOwner }),
|
||||||
dgd.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
|
dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
|
||||||
dgd.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
|
dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
|
||||||
dgd.setBalance(maker, INIT_BAL, { from: tokenOwner }),
|
dgd.setBalance.sendTransactionAsync(maker, INIT_BAL, { from: tokenOwner }),
|
||||||
dgd.setBalance(taker, INIT_BAL, { from: tokenOwner }),
|
dgd.setBalance.sendTransactionAsync(taker, INIT_BAL, { from: tokenOwner }),
|
||||||
zrx.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
|
zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
|
||||||
zrx.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
|
zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
|
||||||
zrx.setBalance(maker, INIT_BAL, { from: tokenOwner }),
|
zrx.setBalance.sendTransactionAsync(maker, INIT_BAL, { from: tokenOwner }),
|
||||||
zrx.setBalance(taker, INIT_BAL, { from: tokenOwner }),
|
zrx.setBalance.sendTransactionAsync(taker, INIT_BAL, { from: tokenOwner }),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
@ -6,6 +6,8 @@ import * as chai from 'chai';
|
|||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json';
|
import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json';
|
||||||
|
import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet';
|
||||||
|
import { MultiSigWalletWithTimeLockContract } from '../src/contract_wrappers/generated/multi_sig_wallet_with_time_lock';
|
||||||
import { artifacts } from '../util/artifacts';
|
import { artifacts } from '../util/artifacts';
|
||||||
import { constants } from '../util/constants';
|
import { constants } from '../util/constants';
|
||||||
import { MultiSigWrapper } from '../util/multi_sig_wrapper';
|
import { MultiSigWrapper } from '../util/multi_sig_wrapper';
|
||||||
@ -30,12 +32,12 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
owners = [accounts[0], accounts[1]];
|
owners = [accounts[0], accounts[1]];
|
||||||
});
|
});
|
||||||
const SIGNATURES_REQUIRED = 2;
|
const SIGNATURES_REQUIRED = new BigNumber(2);
|
||||||
const SECONDS_TIME_LOCKED = 10000;
|
const SECONDS_TIME_LOCKED = new BigNumber(10000);
|
||||||
|
|
||||||
let multiSig: Web3.ContractInstance;
|
let multiSig: MultiSigWalletWithTimeLockContract;
|
||||||
let multiSigWrapper: MultiSigWrapper;
|
let multiSigWrapper: MultiSigWrapper;
|
||||||
let txId: number;
|
let txId: BigNumber;
|
||||||
let initialSecondsTimeLocked: number;
|
let initialSecondsTimeLocked: number;
|
||||||
let rpc: RPC;
|
let rpc: RPC;
|
||||||
|
|
||||||
@ -52,20 +54,21 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
describe('changeTimeLock', () => {
|
describe('changeTimeLock', () => {
|
||||||
describe('initially non-time-locked', async () => {
|
describe('initially non-time-locked', async () => {
|
||||||
before('deploy a walet', async () => {
|
before('deploy a walet', async () => {
|
||||||
multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
||||||
owners,
|
owners,
|
||||||
SIGNATURES_REQUIRED,
|
SIGNATURES_REQUIRED,
|
||||||
0,
|
0,
|
||||||
]);
|
]);
|
||||||
multiSigWrapper = new MultiSigWrapper(multiSig);
|
multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
|
||||||
|
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
|
||||||
|
|
||||||
const secondsTimeLocked = await multiSig.secondsTimeLocked();
|
const secondsTimeLocked = await multiSig.secondsTimeLocked();
|
||||||
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
||||||
});
|
});
|
||||||
it('should throw when not called by wallet', async () => {
|
it('should throw when not called by wallet', async () => {
|
||||||
return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, { from: owners[0] })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw without enough confirmations', async () => {
|
it('should throw without enough confirmations', async () => {
|
||||||
@ -74,7 +77,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
const dataParams = {
|
const dataParams = {
|
||||||
name: 'changeTimeLock',
|
name: 'changeTimeLock',
|
||||||
abi: MULTI_SIG_ABI,
|
abi: MULTI_SIG_ABI,
|
||||||
args: [SECONDS_TIME_LOCKED],
|
args: [SECONDS_TIME_LOCKED.toNumber()],
|
||||||
};
|
};
|
||||||
const txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
|
const txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
|
||||||
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
@ -82,10 +85,10 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
SubmissionContractEventArgs
|
SubmissionContractEventArgs
|
||||||
>;
|
>;
|
||||||
|
|
||||||
txId = log.args.transactionId.toNumber();
|
txId = log.args.transactionId;
|
||||||
return expect(multiSig.executeTransaction(txId, { from: owners[0] })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set confirmation time with enough confirmations', async () => {
|
it('should set confirmation time with enough confirmations', async () => {
|
||||||
@ -94,7 +97,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
const dataParams = {
|
const dataParams = {
|
||||||
name: 'changeTimeLock',
|
name: 'changeTimeLock',
|
||||||
abi: MULTI_SIG_ABI,
|
abi: MULTI_SIG_ABI,
|
||||||
args: [SECONDS_TIME_LOCKED],
|
args: [SECONDS_TIME_LOCKED.toNumber()],
|
||||||
};
|
};
|
||||||
let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
|
let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
|
||||||
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
@ -102,15 +105,15 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
SubmissionContractEventArgs
|
SubmissionContractEventArgs
|
||||||
>;
|
>;
|
||||||
|
|
||||||
txId = log.args.transactionId.toNumber();
|
txId = log.args.transactionId;
|
||||||
txHash = await multiSig.confirmTransaction(txId, { from: owners[1] });
|
txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
expect(res.logs).to.have.length(2);
|
expect(res.logs).to.have.length(2);
|
||||||
|
|
||||||
const blockNum = await web3Wrapper.getBlockNumberAsync();
|
const blockNum = await web3Wrapper.getBlockNumberAsync();
|
||||||
const blockInfo = await web3Wrapper.getBlockAsync(blockNum);
|
const blockInfo = await web3Wrapper.getBlockAsync(blockNum);
|
||||||
const timestamp = new BigNumber(blockInfo.timestamp);
|
const timestamp = new BigNumber(blockInfo.timestamp);
|
||||||
const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.call(txId));
|
const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes(txId));
|
||||||
|
|
||||||
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
|
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
|
||||||
});
|
});
|
||||||
@ -121,7 +124,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
const dataParams = {
|
const dataParams = {
|
||||||
name: 'changeTimeLock',
|
name: 'changeTimeLock',
|
||||||
abi: MULTI_SIG_ABI,
|
abi: MULTI_SIG_ABI,
|
||||||
args: [SECONDS_TIME_LOCKED],
|
args: [SECONDS_TIME_LOCKED.toNumber()],
|
||||||
};
|
};
|
||||||
let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
|
let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
|
||||||
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
@ -129,27 +132,28 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
SubmissionContractEventArgs
|
SubmissionContractEventArgs
|
||||||
>;
|
>;
|
||||||
|
|
||||||
txId = log.args.transactionId.toNumber();
|
txId = log.args.transactionId;
|
||||||
txHash = await multiSig.confirmTransaction(txId, { from: owners[1] });
|
txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
|
|
||||||
expect(initialSecondsTimeLocked).to.be.equal(0);
|
expect(initialSecondsTimeLocked).to.be.equal(0);
|
||||||
|
|
||||||
txHash = await multiSig.executeTransaction(txId, { from: owners[0] });
|
txHash = await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] });
|
||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
expect(res.logs).to.have.length(2);
|
expect(res.logs).to.have.length(2);
|
||||||
|
|
||||||
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
|
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked());
|
||||||
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
|
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('initially time-locked', async () => {
|
describe('initially time-locked', async () => {
|
||||||
before('deploy a walet', async () => {
|
before('deploy a walet', async () => {
|
||||||
multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
||||||
owners,
|
owners,
|
||||||
SIGNATURES_REQUIRED,
|
SIGNATURES_REQUIRED,
|
||||||
SECONDS_TIME_LOCKED,
|
SECONDS_TIME_LOCKED,
|
||||||
]);
|
]);
|
||||||
multiSigWrapper = new MultiSigWrapper(multiSig);
|
multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
|
||||||
|
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
|
||||||
|
|
||||||
const secondsTimeLocked = await multiSig.secondsTimeLocked();
|
const secondsTimeLocked = await multiSig.secondsTimeLocked();
|
||||||
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
||||||
@ -165,8 +169,8 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs<
|
const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs<
|
||||||
SubmissionContractEventArgs
|
SubmissionContractEventArgs
|
||||||
>;
|
>;
|
||||||
txId = log.args.transactionId.toNumber();
|
txId = log.args.transactionId;
|
||||||
txHash = await multiSig.confirmTransaction(txId, {
|
txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, {
|
||||||
from: owners[1],
|
from: owners[1],
|
||||||
});
|
});
|
||||||
const confRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const confRes = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
@ -174,16 +178,16 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
});
|
});
|
||||||
const newSecondsTimeLocked = 0;
|
const newSecondsTimeLocked = 0;
|
||||||
it('should throw if it has enough confirmations but is not past the time lock', async () => {
|
it('should throw if it has enough confirmations but is not past the time lock', async () => {
|
||||||
return expect(multiSig.executeTransaction(txId, { from: owners[0] })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute if it has enough confirmations and is past the time lock', async () => {
|
it('should execute if it has enough confirmations and is past the time lock', async () => {
|
||||||
await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED);
|
await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber());
|
||||||
await multiSig.executeTransaction(txId, { from: owners[0] });
|
await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] });
|
||||||
|
|
||||||
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
|
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked());
|
||||||
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
|
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,6 +5,9 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet';
|
||||||
|
import { MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract } from '../src/contract_wrappers/generated/multi_sig_wallet_with_time_lock_except_remove_authorized_address';
|
||||||
|
import { TokenTransferProxyContract } from '../src/contract_wrappers/generated/token_transfer_proxy';
|
||||||
import { artifacts } from '../util/artifacts';
|
import { artifacts } from '../util/artifacts';
|
||||||
import { constants } from '../util/constants';
|
import { constants } from '../util/constants';
|
||||||
import { crypto } from '../util/crypto';
|
import { crypto } from '../util/crypto';
|
||||||
@ -35,8 +38,8 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
let authorizedAddress: string;
|
let authorizedAddress: string;
|
||||||
let unauthorizedAddress: string;
|
let unauthorizedAddress: string;
|
||||||
|
|
||||||
let tokenTransferProxy: Web3.ContractInstance;
|
let tokenTransferProxy: TokenTransferProxyContract;
|
||||||
let multiSig: Web3.ContractInstance;
|
let multiSig: MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract;
|
||||||
let multiSigWrapper: MultiSigWrapper;
|
let multiSigWrapper: MultiSigWrapper;
|
||||||
|
|
||||||
let validDestination: string;
|
let validDestination: string;
|
||||||
@ -45,20 +48,20 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
owners = [accounts[0], accounts[1]];
|
owners = [accounts[0], accounts[1]];
|
||||||
[authorizedAddress, unauthorizedAddress] = accounts;
|
[authorizedAddress, unauthorizedAddress] = accounts;
|
||||||
const initialOwner = accounts[0];
|
const initialOwner = accounts[0];
|
||||||
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
||||||
await tokenTransferProxy.addAuthorizedAddress(authorizedAddress, {
|
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
|
||||||
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, {
|
||||||
from: initialOwner,
|
from: initialOwner,
|
||||||
});
|
});
|
||||||
multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, [
|
const multiSigInstance = await deployer.deployAsync(
|
||||||
owners,
|
ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
|
||||||
requiredApprovals,
|
[owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address],
|
||||||
SECONDS_TIME_LOCKED,
|
);
|
||||||
tokenTransferProxy.address,
|
multiSig = new MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract(multiSigInstance);
|
||||||
]);
|
await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, {
|
||||||
await tokenTransferProxy.transferOwnership(multiSig.address, {
|
|
||||||
from: initialOwner,
|
from: initialOwner,
|
||||||
});
|
});
|
||||||
multiSigWrapper = new MultiSigWrapper(multiSig);
|
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
|
||||||
validDestination = tokenTransferProxy.address;
|
validDestination = tokenTransferProxy.address;
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -71,12 +74,12 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
describe('isFunctionRemoveAuthorizedAddress', () => {
|
describe('isFunctionRemoveAuthorizedAddress', () => {
|
||||||
it('should throw if data is not for removeAuthorizedAddress', async () => {
|
it('should throw if data is not for removeAuthorizedAddress', async () => {
|
||||||
const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
|
const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
|
||||||
return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)).to.be.rejectedWith(constants.REVERT);
|
return expect(multiSig.isFunctionRemoveAuthorizedAddress(data)).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true if data is for removeAuthorizedAddress', async () => {
|
it('should return true if data is for removeAuthorizedAddress', async () => {
|
||||||
const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
|
const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
|
||||||
const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data);
|
const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress(data);
|
||||||
expect(isFunctionRemoveAuthorizedAddress).to.be.true();
|
expect(isFunctionRemoveAuthorizedAddress).to.be.true();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -91,11 +94,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId.toString();
|
const txId = log.args.transactionId;
|
||||||
|
|
||||||
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if tx destination is not the tokenTransferProxy', async () => {
|
it('should throw if tx destination is not the tokenTransferProxy', async () => {
|
||||||
@ -109,14 +112,14 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const txHash = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams);
|
const txHash = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams);
|
||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId.toString();
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction(txId, { from: owners[1] });
|
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
const isConfirmed = await multiSig.isConfirmed.call(txId);
|
const isConfirmed = await multiSig.isConfirmed(txId);
|
||||||
expect(isConfirmed).to.be.true();
|
expect(isConfirmed).to.be.true();
|
||||||
|
|
||||||
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if tx data is not for removeAuthorizedAddress', async () => {
|
it('should throw if tx data is not for removeAuthorizedAddress', async () => {
|
||||||
@ -128,14 +131,14 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId.toString();
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction(txId, { from: owners[1] });
|
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
const isConfirmed = await multiSig.isConfirmed.call(txId);
|
const isConfirmed = await multiSig.isConfirmed(txId);
|
||||||
expect(isConfirmed).to.be.true();
|
expect(isConfirmed).to.be.true();
|
||||||
|
|
||||||
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => {
|
it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => {
|
||||||
@ -147,12 +150,12 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId.toString();
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction(txId, { from: owners[1] });
|
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
const isConfirmed = await multiSig.isConfirmed.call(txId);
|
const isConfirmed = await multiSig.isConfirmed(txId);
|
||||||
expect(isConfirmed).to.be.true();
|
expect(isConfirmed).to.be.true();
|
||||||
await multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] });
|
await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
const isAuthorized = await tokenTransferProxy.authorized.call(authorizedAddress);
|
const isAuthorized = await tokenTransferProxy.authorized(authorizedAddress);
|
||||||
expect(isAuthorized).to.be.false();
|
expect(isAuthorized).to.be.false();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -165,17 +168,17 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
|
||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId.toString();
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction(txId, { from: owners[1] });
|
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
const isConfirmed = await multiSig.isConfirmed(txId);
|
const isConfirmed = await multiSig.isConfirmed(txId);
|
||||||
expect(isConfirmed).to.be.true();
|
expect(isConfirmed).to.be.true();
|
||||||
await multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] });
|
await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
|
||||||
const tx = await multiSig.transactions(txId);
|
const tx = await multiSig.transactions(txId);
|
||||||
const isExecuted = tx[3];
|
const isExecuted = tx[3];
|
||||||
expect(isExecuted).to.be.true();
|
expect(isExecuted).to.be.true();
|
||||||
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { ZeroEx } from '0x.js';
|
import { ZeroEx } from '0x.js';
|
||||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import ethUtil = require('ethereumjs-util');
|
import ethUtil = require('ethereumjs-util');
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { TokenRegistryContract } from '../src/contract_wrappers/generated/token_registry';
|
||||||
import { constants } from '../util/constants';
|
import { constants } from '../util/constants';
|
||||||
import { TokenRegWrapper } from '../util/token_registry_wrapper';
|
import { TokenRegWrapper } from '../util/token_registry_wrapper';
|
||||||
import { ContractName } from '../util/types';
|
import { ContractName } from '../util/types';
|
||||||
@ -22,13 +24,14 @@ const blockchainLifecycle = new BlockchainLifecycle();
|
|||||||
describe('TokenRegistry', () => {
|
describe('TokenRegistry', () => {
|
||||||
let owner: string;
|
let owner: string;
|
||||||
let notOwner: string;
|
let notOwner: string;
|
||||||
let tokenReg: Web3.ContractInstance;
|
let tokenReg: TokenRegistryContract;
|
||||||
let tokenRegWrapper: TokenRegWrapper;
|
let tokenRegWrapper: TokenRegWrapper;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
owner = accounts[0];
|
owner = accounts[0];
|
||||||
notOwner = accounts[1];
|
notOwner = accounts[1];
|
||||||
tokenReg = await deployer.deployAsync(ContractName.TokenRegistry);
|
const tokenRegInstance = await deployer.deployAsync(ContractName.TokenRegistry);
|
||||||
|
tokenReg = new TokenRegistryContract(tokenRegInstance);
|
||||||
tokenRegWrapper = new TokenRegWrapper(tokenReg);
|
tokenRegWrapper = new TokenRegWrapper(tokenReg);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -132,12 +135,12 @@ describe('TokenRegistry', () => {
|
|||||||
describe('setTokenName', () => {
|
describe('setTokenName', () => {
|
||||||
it('should throw when not called by owner', async () => {
|
it('should throw when not called by owner', async () => {
|
||||||
return expect(
|
return expect(
|
||||||
tokenReg.setTokenName(token1.address, token2.name, { from: notOwner }),
|
tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { from: notOwner }),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change the token name when called by owner', async () => {
|
it('should change the token name when called by owner', async () => {
|
||||||
await tokenReg.setTokenName(token1.address, token2.name, {
|
await tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const [newData, oldData] = await Promise.all([
|
const [newData, oldData] = await Promise.all([
|
||||||
@ -154,14 +157,14 @@ describe('TokenRegistry', () => {
|
|||||||
it('should throw if the name already exists', async () => {
|
it('should throw if the name already exists', async () => {
|
||||||
await tokenRegWrapper.addTokenAsync(token2, owner);
|
await tokenRegWrapper.addTokenAsync(token2, owner);
|
||||||
|
|
||||||
return expect(tokenReg.setTokenName(token1.address, token2.name, { from: owner })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { from: owner }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if token does not exist', async () => {
|
it('should throw if token does not exist', async () => {
|
||||||
return expect(
|
return expect(
|
||||||
tokenReg.setTokenName(nullToken.address, token2.name, { from: owner }),
|
tokenReg.setTokenName.sendTransactionAsync(nullToken.address, token2.name, { from: owner }),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -169,14 +172,14 @@ describe('TokenRegistry', () => {
|
|||||||
describe('setTokenSymbol', () => {
|
describe('setTokenSymbol', () => {
|
||||||
it('should throw when not called by owner', async () => {
|
it('should throw when not called by owner', async () => {
|
||||||
return expect(
|
return expect(
|
||||||
tokenReg.setTokenSymbol(token1.address, token2.symbol, {
|
tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, {
|
||||||
from: notOwner,
|
from: notOwner,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change the token symbol when called by owner', async () => {
|
it('should change the token symbol when called by owner', async () => {
|
||||||
await tokenReg.setTokenSymbol(token1.address, token2.symbol, { from: owner });
|
await tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, { from: owner });
|
||||||
const [newData, oldData] = await Promise.all([
|
const [newData, oldData] = await Promise.all([
|
||||||
tokenRegWrapper.getTokenBySymbolAsync(token2.symbol),
|
tokenRegWrapper.getTokenBySymbolAsync(token2.symbol),
|
||||||
tokenRegWrapper.getTokenBySymbolAsync(token1.symbol),
|
tokenRegWrapper.getTokenBySymbolAsync(token1.symbol),
|
||||||
@ -192,7 +195,7 @@ describe('TokenRegistry', () => {
|
|||||||
await tokenRegWrapper.addTokenAsync(token2, owner);
|
await tokenRegWrapper.addTokenAsync(token2, owner);
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
tokenReg.setTokenSymbol(token1.address, token2.symbol, {
|
tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, {
|
||||||
from: owner,
|
from: owner,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
@ -200,7 +203,7 @@ describe('TokenRegistry', () => {
|
|||||||
|
|
||||||
it('should throw if token does not exist', async () => {
|
it('should throw if token does not exist', async () => {
|
||||||
return expect(
|
return expect(
|
||||||
tokenReg.setTokenSymbol(nullToken.address, token2.symbol, {
|
tokenReg.setTokenSymbol.sendTransactionAsync(nullToken.address, token2.symbol, {
|
||||||
from: owner,
|
from: owner,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
@ -209,15 +212,15 @@ describe('TokenRegistry', () => {
|
|||||||
|
|
||||||
describe('removeToken', () => {
|
describe('removeToken', () => {
|
||||||
it('should throw if not called by owner', async () => {
|
it('should throw if not called by owner', async () => {
|
||||||
const index = 0;
|
const index = new BigNumber(0);
|
||||||
return expect(tokenReg.removeToken(token1.address, index, { from: notOwner })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
tokenReg.removeToken.sendTransactionAsync(token1.address, index, { from: notOwner }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove token metadata when called by owner', async () => {
|
it('should remove token metadata when called by owner', async () => {
|
||||||
const index = 0;
|
const index = new BigNumber(0);
|
||||||
await tokenReg.removeToken(token1.address, index, {
|
await tokenReg.removeToken.sendTransactionAsync(token1.address, index, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address);
|
const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address);
|
||||||
@ -225,18 +228,18 @@ describe('TokenRegistry', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if token does not exist', async () => {
|
it('should throw if token does not exist', async () => {
|
||||||
const index = 0;
|
const index = new BigNumber(0);
|
||||||
return expect(tokenReg.removeToken(nullToken.address, index, { from: owner })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
tokenReg.removeToken.sendTransactionAsync(nullToken.address, index, { from: owner }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if token at given index does not match address', async () => {
|
it('should throw if token at given index does not match address', async () => {
|
||||||
await tokenRegWrapper.addTokenAsync(token2, owner);
|
await tokenRegWrapper.addTokenAsync(token2, owner);
|
||||||
const incorrectIndex = 0;
|
const incorrectIndex = new BigNumber(0);
|
||||||
return expect(tokenReg.removeToken(token2.address, incorrectIndex, { from: owner })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
tokenReg.removeToken.sendTransactionAsync(token2.address, incorrectIndex, { from: owner }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
|
||||||
import { constants } from '../../util/constants';
|
import { constants } from '../../util/constants';
|
||||||
import { ContractName } from '../../util/types';
|
import { ContractName } from '../../util/types';
|
||||||
import { chaiSetup } from '../utils/chai_setup';
|
import { chaiSetup } from '../utils/chai_setup';
|
||||||
@ -18,12 +19,13 @@ describe('TokenTransferProxy', () => {
|
|||||||
let owner: string;
|
let owner: string;
|
||||||
let notOwner: string;
|
let notOwner: string;
|
||||||
let address: string;
|
let address: string;
|
||||||
let tokenTransferProxy: Web3.ContractInstance;
|
let tokenTransferProxy: TokenTransferProxyContract;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
owner = address = accounts[0];
|
owner = address = accounts[0];
|
||||||
notOwner = accounts[1];
|
notOwner = accounts[1];
|
||||||
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
||||||
|
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
await blockchainLifecycle.startAsync();
|
||||||
@ -33,36 +35,36 @@ describe('TokenTransferProxy', () => {
|
|||||||
});
|
});
|
||||||
describe('addAuthorizedAddress', () => {
|
describe('addAuthorizedAddress', () => {
|
||||||
it('should throw if not called by owner', async () => {
|
it('should throw if not called by owner', async () => {
|
||||||
return expect(tokenTransferProxy.addAuthorizedAddress(notOwner, { from: notOwner })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(notOwner, { from: notOwner }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
it('should allow owner to add an authorized address', async () => {
|
it('should allow owner to add an authorized address', async () => {
|
||||||
await tokenTransferProxy.addAuthorizedAddress(address, { from: owner });
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
|
||||||
const isAuthorized = await tokenTransferProxy.authorized(address);
|
const isAuthorized = await tokenTransferProxy.authorized(address);
|
||||||
expect(isAuthorized).to.be.true();
|
expect(isAuthorized).to.be.true();
|
||||||
});
|
});
|
||||||
it('should throw if owner attempts to authorize a duplicate address', async () => {
|
it('should throw if owner attempts to authorize a duplicate address', async () => {
|
||||||
await tokenTransferProxy.addAuthorizedAddress(address, { from: owner });
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
|
||||||
return expect(tokenTransferProxy.addAuthorizedAddress(address, { from: owner })).to.be.rejectedWith(
|
return expect(
|
||||||
constants.REVERT,
|
tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
|
||||||
);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeAuthorizedAddress', () => {
|
describe('removeAuthorizedAddress', () => {
|
||||||
it('should throw if not called by owner', async () => {
|
it('should throw if not called by owner', async () => {
|
||||||
await tokenTransferProxy.addAuthorizedAddress(address, { from: owner });
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
|
||||||
return expect(
|
return expect(
|
||||||
tokenTransferProxy.removeAuthorizedAddress(address, {
|
tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: notOwner,
|
from: notOwner,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow owner to remove an authorized address', async () => {
|
it('should allow owner to remove an authorized address', async () => {
|
||||||
await tokenTransferProxy.addAuthorizedAddress(address, { from: owner });
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
|
||||||
await tokenTransferProxy.removeAuthorizedAddress(address, {
|
await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const isAuthorized = await tokenTransferProxy.authorized(address);
|
const isAuthorized = await tokenTransferProxy.authorized(address);
|
||||||
@ -71,7 +73,7 @@ describe('TokenTransferProxy', () => {
|
|||||||
|
|
||||||
it('should throw if owner attempts to remove an address that is not authorized', async () => {
|
it('should throw if owner attempts to remove an address that is not authorized', async () => {
|
||||||
return expect(
|
return expect(
|
||||||
tokenTransferProxy.removeAuthorizedAddress(address, {
|
tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
@ -82,14 +84,14 @@ describe('TokenTransferProxy', () => {
|
|||||||
it('should return all authorized addresses', async () => {
|
it('should return all authorized addresses', async () => {
|
||||||
const initial = await tokenTransferProxy.getAuthorizedAddresses();
|
const initial = await tokenTransferProxy.getAuthorizedAddresses();
|
||||||
expect(initial).to.have.length(0);
|
expect(initial).to.have.length(0);
|
||||||
await tokenTransferProxy.addAuthorizedAddress(address, {
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const afterAdd = await tokenTransferProxy.getAuthorizedAddresses();
|
const afterAdd = await tokenTransferProxy.getAuthorizedAddresses();
|
||||||
expect(afterAdd).to.have.length(1);
|
expect(afterAdd).to.have.length(1);
|
||||||
expect(afterAdd).to.include(address);
|
expect(afterAdd).to.include(address);
|
||||||
|
|
||||||
await tokenTransferProxy.removeAuthorizedAddress(address, {
|
await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const afterRemove = await tokenTransferProxy.getAuthorizedAddresses();
|
const afterRemove = await tokenTransferProxy.getAuthorizedAddresses();
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
||||||
|
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
|
||||||
import { Balances } from '../../util/balances';
|
import { Balances } from '../../util/balances';
|
||||||
import { constants } from '../../util/constants';
|
import { constants } from '../../util/constants';
|
||||||
import { ContractName } from '../../util/types';
|
import { ContractName } from '../../util/types';
|
||||||
@ -19,29 +22,31 @@ describe('TokenTransferProxy', () => {
|
|||||||
let accounts: string[];
|
let accounts: string[];
|
||||||
let owner: string;
|
let owner: string;
|
||||||
let notAuthorized: string;
|
let notAuthorized: string;
|
||||||
const INIT_BAL = 100000000;
|
const INIT_BAL = new BigNumber(100000000);
|
||||||
const INIT_ALLOW = 100000000;
|
const INIT_ALLOW = new BigNumber(100000000);
|
||||||
|
|
||||||
let tokenTransferProxy: Web3.ContractInstance;
|
let tokenTransferProxy: TokenTransferProxyContract;
|
||||||
let rep: Web3.ContractInstance;
|
let rep: DummyTokenContract;
|
||||||
let dmyBalances: Balances;
|
let dmyBalances: Balances;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
accounts = await web3Wrapper.getAvailableAddressesAsync();
|
accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
owner = notAuthorized = accounts[0];
|
owner = notAuthorized = accounts[0];
|
||||||
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
||||||
rep = await deployer.deployAsync(ContractName.DummyToken);
|
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
|
||||||
|
const repInstance = await deployer.deployAsync(ContractName.DummyToken);
|
||||||
|
rep = new DummyTokenContract(repInstance);
|
||||||
|
|
||||||
dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
|
dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
rep.approve(tokenTransferProxy.address, INIT_ALLOW, {
|
rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, {
|
||||||
from: accounts[0],
|
from: accounts[0],
|
||||||
}),
|
}),
|
||||||
rep.setBalance(accounts[0], INIT_BAL, { from: owner }),
|
rep.setBalance.sendTransactionAsync(accounts[0], INIT_BAL, { from: owner }),
|
||||||
rep.approve(tokenTransferProxy.address, INIT_ALLOW, {
|
rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, {
|
||||||
from: accounts[1],
|
from: accounts[1],
|
||||||
}),
|
}),
|
||||||
rep.setBalance(accounts[1], INIT_BAL, { from: owner }),
|
rep.setBalance.sendTransactionAsync(accounts[1], INIT_BAL, { from: owner }),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -54,20 +59,34 @@ describe('TokenTransferProxy', () => {
|
|||||||
describe('transferFrom', () => {
|
describe('transferFrom', () => {
|
||||||
it('should throw when called by an unauthorized address', async () => {
|
it('should throw when called by an unauthorized address', async () => {
|
||||||
expect(
|
expect(
|
||||||
tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], 1000, { from: notAuthorized }),
|
tokenTransferProxy.transferFrom.sendTransactionAsync(
|
||||||
|
rep.address,
|
||||||
|
accounts[0],
|
||||||
|
accounts[1],
|
||||||
|
new BigNumber(1000),
|
||||||
|
{
|
||||||
|
from: notAuthorized,
|
||||||
|
},
|
||||||
|
),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow an authorized address to transfer', async () => {
|
it('should allow an authorized address to transfer', async () => {
|
||||||
const balances = await dmyBalances.getAsync();
|
const balances = await dmyBalances.getAsync();
|
||||||
|
|
||||||
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, {
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(notAuthorized, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const transferAmt = 10000;
|
const transferAmt = new BigNumber(10000);
|
||||||
await tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], transferAmt, {
|
await tokenTransferProxy.transferFrom.sendTransactionAsync(
|
||||||
from: notAuthorized,
|
rep.address,
|
||||||
});
|
accounts[0],
|
||||||
|
accounts[1],
|
||||||
|
transferAmt,
|
||||||
|
{
|
||||||
|
from: notAuthorized,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const newBalances = await dmyBalances.getAsync();
|
const newBalances = await dmyBalances.getAsync();
|
||||||
expect(newBalances[accounts[0]][rep.address]).to.be.bignumber.equal(
|
expect(newBalances[accounts[0]][rep.address]).to.be.bignumber.equal(
|
||||||
|
@ -5,6 +5,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { DummyTokenContract } from '../src/contract_wrappers/generated/dummy_token';
|
||||||
import { constants } from '../util/constants';
|
import { constants } from '../util/constants';
|
||||||
import { ContractName } from '../util/types';
|
import { ContractName } from '../util/types';
|
||||||
|
|
||||||
@ -27,14 +28,15 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
|
|
||||||
const MAX_MINT_VALUE = new BigNumber(100000000000000000000);
|
const MAX_MINT_VALUE = new BigNumber(100000000000000000000);
|
||||||
let tokenAddress: string;
|
let tokenAddress: string;
|
||||||
let token: Web3.ContractInstance;
|
let token: DummyTokenContract;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
owner = accounts[0];
|
owner = accounts[0];
|
||||||
spender = accounts[1];
|
spender = accounts[1];
|
||||||
token = await deployer.deployAsync(ContractName.DummyToken);
|
const tokenInstance = await deployer.deployAsync(ContractName.DummyToken);
|
||||||
await token.mint(MAX_MINT_VALUE, { from: owner });
|
token = new DummyTokenContract(tokenInstance);
|
||||||
|
await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner });
|
||||||
tokenAddress = token.address;
|
tokenAddress = token.address;
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -47,7 +49,7 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
it('should throw if owner has insufficient balance', async () => {
|
it('should throw if owner has insufficient balance', async () => {
|
||||||
const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
|
const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
|
||||||
const amountToTransfer = ownerBalance.plus(1);
|
const amountToTransfer = ownerBalance.plus(1);
|
||||||
return expect(token.transfer.call(spender, amountToTransfer, { from: owner })).to.be.rejectedWith(
|
return expect(token.transfer.callAsync(spender, amountToTransfer, { from: owner })).to.be.rejectedWith(
|
||||||
constants.REVERT,
|
constants.REVERT,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -67,7 +69,7 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return true on a 0 value transfer', async () => {
|
it('should return true on a 0 value transfer', async () => {
|
||||||
const didReturnTrue = await token.transfer.call(spender, 0, {
|
const didReturnTrue = await token.transfer.callAsync(spender, new BigNumber(0), {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
expect(didReturnTrue).to.be.true();
|
expect(didReturnTrue).to.be.true();
|
||||||
@ -80,7 +82,7 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
const amountToTransfer = ownerBalance.plus(1);
|
const amountToTransfer = ownerBalance.plus(1);
|
||||||
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer);
|
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer);
|
||||||
return expect(
|
return expect(
|
||||||
token.transferFrom.call(owner, spender, amountToTransfer, {
|
token.transferFrom.callAsync(owner, spender, amountToTransfer, {
|
||||||
from: spender,
|
from: spender,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
@ -95,15 +97,17 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
expect(spenderAllowanceIsInsufficient).to.be.true();
|
expect(spenderAllowanceIsInsufficient).to.be.true();
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
token.transferFrom.call(owner, spender, amountToTransfer, {
|
token.transferFrom.callAsync(owner, spender, amountToTransfer, {
|
||||||
from: spender,
|
from: spender,
|
||||||
}),
|
}),
|
||||||
).to.be.rejectedWith(constants.REVERT);
|
).to.be.rejectedWith(constants.REVERT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true on a 0 value transfer', async () => {
|
it('should return true on a 0 value transfer', async () => {
|
||||||
const amountToTransfer = 0;
|
const amountToTransfer = new BigNumber(0);
|
||||||
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, { from: spender });
|
const didReturnTrue = await token.transferFrom.callAsync(owner, spender, amountToTransfer, {
|
||||||
|
from: spender,
|
||||||
|
});
|
||||||
expect(didReturnTrue).to.be.true();
|
expect(didReturnTrue).to.be.true();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import * as path from 'path';
|
|||||||
import { constants } from '../../util/constants';
|
import { constants } from '../../util/constants';
|
||||||
|
|
||||||
const deployerOpts = {
|
const deployerOpts = {
|
||||||
artifactsDir: path.resolve('artifacts'),
|
artifactsDir: path.resolve('src', 'artifacts'),
|
||||||
jsonrpcPort: devConstants.RPC_PORT,
|
jsonrpcPort: devConstants.RPC_PORT,
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
defaults: {
|
defaults: {
|
||||||
|
@ -5,6 +5,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { ZRXTokenContract } from '../src/contract_wrappers/generated/zrx_token';
|
||||||
import { constants } from '../util/constants';
|
import { constants } from '../util/constants';
|
||||||
import { ContractName } from '../util/types';
|
import { ContractName } from '../util/types';
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ describe('ZRXToken', () => {
|
|||||||
|
|
||||||
let MAX_UINT: BigNumber;
|
let MAX_UINT: BigNumber;
|
||||||
|
|
||||||
let zrx: Web3.ContractInstance;
|
let zrx: ZRXTokenContract;
|
||||||
let zrxAddress: string;
|
let zrxAddress: string;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
@ -34,7 +35,8 @@ describe('ZRXToken', () => {
|
|||||||
zeroEx = new ZeroEx(web3.currentProvider, {
|
zeroEx = new ZeroEx(web3.currentProvider, {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
});
|
});
|
||||||
zrx = await deployer.deployAsync(ContractName.ZRXToken);
|
const zrxInstance = await deployer.deployAsync(ContractName.ZRXToken);
|
||||||
|
zrx = new ZRXTokenContract(zrxInstance);
|
||||||
zrxAddress = zrx.address;
|
zrxAddress = zrx.address;
|
||||||
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||||
});
|
});
|
||||||
@ -94,7 +96,7 @@ describe('ZRXToken', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return true on a 0 value transfer', async () => {
|
it('should return true on a 0 value transfer', async () => {
|
||||||
const didReturnTrue = await zrx.transfer.call(spender, 0, {
|
const didReturnTrue = await zrx.transfer.callAsync(spender, new BigNumber(0), {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
expect(didReturnTrue).to.be.true();
|
expect(didReturnTrue).to.be.true();
|
||||||
@ -108,7 +110,7 @@ describe('ZRXToken', () => {
|
|||||||
await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer, {
|
await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer, {
|
||||||
gasLimit: constants.MAX_TOKEN_APPROVE_GAS,
|
gasLimit: constants.MAX_TOKEN_APPROVE_GAS,
|
||||||
});
|
});
|
||||||
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, { from: spender });
|
const didReturnTrue = await zrx.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender });
|
||||||
expect(didReturnTrue).to.be.false();
|
expect(didReturnTrue).to.be.false();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -120,13 +122,13 @@ describe('ZRXToken', () => {
|
|||||||
const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
|
const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
|
||||||
expect(spenderAllowanceIsInsufficient).to.be.true();
|
expect(spenderAllowanceIsInsufficient).to.be.true();
|
||||||
|
|
||||||
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, { from: spender });
|
const didReturnTrue = await zrx.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender });
|
||||||
expect(didReturnTrue).to.be.false();
|
expect(didReturnTrue).to.be.false();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true on a 0 value transfer', async () => {
|
it('should return true on a 0 value transfer', async () => {
|
||||||
const amountToTransfer = 0;
|
const amountToTransfer = new BigNumber(0);
|
||||||
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, { from: spender });
|
const didReturnTrue = await zrx.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender });
|
||||||
expect(didReturnTrue).to.be.true();
|
expect(didReturnTrue).to.be.true();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"outDir": "lib",
|
"outDir": "lib",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"declaration": false,
|
"declaration": false,
|
||||||
|
"noImplicitThis": false,
|
||||||
"allowJs": true
|
"allowJs": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
@ -14,10 +15,10 @@
|
|||||||
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
||||||
"../../node_modules/types-bn/index.d.ts",
|
"../../node_modules/types-bn/index.d.ts",
|
||||||
"./globals.d.ts",
|
"./globals.d.ts",
|
||||||
|
"./src/**/*",
|
||||||
"./util/**/*",
|
"./util/**/*",
|
||||||
"./test/**/*",
|
"./test/**/*",
|
||||||
"./migrations/**/*",
|
"./migrations/**/*"
|
||||||
"./deploy/**/*"
|
|
||||||
],
|
],
|
||||||
"exclude": ["./deploy/solc/solc_bin"]
|
"exclude": ["./deploy/solc/solc_bin"]
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import * as DummyTokenArtifact from '../artifacts/DummyToken.json';
|
import * as DummyTokenArtifact from '../src/artifacts/DummyToken.json';
|
||||||
import * as ExchangeArtifact from '../artifacts/Exchange.json';
|
import * as ExchangeArtifact from '../src/artifacts/Exchange.json';
|
||||||
import * as MaliciousTokenArtifact from '../artifacts/MaliciousToken.json';
|
import * as MaliciousTokenArtifact from '../src/artifacts/MaliciousToken.json';
|
||||||
import * as MultiSigWalletWithTimeLockArtifact from '../artifacts/MultiSigWalletWithTimeLock.json';
|
import * as MultiSigWalletWithTimeLockArtifact from '../src/artifacts/MultiSigWalletWithTimeLock.json';
|
||||||
import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact from '../artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json';
|
import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact from '../src/artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json';
|
||||||
import * as TokenArtifact from '../artifacts/Token.json';
|
import * as TokenArtifact from '../src/artifacts/Token.json';
|
||||||
import * as TokenRegistryArtifact from '../artifacts/TokenRegistry.json';
|
import * as TokenRegistryArtifact from '../src/artifacts/TokenRegistry.json';
|
||||||
import * as TokenTransferProxyArtifact from '../artifacts/TokenTransferProxy.json';
|
import * as TokenTransferProxyArtifact from '../src/artifacts/TokenTransferProxy.json';
|
||||||
import * as EtherTokenArtifact from '../artifacts/WETH9.json';
|
import * as EtherTokenArtifact from '../src/artifacts/WETH9.json';
|
||||||
import * as ZRXArtifact from '../artifacts/ZRXToken.json';
|
import * as ZRXArtifact from '../src/artifacts/ZRXToken.json';
|
||||||
|
|
||||||
import { Artifact } from './types';
|
import { Artifact } from './types';
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@ import { BigNumber } from '@0xproject/utils';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { DummyTokenContract } from '../src/contract_wrappers/generated/dummy_token';
|
||||||
|
|
||||||
import { BalancesByOwner } from './types';
|
import { BalancesByOwner } from './types';
|
||||||
|
|
||||||
export class Balances {
|
export class Balances {
|
||||||
private _tokenContractInstances: Web3.ContractInstance[];
|
private _tokenContractInstances: DummyTokenContract[];
|
||||||
private _ownerAddresses: string[];
|
private _ownerAddresses: string[];
|
||||||
constructor(tokenContractInstances: Web3.ContractInstance[], ownerAddresses: string[]) {
|
constructor(tokenContractInstances: DummyTokenContract[], ownerAddresses: string[]) {
|
||||||
this._tokenContractInstances = tokenContractInstances;
|
this._tokenContractInstances = tokenContractInstances;
|
||||||
this._ownerAddresses = ownerAddresses;
|
this._ownerAddresses = ownerAddresses;
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,16 @@ import { BigNumber } from '@0xproject/utils';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { ExchangeContract } from '../src/contract_wrappers/generated/exchange';
|
||||||
|
|
||||||
import { formatters } from './formatters';
|
import { formatters } from './formatters';
|
||||||
import { Order } from './order';
|
import { Order } from './order';
|
||||||
|
|
||||||
export class ExchangeWrapper {
|
export class ExchangeWrapper {
|
||||||
private _exchange: Web3.ContractInstance;
|
private _exchange: ExchangeContract;
|
||||||
private _zeroEx: ZeroEx;
|
private _zeroEx: ZeroEx;
|
||||||
constructor(exchangeContractInstance: Web3.ContractInstance, zeroEx: ZeroEx) {
|
constructor(exchangeContract: ExchangeContract, zeroEx: ZeroEx) {
|
||||||
this._exchange = exchangeContractInstance;
|
this._exchange = exchangeContract;
|
||||||
this._zeroEx = zeroEx;
|
this._zeroEx = zeroEx;
|
||||||
}
|
}
|
||||||
public async fillOrderAsync(
|
public async fillOrderAsync(
|
||||||
@ -23,14 +25,14 @@ export class ExchangeWrapper {
|
|||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
|
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
|
||||||
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
|
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
|
||||||
const txHash = await this._exchange.fillOrder(
|
const txHash = await this._exchange.fillOrder.sendTransactionAsync(
|
||||||
params.orderAddresses,
|
params.orderAddresses,
|
||||||
params.orderValues,
|
params.orderValues,
|
||||||
params.fillTakerTokenAmount,
|
params.fillTakerTokenAmount,
|
||||||
params.shouldThrowOnInsufficientBalanceOrAllowance,
|
params.shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
params.v,
|
params.v as number,
|
||||||
params.r,
|
params.r as string,
|
||||||
params.s,
|
params.s as string,
|
||||||
{ from },
|
{ from },
|
||||||
);
|
);
|
||||||
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
|
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
@ -44,7 +46,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { cancelTakerTokenAmount?: BigNumber } = {},
|
opts: { cancelTakerTokenAmount?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = order.createCancel(opts.cancelTakerTokenAmount);
|
const params = order.createCancel(opts.cancelTakerTokenAmount);
|
||||||
const txHash = await this._exchange.cancelOrder(
|
const txHash = await this._exchange.cancelOrder.sendTransactionAsync(
|
||||||
params.orderAddresses,
|
params.orderAddresses,
|
||||||
params.orderValues,
|
params.orderValues,
|
||||||
params.cancelTakerTokenAmount,
|
params.cancelTakerTokenAmount,
|
||||||
@ -62,13 +64,13 @@ export class ExchangeWrapper {
|
|||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||||
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
|
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
|
||||||
const txHash = await this._exchange.fillOrKillOrder(
|
const txHash = await this._exchange.fillOrKillOrder.sendTransactionAsync(
|
||||||
params.orderAddresses,
|
params.orderAddresses,
|
||||||
params.orderValues,
|
params.orderValues,
|
||||||
params.fillTakerTokenAmount,
|
params.fillTakerTokenAmount,
|
||||||
params.v,
|
params.v as number,
|
||||||
params.r,
|
params.r as string,
|
||||||
params.s,
|
params.s as string,
|
||||||
{ from },
|
{ from },
|
||||||
);
|
);
|
||||||
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
|
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
@ -90,7 +92,7 @@ export class ExchangeWrapper {
|
|||||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
opts.fillTakerTokenAmounts,
|
opts.fillTakerTokenAmounts,
|
||||||
);
|
);
|
||||||
const txHash = await this._exchange.batchFillOrders(
|
const txHash = await this._exchange.batchFillOrders.sendTransactionAsync(
|
||||||
params.orderAddresses,
|
params.orderAddresses,
|
||||||
params.orderValues,
|
params.orderValues,
|
||||||
params.fillTakerTokenAmounts,
|
params.fillTakerTokenAmounts,
|
||||||
@ -116,7 +118,7 @@ export class ExchangeWrapper {
|
|||||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
opts.fillTakerTokenAmounts,
|
opts.fillTakerTokenAmounts,
|
||||||
);
|
);
|
||||||
const txHash = await this._exchange.batchFillOrKillOrders(
|
const txHash = await this._exchange.batchFillOrKillOrders.sendTransactionAsync(
|
||||||
params.orderAddresses,
|
params.orderAddresses,
|
||||||
params.orderValues,
|
params.orderValues,
|
||||||
params.fillTakerTokenAmounts,
|
params.fillTakerTokenAmounts,
|
||||||
@ -141,7 +143,7 @@ export class ExchangeWrapper {
|
|||||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
opts.fillTakerTokenAmount,
|
opts.fillTakerTokenAmount,
|
||||||
);
|
);
|
||||||
const txHash = await this._exchange.fillOrdersUpTo(
|
const txHash = await this._exchange.fillOrdersUpTo.sendTransactionAsync(
|
||||||
params.orderAddresses,
|
params.orderAddresses,
|
||||||
params.orderValues,
|
params.orderValues,
|
||||||
params.fillTakerTokenAmount,
|
params.fillTakerTokenAmount,
|
||||||
@ -162,7 +164,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { cancelTakerTokenAmounts?: BigNumber[] } = {},
|
opts: { cancelTakerTokenAmounts?: BigNumber[] } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts);
|
const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts);
|
||||||
const txHash = await this._exchange.batchCancelOrders(
|
const txHash = await this._exchange.batchCancelOrders.sendTransactionAsync(
|
||||||
params.orderAddresses,
|
params.orderAddresses,
|
||||||
params.orderValues,
|
params.orderValues,
|
||||||
params.cancelTakerTokenAmounts,
|
params.cancelTakerTokenAmounts,
|
||||||
@ -182,10 +184,10 @@ export class ExchangeWrapper {
|
|||||||
public async isValidSignatureAsync(order: Order): Promise<boolean> {
|
public async isValidSignatureAsync(order: Order): Promise<boolean> {
|
||||||
const isValidSignature = await this._exchange.isValidSignature(
|
const isValidSignature = await this._exchange.isValidSignature(
|
||||||
order.params.maker,
|
order.params.maker,
|
||||||
order.params.orderHashHex,
|
order.params.orderHashHex as string,
|
||||||
order.params.v,
|
order.params.v as number,
|
||||||
order.params.r,
|
order.params.r as string,
|
||||||
order.params.s,
|
order.params.s as string,
|
||||||
);
|
);
|
||||||
return isValidSignature;
|
return isValidSignature;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import ABI = require('ethereumjs-abi');
|
import ABI = require('ethereumjs-abi');
|
||||||
import ethUtil = require('ethereumjs-util');
|
import ethUtil = require('ethereumjs-util');
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet';
|
||||||
|
|
||||||
import { TransactionDataParams } from './types';
|
import { TransactionDataParams } from './types';
|
||||||
|
|
||||||
export class MultiSigWrapper {
|
export class MultiSigWrapper {
|
||||||
private _multiSig: Web3.ContractInstance;
|
private _multiSig: MultiSigWalletContract;
|
||||||
public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) {
|
public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) {
|
||||||
const abiEntity = _.find(abi, { name }) as Web3.MethodAbi;
|
const abiEntity = _.find(abi, { name }) as Web3.MethodAbi;
|
||||||
if (_.isUndefined(abiEntity)) {
|
if (_.isUndefined(abiEntity)) {
|
||||||
@ -21,18 +24,18 @@ export class MultiSigWrapper {
|
|||||||
});
|
});
|
||||||
return funcSig + argsData.join('');
|
return funcSig + argsData.join('');
|
||||||
}
|
}
|
||||||
constructor(multiSigContractInstance: Web3.ContractInstance) {
|
constructor(multiSigContract: MultiSigWalletContract) {
|
||||||
this._multiSig = multiSigContractInstance;
|
this._multiSig = multiSigContract;
|
||||||
}
|
}
|
||||||
public async submitTransactionAsync(
|
public async submitTransactionAsync(
|
||||||
destination: string,
|
destination: string,
|
||||||
from: string,
|
from: string,
|
||||||
dataParams: TransactionDataParams,
|
dataParams: TransactionDataParams,
|
||||||
value: number = 0,
|
value: BigNumber = new BigNumber(0),
|
||||||
) {
|
) {
|
||||||
const { name, abi, args = [] } = dataParams;
|
const { name, abi, args = [] } = dataParams;
|
||||||
const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args);
|
const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args);
|
||||||
return this._multiSig.submitTransaction(destination, value, encoded, {
|
return this._multiSig.submitTransaction.sendTransactionAsync(destination, value, encoded, {
|
||||||
from,
|
from,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { TokenRegistryContract } from '../src/contract_wrappers/generated/token_registry';
|
||||||
|
|
||||||
import { Token } from './types';
|
import { Token } from './types';
|
||||||
|
|
||||||
export class TokenRegWrapper {
|
export class TokenRegWrapper {
|
||||||
private _tokenReg: Web3.ContractInstance;
|
private _tokenReg: TokenRegistryContract;
|
||||||
constructor(tokenRegContractInstance: Web3.ContractInstance) {
|
constructor(tokenRegContract: TokenRegistryContract) {
|
||||||
this._tokenReg = tokenRegContractInstance;
|
this._tokenReg = tokenRegContract;
|
||||||
}
|
}
|
||||||
public addTokenAsync(token: Token, from: string) {
|
public async addTokenAsync(token: Token, from: string) {
|
||||||
const tx = this._tokenReg.addToken(
|
const tx = this._tokenReg.addToken.sendTransactionAsync(
|
||||||
token.address,
|
token.address as string,
|
||||||
token.name,
|
token.name,
|
||||||
token.symbol,
|
token.symbol,
|
||||||
token.decimals,
|
token.decimals,
|
||||||
|
@ -44,11 +44,6 @@ export class RequestQueue {
|
|||||||
this._processNextRequestFireAndForgetAsync(recipientAddress);
|
this._processNextRequestFireAndForgetAsync(recipientAddress);
|
||||||
}, this._queueIntervalMs);
|
}, this._queueIntervalMs);
|
||||||
}
|
}
|
||||||
protected _stop() {
|
|
||||||
if (!_.isUndefined(this._queueIntervalId)) {
|
|
||||||
clearInterval(this._queueIntervalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// tslint:disable-next-line:prefer-function-over-method
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
protected async _processNextRequestFireAndForgetAsync(recipientAddress: string) {
|
protected async _processNextRequestFireAndForgetAsync(recipientAddress: string) {
|
||||||
throw new Error('Expected processNextRequestFireAndForgetAsync to be implemented by a subclass');
|
throw new Error('Expected processNextRequestFireAndForgetAsync to be implemented by a subclass');
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig",
|
"extends": "../../tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "lib"
|
"outDir": "lib",
|
||||||
|
"strictPropertyInitialization": false
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./src/ts/**/*",
|
"./src/ts/**/*",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user