switch @0x/contract-wrappers to generated wrappers (#2037)
* switch @0x/contract-wrappers to generated wrappers - remove TransactionEncoder - move TokenUtils to @0x/dev-utils - detailed changes in #2040
This commit is contained in:
parent
5ac7ff7084
commit
8ce390be3c
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -4,4 +4,5 @@
|
||||
*.svg linguist-generated=true
|
||||
packages/contract-artifacts/artifacts/*json linguist-generated=true
|
||||
packages/abi-gen-wrappers/src/generated-wrappers/*.ts linguist-generated=true
|
||||
packages/contract-wrappers/src/generated-wrappers/*.ts linguist-generated=true
|
||||
|
||||
|
@ -48,7 +48,6 @@
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^3.1.2",
|
||||
"@0x/contract-wrappers": "^10.1.0",
|
||||
"@0x/contracts-gen": "^1.0.12",
|
||||
"@0x/contracts-test-utils": "^3.1.12",
|
||||
"@0x/dev-utils": "^2.2.6",
|
||||
|
@ -47,7 +47,6 @@
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^3.1.2",
|
||||
"@0x/contract-wrappers": "^10.1.0",
|
||||
"@0x/contracts-gen": "^1.0.12",
|
||||
"@0x/contracts-test-utils": "^3.1.12",
|
||||
"@0x/dev-utils": "^2.2.6",
|
||||
|
@ -48,7 +48,7 @@
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^3.1.2",
|
||||
"@0x/contract-wrappers": "^10.1.0",
|
||||
"@0x/contract-wrappers": "10.1.0",
|
||||
"@0x/contracts-gen": "^1.0.12",
|
||||
"@0x/contracts-test-utils": "^3.1.12",
|
||||
"@0x/dev-utils": "^2.2.6",
|
||||
|
@ -50,7 +50,7 @@
|
||||
"config": {
|
||||
"contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-extensions @0x/contracts-multisig @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-coordinator @0x/contracts-dev-utils",
|
||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic",
|
||||
"packagesWithDocPages": "0x.js connect json-schemas subproviders web3-wrapper contract-wrappers order-utils order-watcher sol-compiler sol-coverage sol-profiler sol-trace ethereum-types asset-buyer migrations",
|
||||
"packagesWithDocPages": "0x.js connect json-schemas subproviders web3-wrapper order-utils order-watcher sol-compiler sol-coverage sol-profiler sol-trace ethereum-types asset-buyer migrations",
|
||||
"ignoreDependencyVersions": "@types/styled-components @types/node",
|
||||
"ignoreDependencyVersionsForPackage": "website instant dev-tools-pages"
|
||||
},
|
||||
|
@ -76,7 +76,7 @@
|
||||
"@0x/assert": "^2.1.2",
|
||||
"@0x/asset-swapper": "^1.0.0",
|
||||
"@0x/base-contract": "^5.3.0",
|
||||
"@0x/contract-wrappers": "^10.1.0",
|
||||
"@0x/contract-wrappers": "10.1.0",
|
||||
"@0x/order-utils": "^8.2.4",
|
||||
"@0x/order-watcher": "^4.0.16",
|
||||
"@0x/subproviders": "^5.0.0",
|
||||
|
@ -40,6 +40,13 @@ export {
|
||||
} from '@0x/contract-wrappers';
|
||||
|
||||
export {
|
||||
DutchAuctionContract,
|
||||
ERC20ProxyContract,
|
||||
ERC721ProxyContract,
|
||||
ExchangeContract,
|
||||
ForwarderContract,
|
||||
OrderValidatorContract,
|
||||
WETH9Contract,
|
||||
WETH9Events,
|
||||
WETH9WithdrawalEventArgs,
|
||||
WETH9ApprovalEventArgs,
|
||||
@ -102,15 +109,12 @@ export {
|
||||
ObjectMap,
|
||||
OrderRelevantState,
|
||||
Stats,
|
||||
DutchAuctionDetails,
|
||||
ZeroExTransaction,
|
||||
SignedZeroExTransaction,
|
||||
} from '@0x/types';
|
||||
|
||||
export {
|
||||
BlockParamLiteral,
|
||||
ContractAbi,
|
||||
BlockParam,
|
||||
LogWithDecodedArgs,
|
||||
ContractEventArg,
|
||||
SupportedProvider,
|
||||
|
@ -83,8 +83,10 @@ export class {{contractName}}Contract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return {{contractName}}Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, {{> params inputs=ctor.inputs}});
|
||||
}
|
||||
|
@ -3119,8 +3119,10 @@ export class AssetProxyOwnerContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return AssetProxyOwnerContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -1005,8 +1005,10 @@ export class CoordinatorContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return CoordinatorContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -298,8 +298,10 @@ export class CoordinatorRegistryContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return CoordinatorRegistryContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -1660,8 +1660,10 @@ export class DummyERC20TokenContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return DummyERC20TokenContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -2116,8 +2116,10 @@ export class DummyERC721TokenContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return DummyERC721TokenContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -795,8 +795,10 @@ export class DutchAuctionContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return DutchAuctionContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -1043,8 +1043,10 @@ export class ERC20ProxyContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return ERC20ProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -866,8 +866,10 @@ export class ERC20TokenContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return ERC20TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -1043,8 +1043,10 @@ export class ERC721ProxyContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return ERC721ProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -1428,8 +1428,10 @@ export class ERC721TokenContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return ERC721TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -119,8 +119,10 @@ export class EthBalanceCheckerContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return EthBalanceCheckerContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -6498,8 +6498,10 @@ export class ExchangeContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return ExchangeContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -1501,8 +1501,10 @@ export class ForwarderContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return ForwarderContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -1041,8 +1041,10 @@ export class IAssetProxyContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return IAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -137,8 +137,10 @@ export class IValidatorContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return IValidatorContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -127,8 +127,10 @@ export class IWalletContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return IWalletContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -1345,8 +1345,10 @@ export class MultiAssetProxyContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return MultiAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -1014,8 +1014,10 @@ export class OrderValidatorContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return OrderValidatorContract.deployAsync(
|
||||
bytecode,
|
||||
|
@ -1265,8 +1265,10 @@ export class WETH9Contract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return WETH9Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -1009,8 +1009,10 @@ export class ZRXTokenContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return ZRXTokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -2372,8 +2372,10 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return AbiGenDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -45,8 +45,10 @@ export class LibDummyContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return LibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -173,8 +173,10 @@ export class TestLibDummyContract extends BaseContract {
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return TestLibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@
|
||||
"dependencies": {
|
||||
"@0x/assert": "^2.1.2",
|
||||
"@0x/connect": "^5.0.15",
|
||||
"@0x/contract-wrappers": "^10.1.0",
|
||||
"@0x/contract-wrappers": "10.1.0",
|
||||
"@0x/json-schemas": "^3.1.12",
|
||||
"@0x/order-utils": "^8.2.4",
|
||||
"@0x/subproviders": "^5.0.0",
|
||||
|
@ -40,7 +40,7 @@
|
||||
"@0x/assert": "^2.1.2",
|
||||
"@0x/connect": "^5.0.15",
|
||||
"@0x/contract-addresses": "^3.0.2",
|
||||
"@0x/contract-wrappers": "^10.1.0",
|
||||
"@0x/contract-wrappers": "10.1.0",
|
||||
"@0x/dev-utils": "^2.2.6",
|
||||
"@0x/fill-scenarios": "^3.0.15",
|
||||
"@0x/json-schemas": "^3.1.12",
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
||||
import { tokenUtils } from '@0x/contract-wrappers/lib/test/utils/token_utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { MarketOperation, SignedOrder } from '@0x/types';
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
||||
import { tokenUtils } from '@0x/contract-wrappers/lib/test/utils/token_utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { MarketOperation, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
||||
import { tokenUtils } from '@0x/contract-wrappers/lib/test/utils/token_utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { MarketOperation, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "11.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Use @0x/abi-gen to generate wrappers. For a full list of changes, see https://github.com/0xProject/0x-monorepo/issues/2040",
|
||||
"pr": 2037
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "10.1.0",
|
||||
"changes": [
|
||||
|
@ -1,8 +1,6 @@
|
||||
## @0x/contract-wrappers
|
||||
|
||||
Smart TS wrappers for 0x smart contracts. The wrappers have simplified interfaces, perform client-side validation on transactions and throw helpful error messages.
|
||||
|
||||
### Read the [Documentation](https://0xproject.com/docs/0x.js).
|
||||
Wrappers for 0x smart contracts, generated using @0x/abi-gen.
|
||||
|
||||
## Installation
|
||||
|
||||
@ -14,7 +12,7 @@ npm install @0x/contract-wrappers --save
|
||||
|
||||
**Import**
|
||||
|
||||
```javascript
|
||||
```typescript
|
||||
import { ContractWrappers } from '@0x/contract-wrappers';
|
||||
```
|
||||
|
||||
@ -28,7 +26,7 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
@ -54,22 +52,6 @@ To build this package and all other monorepo packages that it depends on, run th
|
||||
PKG=@0x/contract-wrappers yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contract-wrappers yarn watch
|
||||
```
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
@ -87,3 +69,9 @@ yarn lint
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
Documentation for this package is generated by TypeDoc, using the Solidity source code for 0x contracts. Each contract corresponds to one global-level module, which contains relevant enums and interfaces for its events and structs. Most significantly, each module exports a class, `<ContractName>Contract`, e.g. `ExchangeContract`, which implements helper methods for all the functions defined in the corresponding contract.
|
||||
|
||||
A convention to note is that these contract-specific helper methods are defined as _object literals_, which are separated from methods in the generated documentation. Each contract method has a number of sub-methods, e.g. `sendTransactionAsync`, or `estimateGasAsync`, which are documented separately. This is an example of an expected method call signature: `exchangeContractInstance.fillOrder.sendTransactionAsync(...arguments)`.
|
||||
|
@ -1,7 +1,10 @@
|
||||
{
|
||||
"name": "@0x/contract-wrappers",
|
||||
"version": "10.1.0",
|
||||
"description": "Smart TS wrappers for 0x smart contracts",
|
||||
"version": "11.0.0",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "Wrappers for 0x smart contract wrappers generated using @0x/abi-gen",
|
||||
"keywords": [
|
||||
"0xproject",
|
||||
"ethereum",
|
||||
@ -10,34 +13,43 @@
|
||||
],
|
||||
"main": "lib/src/index.js",
|
||||
"types": "lib/src/index.d.ts",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"build:ci": "yarn build",
|
||||
"lint": "tslint --format stylish --project . --exclude **/lib/**/*",
|
||||
"fix": "tslint --fix --format stylish --project . --exclude **/lib/**/*",
|
||||
"fix": "tslint --fix --format stylish --project .--exclude **/lib/**/*",
|
||||
"test:circleci": "run-s test:coverage",
|
||||
"test": "yarn run_mocha",
|
||||
"rebuild_and_test": "run-s build test",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
|
||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||
"clean": "shx rm -rf _bundles lib test_temp generated_docs",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||
"pre_build": "yarn generate_contract_wrappers && yarn prettier_contract_wrappers",
|
||||
"prettier": "prettier --write **/* --config ../../.prettierrc",
|
||||
"prettier_contract_wrappers": "prettier --write src/generated-wrappers/* --config ../../.prettierrc",
|
||||
"clean": "shx rm -rf lib src/generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output src/generated-wrappers --backend ethers",
|
||||
"docs_test": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --out generated_docs ./src/generated-wrappers/*"
|
||||
},
|
||||
"config": {
|
||||
"postpublish": {
|
||||
"assets": []
|
||||
}
|
||||
"abis": "../contract-artifacts/artifacts/@(AssetProxyOwner|DutchAuction|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IAssetProxy|IValidator|IWallet|MultiAssetProxy|OrderValidator|WETH9|ZRXToken|Coordinator|CoordinatorRegistry|EthBalanceChecker).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo"
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contract-wrappers/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^3.1.2",
|
||||
"@0x/abi-gen-templates": "^2.4.0",
|
||||
"@0x/assert": "^2.1.2",
|
||||
"@0x/json-schemas": "^3.1.12",
|
||||
"@0x/contracts-test-utils": "^3.1.12",
|
||||
"@0x/coordinator-server": "^0.1.3",
|
||||
"@0x/dev-utils": "^2.2.6",
|
||||
@ -45,52 +57,34 @@
|
||||
"@0x/migrations": "^4.1.11",
|
||||
"@0x/subproviders": "^5.0.0",
|
||||
"@0x/tslint-config": "^3.0.1",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/nock": "^10.0.1",
|
||||
"@types/node": "*",
|
||||
"@types/sinon": "^2.2.2",
|
||||
"@types/uuid": "^3.4.3",
|
||||
"@types/web3-provider-engine": "^14.0.0",
|
||||
"@0x/types": "^2.4.1",
|
||||
"@0x/utils": "^4.4.2",
|
||||
"@0x/web3-wrapper": "^6.0.9",
|
||||
"@types/nock": "^10.0.3",
|
||||
"ethereum-types": "^2.1.4",
|
||||
"ethers": "~4.0.4",
|
||||
"lodash": "^4.17.11",
|
||||
"shx": "^0.2.2",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"nock": "^10.0.6",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"opn-cli": "^3.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"sinon": "^4.0.0",
|
||||
"source-map-support": "^0.5.0",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0.13.0",
|
||||
"typescript": "3.0.1",
|
||||
"web3-provider-engine": "14.0.6"
|
||||
"nock": "^10.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/abi-gen-wrappers": "^5.1.0",
|
||||
"@0x/assert": "^2.1.2",
|
||||
"@0x/base-contract": "^5.3.0",
|
||||
"@0x/contract-addresses": "^3.0.2",
|
||||
"@0x/contract-artifacts": "^2.0.3",
|
||||
"@0x/json-schemas": "^3.1.12",
|
||||
"@0x/contracts-test-utils": "^3.1.12",
|
||||
"@0x/coordinator-server": "^0.1.3",
|
||||
"@0x/dev-utils": "^2.2.6",
|
||||
"@0x/fill-scenarios": "^3.0.15",
|
||||
"@0x/migrations": "^4.1.11",
|
||||
"@0x/order-utils": "^8.2.4",
|
||||
"@0x/types": "^2.4.1",
|
||||
"@0x/typescript-typings": "^4.2.4",
|
||||
"@0x/utils": "^4.4.2",
|
||||
"@0x/web3-wrapper": "^6.0.9",
|
||||
"ethereum-types": "^2.1.4",
|
||||
"ethereumjs-abi": "0.6.5",
|
||||
"ethereumjs-blockstream": "6.0.0",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"ethers": "~4.0.4",
|
||||
"http-status-codes": "^1.3.2",
|
||||
"js-sha3": "^0.7.0",
|
||||
"lodash": "^4.17.11",
|
||||
"uuid": "^3.3.2"
|
||||
"@0x/subproviders": "^5.0.0",
|
||||
"http-status-codes": "^1.3.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,11 +0,0 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
export abstract class AbstractBalanceAndProxyAllowanceLazyStore {
|
||||
public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>;
|
||||
public abstract async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>;
|
||||
public abstract setBalance(tokenAddress: string, userAddress: string, balance: BigNumber): void;
|
||||
public abstract deleteBalance(tokenAddress: string, userAddress: string): void;
|
||||
public abstract setProxyAllowance(tokenAddress: string, userAddress: string, proxyAllowance: BigNumber): void;
|
||||
public abstract deleteProxyAllowance(tokenAddress: string, userAddress: string): void;
|
||||
public abstract deleteAll(): void;
|
||||
}
|
@ -15,20 +15,18 @@ import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { SupportedProvider } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { CoordinatorWrapper } from './contract_wrappers/coordinator_wrapper';
|
||||
import { DutchAuctionWrapper } from './contract_wrappers/dutch_auction_wrapper';
|
||||
import { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
|
||||
import { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
|
||||
import { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
|
||||
import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
|
||||
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
|
||||
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
|
||||
import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
|
||||
import { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper';
|
||||
import { CoordinatorWrapper } from './coordinator_wrapper';
|
||||
import { DutchAuctionContract } from './generated-wrappers/dutch_auction';
|
||||
import { ERC20ProxyContract } from './generated-wrappers/erc20_proxy';
|
||||
import { ERC721ProxyContract } from './generated-wrappers/erc721_proxy';
|
||||
import { ExchangeContract } from './generated-wrappers/exchange';
|
||||
import { ForwarderContract } from './generated-wrappers/forwarder';
|
||||
import { OrderValidatorContract } from './generated-wrappers/order_validator';
|
||||
|
||||
import { WETH9Contract } from './generated-wrappers/weth9';
|
||||
import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema';
|
||||
import { ContractWrappersConfig } from './types';
|
||||
import { assert } from './utils/assert';
|
||||
import { constants } from './utils/constants';
|
||||
import { _getDefaultContractAddresses } from './utils/contract_addresses';
|
||||
|
||||
/**
|
||||
@ -36,45 +34,36 @@ import { _getDefaultContractAddresses } from './utils/contract_addresses';
|
||||
*/
|
||||
export class ContractWrappers {
|
||||
/**
|
||||
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
|
||||
* An instance of the ExchangeContract class containing methods for interacting with the 0x Exchange smart contract.
|
||||
*/
|
||||
public exchange: ExchangeWrapper;
|
||||
public exchange: ExchangeContract;
|
||||
/**
|
||||
* An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
|
||||
*/
|
||||
public erc20Token: ERC20TokenWrapper;
|
||||
/**
|
||||
* An instance of the ERC721TokenWrapper class containing methods for interacting with any ERC721 token smart contract.
|
||||
*/
|
||||
public erc721Token: ERC721TokenWrapper;
|
||||
/**
|
||||
* An instance of the EtherTokenWrapper class containing methods for interacting with the
|
||||
* wrapped ETH ERC20 token smart contract.
|
||||
*/
|
||||
public etherToken: EtherTokenWrapper;
|
||||
/**
|
||||
* An instance of the ERC20ProxyWrapper class containing methods for interacting with the
|
||||
* An instance of the ERC20ProxyContract class containing methods for interacting with the
|
||||
* erc20Proxy smart contract.
|
||||
*/
|
||||
public erc20Proxy: ERC20ProxyWrapper;
|
||||
public erc20Proxy: ERC20ProxyContract;
|
||||
/**
|
||||
* An instance of the ERC721ProxyWrapper class containing methods for interacting with the
|
||||
* An instance of the ERC721ProxyContract class containing methods for interacting with the
|
||||
* erc721Proxy smart contract.
|
||||
*/
|
||||
public erc721Proxy: ERC721ProxyWrapper;
|
||||
public erc721Proxy: ERC721ProxyContract;
|
||||
/**
|
||||
* An instance of the ForwarderWrapper class containing methods for interacting with any Forwarder smart contract.
|
||||
* An instance of the WETH9Contract class containing methods for interacting with the
|
||||
* WETH9 smart contract.
|
||||
*/
|
||||
public forwarder: ForwarderWrapper;
|
||||
public weth9: WETH9Contract;
|
||||
/**
|
||||
* An instance of the OrderValidatorWrapper class containing methods for interacting with any OrderValidator smart contract.
|
||||
* An instance of the ForwarderContract class containing methods for interacting with any Forwarder smart contract.
|
||||
*/
|
||||
public orderValidator: OrderValidatorWrapper;
|
||||
public forwarder: ForwarderContract;
|
||||
/**
|
||||
* An instance of the DutchAuctionWrapper class containing methods for interacting with any DutchAuction smart contract.
|
||||
* An instance of the OrderValidatorContract class containing methods for interacting with any OrderValidator smart contract.
|
||||
*/
|
||||
public dutchAuction: DutchAuctionWrapper;
|
||||
|
||||
public orderValidator: OrderValidatorContract;
|
||||
/**
|
||||
* An instance of the DutchAuctionContract class containing methods for interacting with any DutchAuction smart contract.
|
||||
*/
|
||||
public dutchAuction: DutchAuctionContract;
|
||||
/**
|
||||
* An instance of the CoordinatorWrapper class containing methods for interacting with the Coordinator extension contract.
|
||||
*/
|
||||
@ -109,45 +98,17 @@ export class ContractWrappers {
|
||||
_.forEach(artifactsArray, artifact => {
|
||||
this._web3Wrapper.abiDecoder.addABI(artifact.compilerOutput.abi, artifact.contractName);
|
||||
});
|
||||
const blockPollingIntervalMs =
|
||||
config.blockPollingIntervalMs === undefined
|
||||
? constants.DEFAULT_BLOCK_POLLING_INTERVAL
|
||||
: config.blockPollingIntervalMs;
|
||||
const contractAddresses =
|
||||
config.contractAddresses === undefined
|
||||
? _getDefaultContractAddresses(config.networkId)
|
||||
: config.contractAddresses;
|
||||
this.erc20Proxy = new ERC20ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc20Proxy);
|
||||
this.erc721Proxy = new ERC721ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc721Proxy);
|
||||
this.erc20Token = new ERC20TokenWrapper(this._web3Wrapper, this.erc20Proxy, blockPollingIntervalMs);
|
||||
this.erc721Token = new ERC721TokenWrapper(this._web3Wrapper, this.erc721Proxy, blockPollingIntervalMs);
|
||||
this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.erc20Token, blockPollingIntervalMs);
|
||||
this.exchange = new ExchangeWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
this.erc20Token,
|
||||
this.erc721Token,
|
||||
contractAddresses.exchange,
|
||||
contractAddresses.zrxToken,
|
||||
blockPollingIntervalMs,
|
||||
);
|
||||
this.forwarder = new ForwarderWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
contractAddresses.forwarder,
|
||||
contractAddresses.zrxToken,
|
||||
contractAddresses.etherToken,
|
||||
);
|
||||
this.orderValidator = new OrderValidatorWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
contractAddresses.orderValidator,
|
||||
);
|
||||
this.dutchAuction = new DutchAuctionWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
contractAddresses.dutchAuction,
|
||||
);
|
||||
this.erc20Proxy = new ERC20ProxyContract(contractAddresses.erc20Proxy, this.getProvider());
|
||||
this.erc721Proxy = new ERC721ProxyContract(contractAddresses.erc721Proxy, this.getProvider());
|
||||
this.weth9 = new WETH9Contract(contractAddresses.etherToken, this.getProvider());
|
||||
this.exchange = new ExchangeContract(contractAddresses.exchange, this.getProvider());
|
||||
this.forwarder = new ForwarderContract(contractAddresses.forwarder, this.getProvider());
|
||||
this.orderValidator = new OrderValidatorContract(contractAddresses.orderValidator, this.getProvider());
|
||||
this.dutchAuction = new DutchAuctionContract(contractAddresses.dutchAuction, this.getProvider());
|
||||
this.coordinator = new CoordinatorWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
@ -161,9 +122,9 @@ export class ContractWrappers {
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
this.exchange.unsubscribeAll();
|
||||
this.erc20Token.unsubscribeAll();
|
||||
this.erc721Token.unsubscribeAll();
|
||||
this.etherToken.unsubscribeAll();
|
||||
this.erc20Proxy.unsubscribeAll();
|
||||
this.erc721Proxy.unsubscribeAll();
|
||||
this.weth9.unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
* Get the provider instance currently used by contract-wrappers
|
||||
|
@ -1,138 +0,0 @@
|
||||
import { DutchAuctionContract } from '@0x/abi-gen-wrappers';
|
||||
import { DutchAuction } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { DutchAuctionData, DutchAuctionDetails, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
|
||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
||||
import { DutchAuctionWrapperError, OrderTransactionOpts } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { _getDefaultContractAddresses } from '../utils/contract_addresses';
|
||||
|
||||
export class DutchAuctionWrapper {
|
||||
public abi: ContractAbi = DutchAuction.compilerOutput.abi;
|
||||
public address: string;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _dutchAuctionContract: DutchAuctionContract;
|
||||
/**
|
||||
* Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex
|
||||
* encoded assetData string, containing information both about the asset being traded and the
|
||||
* dutch auction; which is usable in the makerAssetData or takerAssetData fields in a 0x order.
|
||||
* @param assetData Hex encoded assetData string for the asset being auctioned.
|
||||
* @param beginTimeSeconds Begin time of the dutch auction.
|
||||
* @param beginAmount Starting amount being sold in the dutch auction.
|
||||
* @return The hex encoded assetData string.
|
||||
*/
|
||||
public static encodeDutchAuctionAssetData(
|
||||
assetData: string,
|
||||
beginTimeSeconds: BigNumber,
|
||||
beginAmount: BigNumber,
|
||||
): string {
|
||||
const dutchAuctionData = assetDataUtils.encodeDutchAuctionAssetData(assetData, beginTimeSeconds, beginAmount);
|
||||
return dutchAuctionData;
|
||||
}
|
||||
/**
|
||||
* Dutch auction details are encoded with the asset data for a 0x order. This function decodes a hex
|
||||
* encoded assetData string, containing information both about the asset being traded and the
|
||||
* dutch auction.
|
||||
* @param dutchAuctionData Hex encoded assetData string for the asset being auctioned.
|
||||
* @return An object containing the auction asset, auction begin time and auction begin amount.
|
||||
*/
|
||||
public static decodeDutchAuctionData(dutchAuctionData: string): DutchAuctionData {
|
||||
const decoded = assetDataUtils.decodeDutchAuctionData(dutchAuctionData);
|
||||
return decoded;
|
||||
}
|
||||
/**
|
||||
* Instantiate DutchAuctionWrapper
|
||||
* @param web3Wrapper Web3Wrapper instance to use.
|
||||
* @param networkId Desired networkId.
|
||||
* @param address The address of the Dutch Auction contract. If undefined, will
|
||||
* default to the known address corresponding to the networkId.
|
||||
*/
|
||||
public constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
|
||||
this.address = address === undefined ? _getDefaultContractAddresses(networkId).dutchAuction : address;
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._dutchAuctionContract = new DutchAuctionContract(
|
||||
this.address,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Matches the buy and sell orders at an amount given the following: the current block time, the auction
|
||||
* start time and the auction begin amount. The sell order is a an order at the lowest amount
|
||||
* at the end of the auction. Excess from the match is transferred to the seller.
|
||||
* Over time the price moves from beginAmount to endAmount given the current block.timestamp.
|
||||
* @param buyOrder The Buyer's order. This order is for the current expected price of the auction.
|
||||
* @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
|
||||
* @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied
|
||||
* Provider provided at instantiation.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async matchOrdersAsync(
|
||||
buyOrder: SignedOrder,
|
||||
sellOrder: SignedOrder,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
|
||||
): Promise<string> {
|
||||
// type assertions
|
||||
assert.doesConformToSchema('buyOrder', buyOrder, schemas.signedOrderSchema);
|
||||
assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
// other assertions
|
||||
if (
|
||||
sellOrder.makerAssetData !== buyOrder.takerAssetData ||
|
||||
sellOrder.takerAssetData !== buyOrder.makerAssetData
|
||||
) {
|
||||
throw new Error(DutchAuctionWrapperError.AssetDataMismatch);
|
||||
}
|
||||
// validate transaction
|
||||
if (orderTransactionOpts.shouldValidate) {
|
||||
await this._dutchAuctionContract.matchOrders.callAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
nonce: orderTransactionOpts.nonce,
|
||||
},
|
||||
);
|
||||
}
|
||||
// send transaction
|
||||
const txHash = await this._dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
nonce: orderTransactionOpts.nonce,
|
||||
},
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Fetches the Auction Details for the given order
|
||||
* @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
|
||||
* @return The dutch auction details.
|
||||
*/
|
||||
public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> {
|
||||
// type assertions
|
||||
assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema);
|
||||
// call contract
|
||||
const auctionDetails = await this._dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
return auctionDetails;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
import { ERC20ProxyContract } from '@0x/abi-gen-wrappers';
|
||||
import { ERC20Proxy } from '@0x/contract-artifacts';
|
||||
import { AssetProxyId } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { assert } from '../utils/assert';
|
||||
import { _getDefaultContractAddresses } from '../utils/contract_addresses';
|
||||
|
||||
/**
|
||||
* This class includes the functionality related to interacting with the ERC20Proxy contract.
|
||||
*/
|
||||
export class ERC20ProxyWrapper {
|
||||
public abi: ContractAbi = ERC20Proxy.compilerOutput.abi;
|
||||
public address: string;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _erc20ProxyContract: ERC20ProxyContract;
|
||||
/**
|
||||
* Instantiate ERC20ProxyWrapper
|
||||
* @param web3Wrapper Web3Wrapper instance to use
|
||||
* @param networkId Desired networkId
|
||||
* @param address The address of the ERC20Proxy contract. If undefined, will
|
||||
* default to the known address corresponding to the networkId.
|
||||
*/
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this.address = address === undefined ? _getDefaultContractAddresses(networkId).erc20Proxy : address;
|
||||
this._erc20ProxyContract = new ERC20ProxyContract(
|
||||
this.address,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Get the 4 bytes ID of this asset proxy
|
||||
* @return Proxy id
|
||||
*/
|
||||
public async getProxyIdAsync(): Promise<AssetProxyId> {
|
||||
// Note(albrow): Below is a TSLint false positive. Code won't compile if
|
||||
// you remove the type assertion.
|
||||
/* tslint:disable-next-line:no-unnecessary-type-assertion */
|
||||
const proxyId = (await this._erc20ProxyContract.getProxyId.callAsync()) as AssetProxyId;
|
||||
return proxyId;
|
||||
}
|
||||
/**
|
||||
* Check if the Exchange contract address is authorized by the ERC20Proxy contract.
|
||||
* @param exchangeContractAddress The hex encoded address of the Exchange contract to call.
|
||||
* @return Whether the exchangeContractAddress is authorized.
|
||||
*/
|
||||
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
|
||||
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
|
||||
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
|
||||
const isAuthorized = await this._erc20ProxyContract.authorized.callAsync(normalizedExchangeContractAddress);
|
||||
return isAuthorized;
|
||||
}
|
||||
/**
|
||||
* Get the list of all Exchange contract addresses authorized by the ERC20Proxy contract.
|
||||
* @return The list of authorized addresses.
|
||||
*/
|
||||
public async getAuthorizedAddressesAsync(): Promise<string[]> {
|
||||
const authorizedAddresses = await this._erc20ProxyContract.getAuthorizedAddresses.callAsync();
|
||||
return authorizedAddresses;
|
||||
}
|
||||
}
|
@ -1,444 +0,0 @@
|
||||
import { ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents } from '@0x/abi-gen-wrappers';
|
||||
import { SubscriptionManager } from '@0x/base-contract';
|
||||
import { ERC20Token } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { methodOptsSchema } from '../schemas/method_opts_schema';
|
||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
||||
import {
|
||||
BlockRange,
|
||||
ContractWrappersError,
|
||||
EventCallback,
|
||||
IndexedFilterValues,
|
||||
MethodOpts,
|
||||
TransactionOpts,
|
||||
} from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { constants } from '../utils/constants';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { ERC20ProxyWrapper } from './erc20_proxy_wrapper';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with ERC20 token contracts.
|
||||
* All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances
|
||||
* to the 0x ERC20 Proxy smart contract.
|
||||
*/
|
||||
export class ERC20TokenWrapper {
|
||||
public abi: ContractAbi = ERC20Token.compilerOutput.abi;
|
||||
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _blockPollingIntervalMs?: number;
|
||||
private readonly _subscriptionManager: SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>;
|
||||
private readonly _tokenContractsByAddress: { [address: string]: ERC20TokenContract };
|
||||
private readonly _erc20ProxyWrapper: ERC20ProxyWrapper;
|
||||
/**
|
||||
* Instantiate ERC20TokenWrapper
|
||||
* @param web3Wrapper Web3Wrapper instance to use
|
||||
* @param erc20ProxyWrapper The ERC20ProxyWrapper instance to use
|
||||
*/
|
||||
constructor(web3Wrapper: Web3Wrapper, erc20ProxyWrapper: ERC20ProxyWrapper, blockPollingIntervalMs?: number) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._tokenContractsByAddress = {};
|
||||
this._erc20ProxyWrapper = erc20ProxyWrapper;
|
||||
this._blockPollingIntervalMs = blockPollingIntervalMs;
|
||||
this._subscriptionManager = new SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>(
|
||||
ERC20TokenContract.ABI(),
|
||||
web3Wrapper,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Retrieves an owner's ERC20 token balance.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address whose balance you would like to check.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return The owner's ERC20 token balance in base units.
|
||||
*/
|
||||
public async getBalanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const txData = {};
|
||||
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, methodOpts.defaultBlock);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
balance = new BigNumber(balance);
|
||||
return balance;
|
||||
}
|
||||
/**
|
||||
* Sets the spender's allowance to a specified number of baseUnits on behalf of the owner address.
|
||||
* Equivalent to the ERC20 spec method `approve`.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance
|
||||
* for spenderAddress.
|
||||
* @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance.
|
||||
* @param amountInBaseUnits The allowance amount you would like to set.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
spenderAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
|
||||
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const txHash = await tokenContract.approve.sendTransactionAsync(
|
||||
normalizedSpenderAddress,
|
||||
amountInBaseUnits,
|
||||
utils.removeUndefinedProperties({
|
||||
from: normalizedOwnerAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Sets the spender's allowance to an unlimited number of baseUnits on behalf of the owner address.
|
||||
* Equivalent to the ERC20 spec method `approve`.
|
||||
* Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating
|
||||
* allowances set to the max amount (e.g ZRX, WETH)
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance
|
||||
* for spenderAddress.
|
||||
* @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setUnlimitedAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
spenderAddress: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
const txHash = await this.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
txOpts,
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Retrieves the owners allowance in baseUnits set to the spender's address.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address whose allowance to spenderAddress
|
||||
* you would like to retrieve.
|
||||
* @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
*/
|
||||
public async getAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
spenderAddress: string,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const txData = {};
|
||||
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
|
||||
normalizedOwnerAddress,
|
||||
normalizedSpenderAddress,
|
||||
txData,
|
||||
methodOpts.defaultBlock,
|
||||
);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
|
||||
return allowanceInBaseUnits;
|
||||
}
|
||||
/**
|
||||
* Retrieves the owner's allowance in baseUnits set to the 0x proxy contract.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
*/
|
||||
public async getProxyAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<BigNumber> {
|
||||
const proxyAddress = this._erc20ProxyWrapper.address;
|
||||
const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts);
|
||||
return allowanceInBaseUnits;
|
||||
}
|
||||
/**
|
||||
* Sets the 0x proxy contract's allowance to a specified number of a tokens' baseUnits on behalf
|
||||
* of an owner address.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address who is setting an allowance
|
||||
* for the Proxy contract.
|
||||
* @param amountInBaseUnits The allowance amount specified in baseUnits.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setProxyAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
const proxyAddress = this._erc20ProxyWrapper.address;
|
||||
const txHash = await this.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
proxyAddress,
|
||||
amountInBaseUnits,
|
||||
txOpts,
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Sets the 0x proxy contract's allowance to a unlimited number of a tokens' baseUnits on behalf
|
||||
* of an owner address.
|
||||
* Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating
|
||||
* allowances set to the max amount (e.g ZRX, WETH)
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address who is setting an allowance
|
||||
* for the Proxy contract.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setUnlimitedProxyAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
const txHash = await this.setProxyAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
txOpts,
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param fromAddress The hex encoded user Ethereum address that will send the funds.
|
||||
* @param toAddress The hex encoded user Ethereum address that will receive the funds.
|
||||
* @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async transferAsync(
|
||||
tokenAddress: string,
|
||||
fromAddress: string,
|
||||
toAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
|
||||
assert.isETHAddressHex('toAddress', toAddress);
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedFromAddress = fromAddress.toLowerCase();
|
||||
const normalizedToAddress = toAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
|
||||
if (fromAddressBalance.isLessThan(amountInBaseUnits)) {
|
||||
throw new Error(ContractWrappersError.InsufficientBalanceForTransfer);
|
||||
}
|
||||
|
||||
const txHash = await tokenContract.transfer.sendTransactionAsync(
|
||||
normalizedToAddress,
|
||||
amountInBaseUnits,
|
||||
utils.removeUndefinedProperties({
|
||||
from: normalizedFromAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`.
|
||||
* Requires the fromAddress to have sufficient funds and to have approved an allowance of
|
||||
* `amountInBaseUnits` to `senderAddress`.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
|
||||
* @param fromAddress The hex encoded user Ethereum address whose funds are being sent.
|
||||
* @param toAddress The hex encoded user Ethereum address that will receive the funds.
|
||||
* @param senderAddress The hex encoded user Ethereum address whose initiates the fund transfer. The
|
||||
* `fromAddress` must have set an allowance to the `senderAddress`
|
||||
* before this call.
|
||||
* @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async transferFromAsync(
|
||||
tokenAddress: string,
|
||||
fromAddress: string,
|
||||
toAddress: string,
|
||||
senderAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('fromAddress', fromAddress);
|
||||
assert.isETHAddressHex('toAddress', toAddress);
|
||||
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
const normalizedToAddress = toAddress.toLowerCase();
|
||||
const normalizedFromAddress = fromAddress.toLowerCase();
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedSenderAddress = senderAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const fromAddressAllowance = await this.getAllowanceAsync(
|
||||
normalizedTokenAddress,
|
||||
normalizedFromAddress,
|
||||
normalizedSenderAddress,
|
||||
);
|
||||
if (fromAddressAllowance.isLessThan(amountInBaseUnits)) {
|
||||
throw new Error(ContractWrappersError.InsufficientAllowanceForTransfer);
|
||||
}
|
||||
|
||||
const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
|
||||
if (fromAddressBalance.isLessThan(amountInBaseUnits)) {
|
||||
throw new Error(ContractWrappersError.InsufficientBalanceForTransfer);
|
||||
}
|
||||
|
||||
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
|
||||
normalizedFromAddress,
|
||||
normalizedToAddress,
|
||||
amountInBaseUnits,
|
||||
utils.removeUndefinedProperties({
|
||||
from: normalizedSenderAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Subscribe to an event type emitted by the Token contract.
|
||||
* @param tokenAddress The hex encoded address where the ERC20 token is deployed.
|
||||
* @param eventName The token contract event you would like to subscribe to.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
|
||||
* @param callback Callback that gets called when a log is added/removed
|
||||
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends ERC20TokenEventArgs>(
|
||||
tokenAddress: string,
|
||||
eventName: ERC20TokenEvents,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>,
|
||||
isVerbose: boolean = false,
|
||||
): string {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
|
||||
normalizedTokenAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
ERC20Token.compilerOutput.abi,
|
||||
callback,
|
||||
isVerbose,
|
||||
this._blockPollingIntervalMs,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
/**
|
||||
* Cancel a subscription
|
||||
* @param subscriptionToken Subscription token returned by `subscribe()`
|
||||
*/
|
||||
public unsubscribe(subscriptionToken: string): void {
|
||||
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
|
||||
this._subscriptionManager.unsubscribe(subscriptionToken); // doesn't matter which contract is used
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
this._subscriptionManager.unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
* Gets historical logs without creating a subscription
|
||||
* @param tokenAddress An address of the token that emitted the logs.
|
||||
* @param eventName The token contract event you would like to subscribe to.
|
||||
* @param blockRange Block range to get logs from.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends ERC20TokenEventArgs>(
|
||||
tokenAddress: string,
|
||||
eventName: ERC20TokenEvents,
|
||||
blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
|
||||
normalizedTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
ERC20Token.compilerOutput.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
private async _getTokenContractAsync(tokenAddress: string): Promise<ERC20TokenContract> {
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
|
||||
if (tokenContract !== undefined) {
|
||||
return tokenContract;
|
||||
}
|
||||
const contractInstance = new ERC20TokenContract(
|
||||
normalizedTokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
tokenContract = contractInstance;
|
||||
this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
|
||||
return tokenContract;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
import { ERC721ProxyContract } from '@0x/abi-gen-wrappers';
|
||||
import { ERC721Proxy } from '@0x/contract-artifacts';
|
||||
import { AssetProxyId } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { assert } from '../utils/assert';
|
||||
import { _getDefaultContractAddresses } from '../utils/contract_addresses';
|
||||
|
||||
/**
|
||||
* This class includes the functionality related to interacting with the ERC721Proxy contract.
|
||||
*/
|
||||
export class ERC721ProxyWrapper {
|
||||
public abi: ContractAbi = ERC721Proxy.compilerOutput.abi;
|
||||
public address: string;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _erc721ProxyContract: ERC721ProxyContract;
|
||||
/**
|
||||
* Instantiate ERC721ProxyWrapper
|
||||
* @param web3Wrapper Web3Wrapper instance to use
|
||||
* @param networkId Desired networkId
|
||||
* @param address The address of the ERC721Proxy contract. If undefined,
|
||||
* will default to the known address corresponding to the networkId.
|
||||
*/
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this.address = address === undefined ? _getDefaultContractAddresses(networkId).erc721Proxy : address;
|
||||
this._erc721ProxyContract = new ERC721ProxyContract(
|
||||
this.address,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Get the 4 bytes ID of this asset proxy
|
||||
* @return Proxy id
|
||||
*/
|
||||
public async getProxyIdAsync(): Promise<AssetProxyId> {
|
||||
// Note(albrow): Below is a TSLint false positive. Code won't compile if
|
||||
// you remove the type assertion.
|
||||
/* tslint:disable-next-line:no-unnecessary-type-assertion */
|
||||
const proxyId = (await this._erc721ProxyContract.getProxyId.callAsync()) as AssetProxyId;
|
||||
return proxyId;
|
||||
}
|
||||
/**
|
||||
* Check if the Exchange contract address is authorized by the ERC721Proxy contract.
|
||||
* @param exchangeContractAddress The hex encoded address of the Exchange contract to call.
|
||||
* @return Whether the exchangeContractAddress is authorized.
|
||||
*/
|
||||
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
|
||||
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
|
||||
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
|
||||
const isAuthorized = await this._erc721ProxyContract.authorized.callAsync(normalizedExchangeContractAddress);
|
||||
return isAuthorized;
|
||||
}
|
||||
/**
|
||||
* Get the list of all Exchange contract addresses authorized by the ERC721Proxy contract.
|
||||
* @return The list of authorized addresses.
|
||||
*/
|
||||
public async getAuthorizedAddressesAsync(): Promise<string[]> {
|
||||
const authorizedAddresses = await this._erc721ProxyContract.getAuthorizedAddresses.callAsync();
|
||||
return authorizedAddresses;
|
||||
}
|
||||
}
|
@ -1,471 +0,0 @@
|
||||
import { ERC721TokenContract, ERC721TokenEventArgs, ERC721TokenEvents } from '@0x/abi-gen-wrappers';
|
||||
import { SubscriptionManager } from '@0x/base-contract';
|
||||
import { ERC721Token } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { methodOptsSchema } from '../schemas/method_opts_schema';
|
||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
||||
import {
|
||||
BlockRange,
|
||||
ContractWrappersError,
|
||||
EventCallback,
|
||||
IndexedFilterValues,
|
||||
MethodOpts,
|
||||
TransactionOpts,
|
||||
} from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { constants } from '../utils/constants';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { ERC721ProxyWrapper } from './erc721_proxy_wrapper';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with ERC721 token contracts.
|
||||
* All ERC721 method calls are supported, along with some convenience methods for getting/setting allowances
|
||||
* to the 0x ERC721 Proxy smart contract.
|
||||
*/
|
||||
export class ERC721TokenWrapper {
|
||||
public abi: ContractAbi = ERC721Token.compilerOutput.abi;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _subscriptionManager: SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>;
|
||||
private readonly _blockPollingIntervalMs?: number;
|
||||
private readonly _tokenContractsByAddress: { [address: string]: ERC721TokenContract };
|
||||
private readonly _erc721ProxyWrapper: ERC721ProxyWrapper;
|
||||
/**
|
||||
* Instantiate ERC721TokenWrapper
|
||||
* @param web3Wrapper Web3Wrapper instance to use
|
||||
* @param erc721ProxyWrapper The ERC721ProxyWrapper instance to use
|
||||
*/
|
||||
constructor(web3Wrapper: Web3Wrapper, erc721ProxyWrapper: ERC721ProxyWrapper, blockPollingIntervalMs?: number) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._tokenContractsByAddress = {};
|
||||
this._erc721ProxyWrapper = erc721ProxyWrapper;
|
||||
this._blockPollingIntervalMs = blockPollingIntervalMs;
|
||||
this._subscriptionManager = new SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>(
|
||||
ERC721TokenContract.ABI(),
|
||||
web3Wrapper,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Count all NFTs assigned to an owner
|
||||
* NFTs assigned to the zero address are considered invalid, and this function throws for queries about the zero address.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address whose balance you would like to check.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return The number of NFTs owned by `ownerAddress`, possibly zero
|
||||
*/
|
||||
public async getTokenCountAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const txData = {};
|
||||
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, methodOpts.defaultBlock);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
balance = new BigNumber(balance);
|
||||
return balance;
|
||||
}
|
||||
/**
|
||||
* Find the owner of an NFT
|
||||
* NFTs assigned to zero address are considered invalid, and queries about them do throw.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param tokenId The identifier for an NFT
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return The address of the owner of the NFT
|
||||
*/
|
||||
public async getOwnerOfAsync(
|
||||
tokenAddress: string,
|
||||
tokenId: BigNumber,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isBigNumber('tokenId', tokenId);
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const txData = {};
|
||||
try {
|
||||
const tokenOwner = await tokenContract.ownerOf.callAsync(tokenId, txData, methodOpts.defaultBlock);
|
||||
return tokenOwner;
|
||||
} catch (err) {
|
||||
throw new Error(ContractWrappersError.ERC721OwnerNotFound);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Query if an address is an authorized operator for all NFT's of `ownerAddress`
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
|
||||
* @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to check if approved.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return True if `operatorAddress` is an approved operator for `ownerAddress`, false otherwise
|
||||
*/
|
||||
public async isApprovedForAllAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
operatorAddress: string,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<boolean> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('operatorAddress', operatorAddress);
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
const normalizedOperatorAddress = operatorAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const txData = {};
|
||||
const isApprovedForAll = await tokenContract.isApprovedForAll.callAsync(
|
||||
normalizedOwnerAddress,
|
||||
normalizedOperatorAddress,
|
||||
txData,
|
||||
methodOpts.defaultBlock,
|
||||
);
|
||||
return isApprovedForAll;
|
||||
}
|
||||
/**
|
||||
* Query if 0x proxy is an authorized operator for all NFT's of `ownerAddress`
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return True if `operatorAddress` is an approved operator for `ownerAddress`, false otherwise
|
||||
*/
|
||||
public async isProxyApprovedForAllAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<boolean> {
|
||||
const proxyAddress = this._erc721ProxyWrapper.address;
|
||||
const isProxyApprovedForAll = await this.isApprovedForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
proxyAddress,
|
||||
methodOpts,
|
||||
);
|
||||
return isProxyApprovedForAll;
|
||||
}
|
||||
/**
|
||||
* Get the approved address for a single NFT. Returns undefined if no approval was set
|
||||
* Throws if `_tokenId` is not a valid NFT
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param tokenId The identifier for an NFT
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return The approved address for this NFT, or the undefined if there is none
|
||||
*/
|
||||
public async getApprovedIfExistsAsync(
|
||||
tokenAddress: string,
|
||||
tokenId: BigNumber,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<string | undefined> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isBigNumber('tokenId', tokenId);
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const txData = {};
|
||||
const approvedAddress = await tokenContract.getApproved.callAsync(tokenId, txData, methodOpts.defaultBlock);
|
||||
if (approvedAddress === constants.NULL_ADDRESS) {
|
||||
return undefined;
|
||||
}
|
||||
return approvedAddress;
|
||||
}
|
||||
/**
|
||||
* Checks if 0x proxy is approved for a single NFT
|
||||
* Throws if `_tokenId` is not a valid NFT
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param tokenId The identifier for an NFT
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return True if 0x proxy is approved
|
||||
*/
|
||||
public async isProxyApprovedAsync(
|
||||
tokenAddress: string,
|
||||
tokenId: BigNumber,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<boolean> {
|
||||
const proxyAddress = this._erc721ProxyWrapper.address;
|
||||
const approvedAddress = await this.getApprovedIfExistsAsync(tokenAddress, tokenId, methodOpts);
|
||||
const isProxyApproved = approvedAddress === proxyAddress;
|
||||
return isProxyApproved;
|
||||
}
|
||||
/**
|
||||
* Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets.
|
||||
* Throws if `_tokenId` is not a valid NFT
|
||||
* Emits the ApprovalForAll event.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
|
||||
* @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to set approval for.
|
||||
* @param isApproved The boolean variable to set the approval to.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setApprovalForAllAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
operatorAddress: string,
|
||||
isApproved: boolean,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
|
||||
assert.isETHAddressHex('operatorAddress', operatorAddress);
|
||||
assert.isBoolean('isApproved', isApproved);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
const normalizedOperatorAddress = operatorAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const txHash = await tokenContract.setApprovalForAll.sendTransactionAsync(
|
||||
normalizedOperatorAddress,
|
||||
isApproved,
|
||||
utils.removeUndefinedProperties({
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
from: normalizedOwnerAddress,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets.
|
||||
* Throws if `_tokenId` is not a valid NFT
|
||||
* Emits the ApprovalForAll event.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
|
||||
* @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to set approval for.
|
||||
* @param isApproved The boolean variable to set the approval to.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setProxyApprovalForAllAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
isApproved: boolean,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
const proxyAddress = this._erc721ProxyWrapper.address;
|
||||
const txHash = await this.setApprovalForAllAsync(tokenAddress, ownerAddress, proxyAddress, isApproved, txOpts);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Set or reaffirm the approved address for an NFT
|
||||
* The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner,
|
||||
* or an authorized operator of the current owner.
|
||||
* Throws if `_tokenId` is not a valid NFT
|
||||
* Emits the Approval event.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param approvedAddress The hex encoded user Ethereum address you'd like to set approval for.
|
||||
* @param tokenId The identifier for an NFT
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setApprovalAsync(
|
||||
tokenAddress: string,
|
||||
approvedAddress: string,
|
||||
tokenId: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('approvedAddress', approvedAddress);
|
||||
assert.isBigNumber('tokenId', tokenId);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedApprovedAddress = approvedAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const tokenOwnerAddress = await tokenContract.ownerOf.callAsync(tokenId);
|
||||
await assert.isSenderAddressAsync('tokenOwnerAddress', tokenOwnerAddress, this._web3Wrapper);
|
||||
const txHash = await tokenContract.approve.sendTransactionAsync(
|
||||
normalizedApprovedAddress,
|
||||
tokenId,
|
||||
utils.removeUndefinedProperties({
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
from: tokenOwnerAddress,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Set or reaffirm 0x proxy as an approved address for an NFT
|
||||
* Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.
|
||||
* Throws if `_tokenId` is not a valid NFT
|
||||
* Emits the Approval event.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param tokenId The identifier for an NFT
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setProxyApprovalAsync(
|
||||
tokenAddress: string,
|
||||
tokenId: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
const proxyAddress = this._erc721ProxyWrapper.address;
|
||||
const txHash = await this.setApprovalAsync(tokenAddress, proxyAddress, tokenId, txOpts);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets.
|
||||
* Throws if `_tokenId` is not a valid NFT
|
||||
* Emits the ApprovalForAll event.
|
||||
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
|
||||
* @param receiverAddress The hex encoded Ethereum address of the user to send the NFT to.
|
||||
* @param senderAddress The hex encoded Ethereum address of the user to send the NFT to.
|
||||
* @param tokenId The identifier for an NFT
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async transferFromAsync(
|
||||
tokenAddress: string,
|
||||
receiverAddress: string,
|
||||
senderAddress: string,
|
||||
tokenId: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('receiverAddress', receiverAddress);
|
||||
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedReceiverAddress = receiverAddress.toLowerCase();
|
||||
const normalizedSenderAddress = senderAddress.toLowerCase();
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const ownerAddress = await this.getOwnerOfAsync(tokenAddress, tokenId);
|
||||
if (normalizedSenderAddress !== ownerAddress) {
|
||||
const isApprovedForAll = await this.isApprovedForAllAsync(
|
||||
normalizedTokenAddress,
|
||||
ownerAddress,
|
||||
normalizedSenderAddress,
|
||||
);
|
||||
if (!isApprovedForAll) {
|
||||
const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId);
|
||||
if (approvedAddress !== normalizedSenderAddress) {
|
||||
throw new Error(ContractWrappersError.ERC721NoApproval);
|
||||
}
|
||||
}
|
||||
}
|
||||
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
|
||||
ownerAddress,
|
||||
normalizedReceiverAddress,
|
||||
tokenId,
|
||||
utils.removeUndefinedProperties({
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
from: normalizedSenderAddress,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Subscribe to an event type emitted by the Token contract.
|
||||
* @param tokenAddress The hex encoded address where the ERC721 token is deployed.
|
||||
* @param eventName The token contract event you would like to subscribe to.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
|
||||
* @param callback Callback that gets called when a log is added/removed
|
||||
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends ERC721TokenEventArgs>(
|
||||
tokenAddress: string,
|
||||
eventName: ERC721TokenEvents,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>,
|
||||
isVerbose: boolean = false,
|
||||
): string {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
|
||||
normalizedTokenAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
ERC721Token.compilerOutput.abi,
|
||||
callback,
|
||||
isVerbose,
|
||||
this._blockPollingIntervalMs,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
/**
|
||||
* Cancel a subscription
|
||||
* @param subscriptionToken Subscription token returned by `subscribe()`
|
||||
*/
|
||||
public unsubscribe(subscriptionToken: string): void {
|
||||
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
|
||||
this._subscriptionManager.unsubscribe(subscriptionToken);
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
this._subscriptionManager.unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
* Gets historical logs without creating a subscription
|
||||
* @param tokenAddress An address of the token that emitted the logs.
|
||||
* @param eventName The token contract event you would like to subscribe to.
|
||||
* @param blockRange Block range to get logs from.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends ERC721TokenEventArgs>(
|
||||
tokenAddress: string,
|
||||
eventName: ERC721TokenEvents,
|
||||
blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
|
||||
normalizedTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
ERC721Token.compilerOutput.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
private async _getTokenContractAsync(tokenAddress: string): Promise<ERC721TokenContract> {
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
|
||||
if (tokenContract !== undefined) {
|
||||
return tokenContract;
|
||||
}
|
||||
const contractInstance = new ERC721TokenContract(
|
||||
normalizedTokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
tokenContract = contractInstance;
|
||||
this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
|
||||
return tokenContract;
|
||||
}
|
||||
}
|
@ -1,212 +0,0 @@
|
||||
import { WETH9Contract, WETH9EventArgs, WETH9Events } from '@0x/abi-gen-wrappers';
|
||||
import { SubscriptionManager } from '@0x/base-contract';
|
||||
import { WETH9 } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { BlockRange, ContractWrappersError, EventCallback, IndexedFilterValues, TransactionOpts } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { ERC20TokenWrapper } from './erc20_token_wrapper';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
|
||||
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
|
||||
*/
|
||||
export class EtherTokenWrapper {
|
||||
public abi: ContractAbi = WETH9.compilerOutput.abi;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _subscriptionManager: SubscriptionManager<WETH9EventArgs, WETH9Events>;
|
||||
private readonly _blockPollingIntervalMs?: number;
|
||||
private readonly _etherTokenContractsByAddress: {
|
||||
[address: string]: WETH9Contract;
|
||||
} = {};
|
||||
private readonly _erc20TokenWrapper: ERC20TokenWrapper;
|
||||
/**
|
||||
* Instantiate EtherTokenWrapper.
|
||||
* @param web3Wrapper Web3Wrapper instance to use
|
||||
* @param erc20TokenWrapper The ERC20TokenWrapper instance to use
|
||||
*/
|
||||
constructor(web3Wrapper: Web3Wrapper, erc20TokenWrapper: ERC20TokenWrapper, blockPollingIntervalMs?: number) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._erc20TokenWrapper = erc20TokenWrapper;
|
||||
this._blockPollingIntervalMs = blockPollingIntervalMs;
|
||||
this._subscriptionManager = new SubscriptionManager<WETH9EventArgs, WETH9Events>(
|
||||
WETH9Contract.ABI(),
|
||||
web3Wrapper,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens
|
||||
* to the depositor address. These wrapped ETH tokens can be used in 0x trades and are redeemable for 1-to-1
|
||||
* for ETH.
|
||||
* @param etherTokenAddress EtherToken address you wish to deposit into.
|
||||
* @param amountInWei Amount of ETH in Wei the caller wishes to deposit.
|
||||
* @param depositor The hex encoded user Ethereum address that would like to make the deposit.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async depositAsync(
|
||||
etherTokenAddress: string,
|
||||
amountInWei: BigNumber,
|
||||
depositor: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
const normalizedDepositorAddress = depositor.toLowerCase();
|
||||
|
||||
const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(normalizedDepositorAddress);
|
||||
assert.assert(ethBalanceInWei.gte(amountInWei), ContractWrappersError.InsufficientEthBalanceForDeposit);
|
||||
|
||||
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
|
||||
const txHash = await wethContract.deposit.sendTransactionAsync(
|
||||
utils.removeUndefinedProperties({
|
||||
from: normalizedDepositorAddress,
|
||||
value: amountInWei,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Withdraw ETH to the withdrawer's address from the wrapped ETH smart contract in exchange for the
|
||||
* equivalent number of wrapped ETH tokens.
|
||||
* @param etherTokenAddress EtherToken address you wish to withdraw from.
|
||||
* @param amountInWei Amount of ETH in Wei the caller wishes to withdraw.
|
||||
* @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawal.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async withdrawAsync(
|
||||
etherTokenAddress: string,
|
||||
amountInWei: BigNumber,
|
||||
withdrawer: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
const normalizedWithdrawerAddress = withdrawer.toLowerCase();
|
||||
|
||||
const WETHBalanceInBaseUnits = await this._erc20TokenWrapper.getBalanceAsync(
|
||||
normalizedEtherTokenAddress,
|
||||
normalizedWithdrawerAddress,
|
||||
);
|
||||
assert.assert(
|
||||
WETHBalanceInBaseUnits.gte(amountInWei),
|
||||
ContractWrappersError.InsufficientWEthBalanceForWithdrawal,
|
||||
);
|
||||
|
||||
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
|
||||
const txHash = await wethContract.withdraw.sendTransactionAsync(
|
||||
amountInWei,
|
||||
utils.removeUndefinedProperties({
|
||||
from: normalizedWithdrawerAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
nonce: txOpts.nonce,
|
||||
}),
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Gets historical logs without creating a subscription
|
||||
* @param etherTokenAddress An address of the ether token that emitted the logs.
|
||||
* @param eventName The ether token contract event you would like to subscribe to.
|
||||
* @param blockRange Block range to get logs from.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends WETH9EventArgs>(
|
||||
etherTokenAddress: string,
|
||||
eventName: WETH9Events,
|
||||
blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
|
||||
normalizedEtherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
WETH9.compilerOutput.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
/**
|
||||
* Subscribe to an event type emitted by the Token contract.
|
||||
* @param etherTokenAddress The hex encoded address where the ether token is deployed.
|
||||
* @param eventName The ether token contract event you would like to subscribe to.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
|
||||
* @param callback Callback that gets called when a log is added/removed
|
||||
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends WETH9EventArgs>(
|
||||
etherTokenAddress: string,
|
||||
eventName: WETH9Events,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>,
|
||||
isVerbose: boolean = false,
|
||||
): string {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
|
||||
normalizedEtherTokenAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
WETH9.compilerOutput.abi,
|
||||
callback,
|
||||
isVerbose,
|
||||
this._blockPollingIntervalMs,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
/**
|
||||
* Cancel a subscription
|
||||
* @param subscriptionToken Subscription token returned by `subscribe()`
|
||||
*/
|
||||
public unsubscribe(subscriptionToken: string): void {
|
||||
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
|
||||
this._subscriptionManager.unsubscribe(subscriptionToken);
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
this._subscriptionManager.unsubscribeAll();
|
||||
}
|
||||
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<WETH9Contract> {
|
||||
let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress];
|
||||
if (etherTokenContract !== undefined) {
|
||||
return etherTokenContract;
|
||||
}
|
||||
const contractInstance = new WETH9Contract(
|
||||
etherTokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
etherTokenContract = contractInstance;
|
||||
this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
|
||||
return etherTokenContract;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,239 +0,0 @@
|
||||
import { ForwarderContract } from '@0x/abi-gen-wrappers';
|
||||
import { Forwarder } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
|
||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
||||
import { OrderTransactionOpts } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { calldataOptimizationUtils } from '../utils/calldata_optimization_utils';
|
||||
import { constants } from '../utils/constants';
|
||||
import { _getDefaultContractAddresses } from '../utils/contract_addresses';
|
||||
import { decorators } from '../utils/decorators';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
/**
|
||||
* This class includes the functionality related to interacting with the Forwarder contract.
|
||||
*/
|
||||
export class ForwarderWrapper {
|
||||
public abi: ContractAbi = Forwarder.compilerOutput.abi;
|
||||
public address: string;
|
||||
public zrxTokenAddress: string;
|
||||
public etherTokenAddress: string;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _forwarderContract: ForwarderContract;
|
||||
|
||||
/**
|
||||
* Instantiate ForwarderWrapper
|
||||
* @param web3Wrapper Web3Wrapper instance to use.
|
||||
* @param networkId Desired networkId.
|
||||
* @param address The address of the Exchange contract. If undefined, will
|
||||
* default to the known address corresponding to the networkId.
|
||||
* @param zrxTokenAddress The address of the ZRXToken contract. If
|
||||
* undefined, will default to the known address corresponding to the
|
||||
* networkId.
|
||||
* @param etherTokenAddress The address of a WETH (Ether token) contract. If
|
||||
* undefined, will default to the known address corresponding to the
|
||||
* networkId.
|
||||
*/
|
||||
constructor(
|
||||
web3Wrapper: Web3Wrapper,
|
||||
networkId: number,
|
||||
address?: string,
|
||||
zrxTokenAddress?: string,
|
||||
etherTokenAddress?: string,
|
||||
) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this.address = address === undefined ? _getDefaultContractAddresses(networkId).exchange : address;
|
||||
this.zrxTokenAddress =
|
||||
zrxTokenAddress === undefined ? _getDefaultContractAddresses(networkId).zrxToken : zrxTokenAddress;
|
||||
this.etherTokenAddress =
|
||||
etherTokenAddress === undefined ? _getDefaultContractAddresses(networkId).etherToken : etherTokenAddress;
|
||||
this._forwarderContract = new ForwarderContract(
|
||||
this.address,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.
|
||||
* Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.
|
||||
* 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH).
|
||||
* Any ETH not spent will be refunded to sender.
|
||||
* @param signedOrders An array of objects that conform to the SignedOrder interface. All orders must specify the same makerAsset.
|
||||
* All orders must specify WETH as the takerAsset
|
||||
* @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied
|
||||
* Provider provided at instantiation.
|
||||
* @param ethAmount The amount of eth to send with the transaction (in wei).
|
||||
* @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset.
|
||||
* Used to purchase ZRX for primary order fees.
|
||||
* @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
* Defaults to 0.
|
||||
* @param feeRecipientAddress The address that will receive ETH when signedFeeOrders are filled.
|
||||
* @param orderTransactionOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async marketSellOrdersWithEthAsync(
|
||||
signedOrders: SignedOrder[],
|
||||
takerAddress: string,
|
||||
ethAmount: BigNumber,
|
||||
signedFeeOrders: SignedOrder[] = [],
|
||||
feePercentage: number = 0,
|
||||
feeRecipientAddress: string = constants.NULL_ADDRESS,
|
||||
orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
|
||||
): Promise<string> {
|
||||
// type assertions
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
assert.isBigNumber('ethAmount', ethAmount);
|
||||
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
|
||||
assert.isNumber('feePercentage', feePercentage);
|
||||
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
// other assertions
|
||||
assert.ordersCanBeUsedForForwarderContract(signedOrders, this.etherTokenAddress);
|
||||
assert.feeOrdersCanBeUsedForForwarderContract(signedFeeOrders, this.zrxTokenAddress, this.etherTokenAddress);
|
||||
// format feePercentage
|
||||
const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
|
||||
// lowercase input addresses
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
|
||||
// optimize orders
|
||||
const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders);
|
||||
const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders);
|
||||
// compile signatures
|
||||
const signatures = _.map(optimizedMarketOrders, order => order.signature);
|
||||
const feeSignatures = _.map(optimizedFeeOrders, order => order.signature);
|
||||
// validate transaction
|
||||
if (orderTransactionOpts.shouldValidate) {
|
||||
await this._forwarderContract.marketSellOrdersWithEth.callAsync(
|
||||
optimizedMarketOrders,
|
||||
signatures,
|
||||
optimizedFeeOrders,
|
||||
feeSignatures,
|
||||
formattedFeePercentage,
|
||||
normalizedFeeRecipientAddress,
|
||||
{
|
||||
value: ethAmount,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
nonce: orderTransactionOpts.nonce,
|
||||
},
|
||||
);
|
||||
}
|
||||
// send transaction
|
||||
const txHash = await this._forwarderContract.marketSellOrdersWithEth.sendTransactionAsync(
|
||||
optimizedMarketOrders,
|
||||
signatures,
|
||||
optimizedFeeOrders,
|
||||
feeSignatures,
|
||||
formattedFeePercentage,
|
||||
feeRecipientAddress,
|
||||
{
|
||||
value: ethAmount,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
nonce: orderTransactionOpts.nonce,
|
||||
},
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Attempt to purchase makerAssetFillAmount of makerAsset by selling ethAmount provided with transaction.
|
||||
* Any ZRX required to pay fees for primary orders will automatically be purchased by the contract.
|
||||
* Any ETH not spent will be refunded to sender.
|
||||
* @param signedOrders An array of objects that conform to the SignedOrder interface. All orders must specify the same makerAsset.
|
||||
* All orders must specify WETH as the takerAsset
|
||||
* @param makerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
|
||||
* @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied
|
||||
* Provider provided at instantiation.
|
||||
* @param ethAmount The amount of eth to send with the transaction (in wei).
|
||||
* @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset.
|
||||
* Used to purchase ZRX for primary order fees.
|
||||
* @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
* Defaults to 0.
|
||||
* @param feeRecipientAddress The address that will receive ETH when signedFeeOrders are filled.
|
||||
* @param orderTransactionOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async marketBuyOrdersWithEthAsync(
|
||||
signedOrders: SignedOrder[],
|
||||
makerAssetFillAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
ethAmount: BigNumber,
|
||||
signedFeeOrders: SignedOrder[] = [],
|
||||
feePercentage: number = 0,
|
||||
feeRecipientAddress: string = constants.NULL_ADDRESS,
|
||||
orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
|
||||
): Promise<string> {
|
||||
// type assertions
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
assert.isBigNumber('ethAmount', ethAmount);
|
||||
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
|
||||
assert.isNumber('feePercentage', feePercentage);
|
||||
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
// other assertions
|
||||
assert.ordersCanBeUsedForForwarderContract(signedOrders, this.etherTokenAddress);
|
||||
assert.feeOrdersCanBeUsedForForwarderContract(signedFeeOrders, this.zrxTokenAddress, this.etherTokenAddress);
|
||||
// format feePercentage
|
||||
const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
|
||||
// lowercase input addresses
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
|
||||
// optimize orders
|
||||
const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders);
|
||||
const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders);
|
||||
// compile signatures
|
||||
const signatures = _.map(optimizedMarketOrders, order => order.signature);
|
||||
const feeSignatures = _.map(optimizedFeeOrders, order => order.signature);
|
||||
// validate transaction
|
||||
if (orderTransactionOpts.shouldValidate) {
|
||||
await this._forwarderContract.marketBuyOrdersWithEth.callAsync(
|
||||
optimizedMarketOrders,
|
||||
makerAssetFillAmount,
|
||||
signatures,
|
||||
optimizedFeeOrders,
|
||||
feeSignatures,
|
||||
formattedFeePercentage,
|
||||
normalizedFeeRecipientAddress,
|
||||
{
|
||||
value: ethAmount,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
nonce: orderTransactionOpts.nonce,
|
||||
},
|
||||
);
|
||||
}
|
||||
// send transaction
|
||||
const txHash = await this._forwarderContract.marketBuyOrdersWithEth.sendTransactionAsync(
|
||||
optimizedMarketOrders,
|
||||
makerAssetFillAmount,
|
||||
signatures,
|
||||
optimizedFeeOrders,
|
||||
feeSignatures,
|
||||
formattedFeePercentage,
|
||||
feeRecipientAddress,
|
||||
{
|
||||
value: ethAmount,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
nonce: orderTransactionOpts.nonce,
|
||||
},
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
import { OrderValidatorContract } from '@0x/abi-gen-wrappers';
|
||||
import { OrderValidator } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { _getDefaultContractAddresses } from '../utils/contract_addresses';
|
||||
|
||||
/**
|
||||
* This class includes the functionality related to interacting with the OrderValidator contract.
|
||||
*/
|
||||
export class OrderValidatorWrapper {
|
||||
public abi: ContractAbi = OrderValidator.compilerOutput.abi;
|
||||
public address: string;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _orderValidatorContract: OrderValidatorContract;
|
||||
/**
|
||||
* Instantiate OrderValidatorWrapper
|
||||
* @param web3Wrapper Web3Wrapper instance to use.
|
||||
* @param networkId Desired networkId.
|
||||
* @param address The address of the OrderValidator contract. If undefined,
|
||||
* will default to the known address corresponding to the networkId.
|
||||
*/
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this.address = address === undefined ? _getDefaultContractAddresses(networkId).orderValidator : address;
|
||||
this._orderValidatorContract = new OrderValidatorContract(
|
||||
this.address,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Get an object conforming to OrderAndTraderInfo containing on-chain information of the provided order and address
|
||||
* @param order An object conforming to SignedOrder
|
||||
* @param takerAddress An ethereum address
|
||||
* @return OrderAndTraderInfo
|
||||
*/
|
||||
public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> {
|
||||
assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
|
||||
assert.isETHAddressHex('takerAddress', takerAddress);
|
||||
const orderAndTraderInfo = await this._orderValidatorContract.getOrderAndTraderInfo.callAsync(
|
||||
order,
|
||||
takerAddress,
|
||||
);
|
||||
const result = {
|
||||
orderInfo: orderAndTraderInfo[0],
|
||||
traderInfo: orderAndTraderInfo[1],
|
||||
};
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get an array of objects conforming to OrderAndTraderInfo containing on-chain information of the provided orders and addresses
|
||||
* @param orders An array of objects conforming to SignedOrder
|
||||
* @param takerAddresses An array of ethereum addresses
|
||||
* @return array of OrderAndTraderInfo
|
||||
*/
|
||||
public async getOrdersAndTradersInfoAsync(
|
||||
orders: SignedOrder[],
|
||||
takerAddresses: string[],
|
||||
): Promise<OrderAndTraderInfo[]> {
|
||||
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
|
||||
_.forEach(takerAddresses, (takerAddress, index) =>
|
||||
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
|
||||
);
|
||||
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
|
||||
const ordersAndTradersInfo = await this._orderValidatorContract.getOrdersAndTradersInfo.callAsync(
|
||||
orders,
|
||||
takerAddresses,
|
||||
);
|
||||
const orderInfos = ordersAndTradersInfo[0];
|
||||
const traderInfos = ordersAndTradersInfo[1];
|
||||
const result = _.map(orderInfos, (orderInfo, index) => {
|
||||
const traderInfo = traderInfos[index];
|
||||
return {
|
||||
orderInfo,
|
||||
traderInfo,
|
||||
};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get an object conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order
|
||||
* @param order An object conforming to SignedOrder
|
||||
* @param takerAddress An ethereum address
|
||||
* @return TraderInfo
|
||||
*/
|
||||
public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> {
|
||||
assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
|
||||
assert.isETHAddressHex('takerAddress', takerAddress);
|
||||
const result = await this._orderValidatorContract.getTraderInfo.callAsync(order, takerAddress);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get an array of objects conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order
|
||||
* @param orders An array of objects conforming to SignedOrder
|
||||
* @param takerAddresses An array of ethereum addresses
|
||||
* @return array of TraderInfo
|
||||
*/
|
||||
public async getTradersInfoAsync(orders: SignedOrder[], takerAddresses: string[]): Promise<TraderInfo[]> {
|
||||
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
|
||||
_.forEach(takerAddresses, (takerAddress, index) =>
|
||||
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
|
||||
);
|
||||
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
|
||||
const result = await this._orderValidatorContract.getTradersInfo.callAsync(orders, takerAddresses);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get an object conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and assetData
|
||||
* @param address An ethereum address
|
||||
* @param assetData An encoded string that can be decoded by a specified proxy contract
|
||||
* @return BalanceAndAllowance
|
||||
*/
|
||||
public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> {
|
||||
assert.isETHAddressHex('address', address);
|
||||
assert.isHexString('assetData', assetData);
|
||||
const balanceAndAllowance = await this._orderValidatorContract.getBalanceAndAllowance.callAsync(
|
||||
address,
|
||||
assetData,
|
||||
);
|
||||
const result = {
|
||||
balance: balanceAndAllowance[0],
|
||||
allowance: balanceAndAllowance[1],
|
||||
};
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get an array of objects conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and array of assetDatas
|
||||
* @param address An ethereum address
|
||||
* @param assetDatas An array of encoded strings that can be decoded by a specified proxy contract
|
||||
* @return BalanceAndAllowance
|
||||
*/
|
||||
public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> {
|
||||
assert.isETHAddressHex('address', address);
|
||||
_.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData));
|
||||
const balancesAndAllowances = await this._orderValidatorContract.getBalancesAndAllowances.callAsync(
|
||||
address,
|
||||
assetDatas,
|
||||
);
|
||||
const balances = balancesAndAllowances[0];
|
||||
const allowances = balancesAndAllowances[1];
|
||||
const result = _.map(balances, (balance, index) => {
|
||||
const allowance = allowances[index];
|
||||
return {
|
||||
balance,
|
||||
allowance,
|
||||
};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get owner address of tokenId by calling `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.
|
||||
* @param tokenAddress An ethereum address
|
||||
* @param tokenId An ERC721 tokenId
|
||||
* @return Owner of tokenId or null address if unowned
|
||||
*/
|
||||
public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isBigNumber('tokenId', tokenId);
|
||||
const result = await this._orderValidatorContract.getERC721TokenOwner.callAsync(tokenAddress, tokenId);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import { CoordinatorContract, CoordinatorRegistryContract, ExchangeContract } from '@0x/abi-gen-wrappers';
|
||||
import { getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses';
|
||||
import { Coordinator } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
@ -10,10 +9,12 @@ import { ContractAbi } from 'ethereum-types';
|
||||
import * as HttpStatus from 'http-status-codes';
|
||||
import { flatten } from 'lodash';
|
||||
|
||||
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
|
||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
||||
import { CoordinatorTransaction, OrderTransactionOpts } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { CoordinatorContract, CoordinatorRegistryContract, ExchangeContract } from './index';
|
||||
|
||||
import { orderTxOptsSchema } from './schemas/order_tx_opts_schema';
|
||||
import { txOptsSchema } from './schemas/tx_opts_schema';
|
||||
import { CoordinatorTransaction, OrderTransactionOpts } from './types';
|
||||
import { assert } from './utils/assert';
|
||||
import {
|
||||
CoordinatorServerApprovalRawResponse,
|
||||
CoordinatorServerApprovalResponse,
|
||||
@ -21,9 +22,9 @@ import {
|
||||
CoordinatorServerError,
|
||||
CoordinatorServerErrorMsg,
|
||||
CoordinatorServerResponse,
|
||||
} from '../utils/coordinator_server_types';
|
||||
import { decorators } from '../utils/decorators';
|
||||
import { TransactionEncoder } from '../utils/transaction_encoder';
|
||||
} from './utils/coordinator_server_types';
|
||||
import { decorators } from './utils/decorators';
|
||||
import { getAbiEncodedTransactionData } from './utils/getAbiEncodedTransactionData';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to filling or cancelling orders through
|
||||
@ -39,7 +40,6 @@ export class CoordinatorWrapper {
|
||||
private readonly _contractInstance: CoordinatorContract;
|
||||
private readonly _registryInstance: CoordinatorRegistryContract;
|
||||
private readonly _exchangeInstance: ExchangeContract;
|
||||
private readonly _transactionEncoder: TransactionEncoder;
|
||||
private readonly _feeRecipientToEndpoint: { [feeRecipient: string]: string } = {};
|
||||
|
||||
/**
|
||||
@ -82,8 +82,6 @@ export class CoordinatorWrapper {
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
|
||||
this._transactionEncoder = new TransactionEncoder(this._exchangeInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +110,12 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.fillOrderTx(signedOrder, takerAssetFillAmount);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'fillOrder',
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
signedOrder.signature,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -139,7 +142,12 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.fillOrderNoThrowTx(signedOrder, takerAssetFillAmount);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'fillOrderNoThrow',
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
signedOrder.signature,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -167,7 +175,12 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.fillOrKillOrderTx(signedOrder, takerAssetFillAmount);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'fillOrKillOrder',
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
signedOrder.signature,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -201,7 +214,13 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.batchFillOrdersTx(signedOrders, takerAssetFillAmounts);
|
||||
const signatures = signedOrders.map(o => o.signature);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'batchFillOrders',
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
signatures,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -230,7 +249,13 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.batchFillOrdersNoThrowTx(signedOrders, takerAssetFillAmounts);
|
||||
const signatures = signedOrders.map(o => o.signature);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'batchFillOrdersNoThrow',
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
signatures,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -259,7 +284,13 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.batchFillOrKillOrdersTx(signedOrders, takerAssetFillAmounts);
|
||||
const signatures = signedOrders.map(o => o.signature);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'batchFillOrKillOrders',
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
signatures,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -291,7 +322,13 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.marketBuyOrdersTx(signedOrders, makerAssetFillAmount);
|
||||
const signatures = signedOrders.map(o => o.signature);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'marketBuyOrders',
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -323,7 +360,13 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.marketSellOrdersTx(signedOrders, takerAssetFillAmount);
|
||||
const signatures = signedOrders.map(o => o.signature);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'marketSellOrders',
|
||||
signedOrders,
|
||||
takerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -350,7 +393,13 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.marketBuyOrdersNoThrowTx(signedOrders, makerAssetFillAmount);
|
||||
const signatures = signedOrders.map(o => o.signature);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'marketBuyOrdersNoThrow',
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -377,7 +426,13 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.marketSellOrdersNoThrowTx(signedOrders, takerAssetFillAmount);
|
||||
const signatures = signedOrders.map(o => o.signature);
|
||||
const data = this._getAbiEncodedTransactionData(
|
||||
'marketSellOrdersNoThrow',
|
||||
signedOrders,
|
||||
takerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||
return txHash;
|
||||
}
|
||||
@ -394,7 +449,7 @@ export class CoordinatorWrapper {
|
||||
assert.isETHAddressHex('feeRecipientAddress', order.feeRecipientAddress);
|
||||
assert.isSenderAddressAsync('makerAddress', order.makerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.cancelOrderTx(order);
|
||||
const data = this._getAbiEncodedTransactionData('cancelOrder', order);
|
||||
const transaction = await this._generateSignedZeroExTransactionAsync(data, order.makerAddress);
|
||||
const endpoint = await this._getServerEndpointOrThrowAsync(order.feeRecipientAddress);
|
||||
|
||||
@ -428,7 +483,7 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
|
||||
const makerAddress = getMakerAddressOrThrow(orders);
|
||||
assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
|
||||
const data = this._transactionEncoder.batchCancelOrdersTx(orders);
|
||||
const data = this._getAbiEncodedTransactionData('batchCancelOrders', orders);
|
||||
|
||||
const serverEndpointsToOrders = await this._mapServerEndpointsToOrdersAsync(orders);
|
||||
|
||||
@ -486,7 +541,7 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('makerAddress', order.makerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.cancelOrderTx(order);
|
||||
const data = this._getAbiEncodedTransactionData('cancelOrder', order);
|
||||
const transaction = await this._generateSignedZeroExTransactionAsync(data, order.makerAddress);
|
||||
|
||||
const approvalSignatures = new Array();
|
||||
@ -519,7 +574,7 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.batchCancelOrdersTx(orders);
|
||||
const data = this._getAbiEncodedTransactionData('batchCancelOrders', orders);
|
||||
const transaction = await this._generateSignedZeroExTransactionAsync(data, makerAddress);
|
||||
|
||||
const approvalSignatures = new Array();
|
||||
@ -554,7 +609,7 @@ export class CoordinatorWrapper {
|
||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
|
||||
|
||||
const data = this._transactionEncoder.cancelOrdersUpToTx(targetOrderEpoch);
|
||||
const data = this._getAbiEncodedTransactionData('cancelOrdersUpTo', targetOrderEpoch);
|
||||
const transaction = await this._generateSignedZeroExTransactionAsync(data, senderAddress);
|
||||
|
||||
const approvalSignatures = new Array();
|
||||
@ -618,6 +673,10 @@ export class CoordinatorWrapper {
|
||||
return signerAddress;
|
||||
}
|
||||
|
||||
private _getAbiEncodedTransactionData<K extends keyof ExchangeContract>(methodName: K, ...args: any[]): string {
|
||||
return getAbiEncodedTransactionData(this._exchangeInstance, methodName, ...args);
|
||||
}
|
||||
|
||||
private async _handleFillsAsync(
|
||||
data: string,
|
||||
takerAddress: string,
|
@ -1,91 +0,0 @@
|
||||
import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0x/order-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { BlockParamLiteral } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper';
|
||||
import { ERC721TokenWrapper } from '../contract_wrappers/erc721_token_wrapper';
|
||||
|
||||
export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {
|
||||
private readonly _erc20Token: ERC20TokenWrapper;
|
||||
private readonly _erc721Token: ERC721TokenWrapper;
|
||||
private readonly _stateLayer: BlockParamLiteral;
|
||||
constructor(erc20Token: ERC20TokenWrapper, erc721Token: ERC721TokenWrapper, stateLayer: BlockParamLiteral) {
|
||||
this._erc20Token = erc20Token;
|
||||
this._erc721Token = erc721Token;
|
||||
this._stateLayer = stateLayer;
|
||||
}
|
||||
public async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
|
||||
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
|
||||
let balance: BigNumber | undefined;
|
||||
if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
|
||||
balance = await this._erc20Token.getBalanceAsync(decodedAssetData.tokenAddress, userAddress, {
|
||||
defaultBlock: this._stateLayer,
|
||||
});
|
||||
} else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
|
||||
const tokenOwner = await this._erc721Token.getOwnerOfAsync(
|
||||
decodedAssetData.tokenAddress,
|
||||
decodedAssetData.tokenId,
|
||||
{
|
||||
defaultBlock: this._stateLayer,
|
||||
},
|
||||
);
|
||||
balance = tokenOwner === userAddress ? new BigNumber(1) : new BigNumber(0);
|
||||
} else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
|
||||
// The `balance` for MultiAssetData is the total units of the entire `assetData` that are held by the `userAddress`.
|
||||
for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) {
|
||||
const nestedAmountElement = decodedAssetData.amounts[index];
|
||||
const nestedAssetBalance = (await this.getBalanceAsync(
|
||||
nestedAssetDataElement,
|
||||
userAddress,
|
||||
)).dividedToIntegerBy(nestedAmountElement);
|
||||
if (balance === undefined || nestedAssetBalance.isLessThan(balance)) {
|
||||
balance = nestedAssetBalance;
|
||||
}
|
||||
}
|
||||
}
|
||||
return balance as BigNumber;
|
||||
}
|
||||
public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
|
||||
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
|
||||
let proxyAllowance: BigNumber | undefined;
|
||||
if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
|
||||
proxyAllowance = await this._erc20Token.getProxyAllowanceAsync(decodedAssetData.tokenAddress, userAddress, {
|
||||
defaultBlock: this._stateLayer,
|
||||
});
|
||||
} else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
|
||||
const isApprovedForAll = await this._erc721Token.isProxyApprovedForAllAsync(
|
||||
decodedAssetData.tokenAddress,
|
||||
userAddress,
|
||||
{
|
||||
defaultBlock: this._stateLayer,
|
||||
},
|
||||
);
|
||||
if (isApprovedForAll) {
|
||||
return new BigNumber(this._erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
} else {
|
||||
const isApproved = await this._erc721Token.isProxyApprovedAsync(
|
||||
decodedAssetData.tokenAddress,
|
||||
decodedAssetData.tokenId,
|
||||
{
|
||||
defaultBlock: this._stateLayer,
|
||||
},
|
||||
);
|
||||
proxyAllowance = isApproved ? new BigNumber(1) : new BigNumber(0);
|
||||
}
|
||||
} else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
|
||||
// The `proxyAllowance` for MultiAssetData is the total units of the entire `assetData` that the proxies have been approved to spend by the `userAddress`.
|
||||
for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) {
|
||||
const nestedAmountElement = decodedAssetData.amounts[index];
|
||||
const nestedAssetAllowance = (await this.getProxyAllowanceAsync(
|
||||
nestedAssetDataElement,
|
||||
userAddress,
|
||||
)).dividedToIntegerBy(nestedAmountElement);
|
||||
if (proxyAllowance === undefined || nestedAssetAllowance.isLessThan(proxyAllowance)) {
|
||||
proxyAllowance = nestedAssetAllowance;
|
||||
}
|
||||
}
|
||||
}
|
||||
return proxyAllowance as BigNumber;
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
import { AbstractOrderFilledCancelledFetcher, orderHashUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { BlockParamLiteral } from 'ethereum-types';
|
||||
|
||||
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||
|
||||
export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher {
|
||||
private readonly _exchange: ExchangeWrapper;
|
||||
private readonly _stateLayer: BlockParamLiteral;
|
||||
constructor(exchange: ExchangeWrapper, stateLayer: BlockParamLiteral) {
|
||||
this._exchange = exchange;
|
||||
this._stateLayer = stateLayer;
|
||||
}
|
||||
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
||||
const filledTakerAmount = this._exchange.getFilledTakerAssetAmountAsync(orderHash, {
|
||||
defaultBlock: this._stateLayer,
|
||||
});
|
||||
return filledTakerAmount;
|
||||
}
|
||||
public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const isCancelled = await this._exchange.isCancelledAsync(orderHash);
|
||||
const orderEpoch = await this._exchange.getOrderEpochAsync(
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.senderAddress,
|
||||
{
|
||||
defaultBlock: this._stateLayer,
|
||||
},
|
||||
);
|
||||
const isCancelledByOrderEpoch = orderEpoch > signedOrder.salt;
|
||||
return isCancelled || isCancelledByOrderEpoch;
|
||||
}
|
||||
public getZRXAssetData(): string {
|
||||
const zrxAssetData = this._exchange.getZRXAssetData();
|
||||
return zrxAssetData;
|
||||
}
|
||||
}
|
3984
packages/contract-wrappers/src/generated-wrappers/asset_proxy_owner.ts
generated
Normal file
3984
packages/contract-wrappers/src/generated-wrappers/asset_proxy_owner.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1377
packages/contract-wrappers/src/generated-wrappers/coordinator.ts
generated
Normal file
1377
packages/contract-wrappers/src/generated-wrappers/coordinator.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
511
packages/contract-wrappers/src/generated-wrappers/coordinator_registry.ts
generated
Normal file
511
packages/contract-wrappers/src/generated-wrappers/coordinator_registry.ts
generated
Normal file
@ -0,0 +1,511 @@
|
||||
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
|
||||
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace
|
||||
// tslint:disable:no-unused-variable
|
||||
import {
|
||||
BaseContract,
|
||||
BlockRange,
|
||||
EventCallback,
|
||||
IndexedFilterValues,
|
||||
SubscriptionManager,
|
||||
PromiseWithTransactionHash,
|
||||
} from '@0x/base-contract';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import {
|
||||
BlockParam,
|
||||
BlockParamLiteral,
|
||||
CallData,
|
||||
ContractAbi,
|
||||
ContractArtifact,
|
||||
DecodedLogArgs,
|
||||
LogWithDecodedArgs,
|
||||
MethodAbi,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
TxData,
|
||||
TxDataPayable,
|
||||
SupportedProvider,
|
||||
} from 'ethereum-types';
|
||||
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
|
||||
import { SimpleContractArtifact } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
export type CoordinatorRegistryEventArgs = CoordinatorRegistryCoordinatorEndpointSetEventArgs;
|
||||
|
||||
export enum CoordinatorRegistryEvents {
|
||||
CoordinatorEndpointSet = 'CoordinatorEndpointSet',
|
||||
}
|
||||
|
||||
export interface CoordinatorRegistryCoordinatorEndpointSetEventArgs extends DecodedLogArgs {
|
||||
coordinatorOperator: string;
|
||||
coordinatorEndpoint: string;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class CoordinatorRegistryContract extends BaseContract {
|
||||
/**
|
||||
* Called by a Coordinator operator to set the endpoint of their Coordinator.
|
||||
*/
|
||||
public setCoordinatorEndpoint = {
|
||||
/**
|
||||
* Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write
|
||||
* Ethereum operation and will cost gas.
|
||||
* @param coordinatorEndpoint endpoint of the Coordinator.
|
||||
* @param txData Additional data for transaction
|
||||
* @returns The hash of the transaction
|
||||
*/
|
||||
async sendTransactionAsync(coordinatorEndpoint: string, txData?: Partial<TxData> | undefined): Promise<string> {
|
||||
assert.isString('coordinatorEndpoint', coordinatorEndpoint);
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const encodedData = self._strictEncodeArguments('setCoordinatorEndpoint(string)', [coordinatorEndpoint]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.setCoordinatorEndpoint.estimateGasAsync.bind(self, coordinatorEndpoint),
|
||||
);
|
||||
if (txDataWithDefaults.from !== undefined) {
|
||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||
}
|
||||
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
/**
|
||||
* Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting.
|
||||
* If the transaction was mined, but reverted, an error is thrown.
|
||||
* @param coordinatorEndpoint endpoint of the Coordinator.
|
||||
* @param txData Additional data for transaction
|
||||
* @param pollingIntervalMs Interval at which to poll for success
|
||||
* @returns A promise that resolves when the transaction is successful
|
||||
*/
|
||||
awaitTransactionSuccessAsync(
|
||||
coordinatorEndpoint: string,
|
||||
txData?: Partial<TxData>,
|
||||
pollingIntervalMs?: number,
|
||||
timeoutMs?: number,
|
||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
||||
assert.isString('coordinatorEndpoint', coordinatorEndpoint);
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const txHashPromise = self.setCoordinatorEndpoint.sendTransactionAsync(coordinatorEndpoint, txData);
|
||||
return new PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>(
|
||||
txHashPromise,
|
||||
(async (): Promise<TransactionReceiptWithDecodedLogs> => {
|
||||
// When the transaction hash resolves, wait for it to be mined.
|
||||
return self._web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await txHashPromise,
|
||||
pollingIntervalMs,
|
||||
timeoutMs,
|
||||
);
|
||||
})(),
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments.
|
||||
* @param coordinatorEndpoint endpoint of the Coordinator.
|
||||
* @param txData Additional data for transaction
|
||||
* @returns The hash of the transaction
|
||||
*/
|
||||
async estimateGasAsync(coordinatorEndpoint: string, txData?: Partial<TxData> | undefined): Promise<number> {
|
||||
assert.isString('coordinatorEndpoint', coordinatorEndpoint);
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const encodedData = self._strictEncodeArguments('setCoordinatorEndpoint(string)', [coordinatorEndpoint]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
if (txDataWithDefaults.from !== undefined) {
|
||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||
}
|
||||
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
/**
|
||||
* Sends a read-only call to the contract method. Returns the result that would happen if one were to send an
|
||||
* Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas
|
||||
* since they don't modify state.
|
||||
* @param coordinatorEndpoint endpoint of the Coordinator.
|
||||
*/
|
||||
async callAsync(
|
||||
coordinatorEndpoint: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void> {
|
||||
assert.isString('coordinatorEndpoint', coordinatorEndpoint);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const encodedData = self._strictEncodeArguments('setCoordinatorEndpoint(string)', [coordinatorEndpoint]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('setCoordinatorEndpoint(string)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before
|
||||
* sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used
|
||||
* to create a 0x transaction (see protocol spec for more details).
|
||||
* @param coordinatorEndpoint endpoint of the Coordinator.
|
||||
*/
|
||||
getABIEncodedTransactionData(coordinatorEndpoint: string): string {
|
||||
assert.isString('coordinatorEndpoint', coordinatorEndpoint);
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('setCoordinatorEndpoint(string)', [
|
||||
coordinatorEndpoint,
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
getABIDecodedTransactionData(callData: string): void {
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('setCoordinatorEndpoint(string)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedCallData = abiEncoder.strictDecode<void>(callData);
|
||||
return abiDecodedCallData;
|
||||
},
|
||||
getABIDecodedReturnData(returnData: string): void {
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('setCoordinatorEndpoint(string)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<void>(returnData);
|
||||
return abiDecodedReturnData;
|
||||
},
|
||||
};
|
||||
/**
|
||||
* Gets the endpoint for a Coordinator.
|
||||
*/
|
||||
public getCoordinatorEndpoint = {
|
||||
/**
|
||||
* Sends a read-only call to the contract method. Returns the result that would happen if one were to send an
|
||||
* Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas
|
||||
* since they don't modify state.
|
||||
* @param coordinatorOperator operator of the Coordinator endpoint.
|
||||
*/
|
||||
async callAsync(
|
||||
coordinatorOperator: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<string> {
|
||||
assert.isString('coordinatorOperator', coordinatorOperator);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const encodedData = self._strictEncodeArguments('getCoordinatorEndpoint(address)', [
|
||||
coordinatorOperator.toLowerCase(),
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('getCoordinatorEndpoint(address)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before
|
||||
* sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used
|
||||
* to create a 0x transaction (see protocol spec for more details).
|
||||
* @param coordinatorOperator operator of the Coordinator endpoint.
|
||||
*/
|
||||
getABIEncodedTransactionData(coordinatorOperator: string): string {
|
||||
assert.isString('coordinatorOperator', coordinatorOperator);
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('getCoordinatorEndpoint(address)', [
|
||||
coordinatorOperator.toLowerCase(),
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
getABIDecodedTransactionData(callData: string): string {
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('getCoordinatorEndpoint(address)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedCallData = abiEncoder.strictDecode<string>(callData);
|
||||
return abiDecodedCallData;
|
||||
},
|
||||
getABIDecodedReturnData(returnData: string): string {
|
||||
const self = (this as any) as CoordinatorRegistryContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('getCoordinatorEndpoint(address)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<string>(returnData);
|
||||
return abiDecodedReturnData;
|
||||
},
|
||||
};
|
||||
private readonly _subscriptionManager: SubscriptionManager<CoordinatorRegistryEventArgs, CoordinatorRegistryEvents>;
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
|
||||
): Promise<CoordinatorRegistryContract> {
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (artifact.compilerOutput === undefined) {
|
||||
throw new Error('Compiler output not found in the artifact file');
|
||||
}
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return CoordinatorRegistryContract.deployAsync(
|
||||
bytecode,
|
||||
abi,
|
||||
provider,
|
||||
txDefaults,
|
||||
logDecodeDependenciesAbiOnly,
|
||||
);
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
abi: ContractAbi,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractAbi },
|
||||
): Promise<CoordinatorRegistryContract> {
|
||||
assert.isHexString('bytecode', bytecode);
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{ data: txData },
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
||||
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
logUtils.log(`transactionHash: ${txHash}`);
|
||||
const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
logUtils.log(`CoordinatorRegistry successfully deployed at ${txReceipt.contractAddress}`);
|
||||
const contractInstance = new CoordinatorRegistryContract(
|
||||
txReceipt.contractAddress as string,
|
||||
provider,
|
||||
txDefaults,
|
||||
logDecodeDependencies,
|
||||
);
|
||||
contractInstance.constructorArgs = [];
|
||||
return contractInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The contract ABI
|
||||
*/
|
||||
public static ABI(): ContractAbi {
|
||||
const abi = [
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'coordinatorEndpoint',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
name: 'setCoordinatorEndpoint',
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 'coordinatorOperator',
|
||||
type: 'address',
|
||||
},
|
||||
],
|
||||
name: 'getCoordinatorEndpoint',
|
||||
outputs: [
|
||||
{
|
||||
name: 'coordinatorEndpoint',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'constructor',
|
||||
},
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'coordinatorOperator',
|
||||
type: 'address',
|
||||
indexed: false,
|
||||
},
|
||||
{
|
||||
name: 'coordinatorEndpoint',
|
||||
type: 'string',
|
||||
indexed: false,
|
||||
},
|
||||
],
|
||||
name: 'CoordinatorEndpointSet',
|
||||
outputs: [],
|
||||
type: 'event',
|
||||
},
|
||||
] as ContractAbi;
|
||||
return abi;
|
||||
}
|
||||
/**
|
||||
* Subscribe to an event type emitted by the CoordinatorRegistry contract.
|
||||
* @param eventName The CoordinatorRegistry contract event you would like to subscribe to.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
|
||||
* @param callback Callback that gets called when a log is added/removed
|
||||
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends CoordinatorRegistryEventArgs>(
|
||||
eventName: CoordinatorRegistryEvents,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>,
|
||||
isVerbose: boolean = false,
|
||||
blockPollingIntervalMs?: number,
|
||||
): string {
|
||||
assert.doesBelongToStringEnum('eventName', eventName, CoordinatorRegistryEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
|
||||
this.address,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
CoordinatorRegistryContract.ABI(),
|
||||
callback,
|
||||
isVerbose,
|
||||
blockPollingIntervalMs,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
/**
|
||||
* Cancel a subscription
|
||||
* @param subscriptionToken Subscription token returned by `subscribe()`
|
||||
*/
|
||||
public unsubscribe(subscriptionToken: string): void {
|
||||
this._subscriptionManager.unsubscribe(subscriptionToken);
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
this._subscriptionManager.unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
* Gets historical logs without creating a subscription
|
||||
* @param eventName The CoordinatorRegistry contract event you would like to subscribe to.
|
||||
* @param blockRange Block range to get logs from.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends CoordinatorRegistryEventArgs>(
|
||||
eventName: CoordinatorRegistryEvents,
|
||||
blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.doesBelongToStringEnum('eventName', eventName, CoordinatorRegistryEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
|
||||
this.address,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
CoordinatorRegistryContract.ABI(),
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
constructor(
|
||||
address: string,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults?: Partial<TxData>,
|
||||
logDecodeDependencies?: { [contractName: string]: ContractAbi },
|
||||
) {
|
||||
super(
|
||||
'CoordinatorRegistry',
|
||||
CoordinatorRegistryContract.ABI(),
|
||||
address,
|
||||
supportedProvider,
|
||||
txDefaults,
|
||||
logDecodeDependencies,
|
||||
);
|
||||
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
|
||||
this._subscriptionManager = new SubscriptionManager<CoordinatorRegistryEventArgs, CoordinatorRegistryEvents>(
|
||||
CoordinatorRegistryContract.ABI(),
|
||||
this._web3Wrapper,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable:max-file-line-count
|
||||
// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align
|
||||
// tslint:enable:trailing-comma whitespace no-trailing-whitespace
|
2142
packages/contract-wrappers/src/generated-wrappers/dummy_erc20_token.ts
generated
Normal file
2142
packages/contract-wrappers/src/generated-wrappers/dummy_erc20_token.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
2642
packages/contract-wrappers/src/generated-wrappers/dummy_erc721_token.ts
generated
Normal file
2642
packages/contract-wrappers/src/generated-wrappers/dummy_erc721_token.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1172
packages/contract-wrappers/src/generated-wrappers/dutch_auction.ts
generated
Normal file
1172
packages/contract-wrappers/src/generated-wrappers/dutch_auction.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1368
packages/contract-wrappers/src/generated-wrappers/erc20_proxy.ts
generated
Normal file
1368
packages/contract-wrappers/src/generated-wrappers/erc20_proxy.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1183
packages/contract-wrappers/src/generated-wrappers/erc20_token.ts
generated
Normal file
1183
packages/contract-wrappers/src/generated-wrappers/erc20_token.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1368
packages/contract-wrappers/src/generated-wrappers/erc721_proxy.ts
generated
Normal file
1368
packages/contract-wrappers/src/generated-wrappers/erc721_proxy.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1825
packages/contract-wrappers/src/generated-wrappers/erc721_token.ts
generated
Normal file
1825
packages/contract-wrappers/src/generated-wrappers/erc721_token.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
215
packages/contract-wrappers/src/generated-wrappers/eth_balance_checker.ts
generated
Normal file
215
packages/contract-wrappers/src/generated-wrappers/eth_balance_checker.ts
generated
Normal file
@ -0,0 +1,215 @@
|
||||
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
|
||||
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace
|
||||
// tslint:disable:no-unused-variable
|
||||
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import {
|
||||
BlockParam,
|
||||
BlockParamLiteral,
|
||||
CallData,
|
||||
ContractAbi,
|
||||
ContractArtifact,
|
||||
DecodedLogArgs,
|
||||
MethodAbi,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
TxData,
|
||||
TxDataPayable,
|
||||
SupportedProvider,
|
||||
} from 'ethereum-types';
|
||||
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
|
||||
import { SimpleContractArtifact } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class EthBalanceCheckerContract extends BaseContract {
|
||||
/**
|
||||
* Batch fetches ETH balances
|
||||
*/
|
||||
public getEthBalances = {
|
||||
/**
|
||||
* Sends a read-only call to the contract method. Returns the result that would happen if one were to send an
|
||||
* Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas
|
||||
* since they don't modify state.
|
||||
* @param addresses Array of addresses.
|
||||
* @returns Array of ETH balances.
|
||||
*/
|
||||
async callAsync(
|
||||
addresses: string[],
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<BigNumber[]> {
|
||||
assert.isArray('addresses', addresses);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as EthBalanceCheckerContract;
|
||||
const encodedData = self._strictEncodeArguments('getEthBalances(address[])', [addresses]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('getEthBalances(address[])');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before
|
||||
* sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used
|
||||
* to create a 0x transaction (see protocol spec for more details).
|
||||
* @param addresses Array of addresses.
|
||||
*/
|
||||
getABIEncodedTransactionData(addresses: string[]): string {
|
||||
assert.isArray('addresses', addresses);
|
||||
const self = (this as any) as EthBalanceCheckerContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('getEthBalances(address[])', [addresses]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
getABIDecodedTransactionData(callData: string): BigNumber[] {
|
||||
const self = (this as any) as EthBalanceCheckerContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('getEthBalances(address[])');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedCallData = abiEncoder.strictDecode<BigNumber[]>(callData);
|
||||
return abiDecodedCallData;
|
||||
},
|
||||
getABIDecodedReturnData(returnData: string): BigNumber[] {
|
||||
const self = (this as any) as EthBalanceCheckerContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('getEthBalances(address[])');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<BigNumber[]>(returnData);
|
||||
return abiDecodedReturnData;
|
||||
},
|
||||
};
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
|
||||
): Promise<EthBalanceCheckerContract> {
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (artifact.compilerOutput === undefined) {
|
||||
throw new Error('Compiler output not found in the artifact file');
|
||||
}
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return EthBalanceCheckerContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
abi: ContractAbi,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractAbi },
|
||||
): Promise<EthBalanceCheckerContract> {
|
||||
assert.isHexString('bytecode', bytecode);
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{ data: txData },
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
||||
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
logUtils.log(`transactionHash: ${txHash}`);
|
||||
const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
logUtils.log(`EthBalanceChecker successfully deployed at ${txReceipt.contractAddress}`);
|
||||
const contractInstance = new EthBalanceCheckerContract(
|
||||
txReceipt.contractAddress as string,
|
||||
provider,
|
||||
txDefaults,
|
||||
logDecodeDependencies,
|
||||
);
|
||||
contractInstance.constructorArgs = [];
|
||||
return contractInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The contract ABI
|
||||
*/
|
||||
public static ABI(): ContractAbi {
|
||||
const abi = [
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 'addresses',
|
||||
type: 'address[]',
|
||||
},
|
||||
],
|
||||
name: 'getEthBalances',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256[]',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
] as ContractAbi;
|
||||
return abi;
|
||||
}
|
||||
constructor(
|
||||
address: string,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults?: Partial<TxData>,
|
||||
logDecodeDependencies?: { [contractName: string]: ContractAbi },
|
||||
) {
|
||||
super(
|
||||
'EthBalanceChecker',
|
||||
EthBalanceCheckerContract.ABI(),
|
||||
address,
|
||||
supportedProvider,
|
||||
txDefaults,
|
||||
logDecodeDependencies,
|
||||
);
|
||||
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable:max-file-line-count
|
||||
// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align
|
||||
// tslint:enable:trailing-comma whitespace no-trailing-whitespace
|
8623
packages/contract-wrappers/src/generated-wrappers/exchange.ts
generated
Normal file
8623
packages/contract-wrappers/src/generated-wrappers/exchange.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
2022
packages/contract-wrappers/src/generated-wrappers/forwarder.ts
generated
Normal file
2022
packages/contract-wrappers/src/generated-wrappers/forwarder.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1225
packages/contract-wrappers/src/generated-wrappers/i_asset_proxy.ts
generated
Normal file
1225
packages/contract-wrappers/src/generated-wrappers/i_asset_proxy.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
234
packages/contract-wrappers/src/generated-wrappers/i_validator.ts
generated
Normal file
234
packages/contract-wrappers/src/generated-wrappers/i_validator.ts
generated
Normal file
@ -0,0 +1,234 @@
|
||||
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
|
||||
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace
|
||||
// tslint:disable:no-unused-variable
|
||||
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import {
|
||||
BlockParam,
|
||||
BlockParamLiteral,
|
||||
CallData,
|
||||
ContractAbi,
|
||||
ContractArtifact,
|
||||
DecodedLogArgs,
|
||||
MethodAbi,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
TxData,
|
||||
TxDataPayable,
|
||||
SupportedProvider,
|
||||
} from 'ethereum-types';
|
||||
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
|
||||
import { SimpleContractArtifact } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class IValidatorContract extends BaseContract {
|
||||
/**
|
||||
* Verifies that a signature is valid.
|
||||
*/
|
||||
public isValidSignature = {
|
||||
/**
|
||||
* Sends a read-only call to the contract method. Returns the result that would happen if one were to send an
|
||||
* Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas
|
||||
* since they don't modify state.
|
||||
* @param hash Message hash that is signed.
|
||||
* @param signerAddress Address that should have signed the given hash.
|
||||
* @param signature Proof of signing.
|
||||
* @returns Validity of order signature.
|
||||
*/
|
||||
async callAsync(
|
||||
hash: string,
|
||||
signerAddress: string,
|
||||
signature: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<boolean> {
|
||||
assert.isString('hash', hash);
|
||||
assert.isString('signerAddress', signerAddress);
|
||||
assert.isString('signature', signature);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as IValidatorContract;
|
||||
const encodedData = self._strictEncodeArguments('isValidSignature(bytes32,address,bytes)', [
|
||||
hash,
|
||||
signerAddress.toLowerCase(),
|
||||
signature,
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,address,bytes)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<boolean>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before
|
||||
* sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used
|
||||
* to create a 0x transaction (see protocol spec for more details).
|
||||
* @param hash Message hash that is signed.
|
||||
* @param signerAddress Address that should have signed the given hash.
|
||||
* @param signature Proof of signing.
|
||||
*/
|
||||
getABIEncodedTransactionData(hash: string, signerAddress: string, signature: string): string {
|
||||
assert.isString('hash', hash);
|
||||
assert.isString('signerAddress', signerAddress);
|
||||
assert.isString('signature', signature);
|
||||
const self = (this as any) as IValidatorContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('isValidSignature(bytes32,address,bytes)', [
|
||||
hash,
|
||||
signerAddress.toLowerCase(),
|
||||
signature,
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
getABIDecodedTransactionData(callData: string): boolean {
|
||||
const self = (this as any) as IValidatorContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,address,bytes)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedCallData = abiEncoder.strictDecode<boolean>(callData);
|
||||
return abiDecodedCallData;
|
||||
},
|
||||
getABIDecodedReturnData(returnData: string): boolean {
|
||||
const self = (this as any) as IValidatorContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,address,bytes)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<boolean>(returnData);
|
||||
return abiDecodedReturnData;
|
||||
},
|
||||
};
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
|
||||
): Promise<IValidatorContract> {
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (artifact.compilerOutput === undefined) {
|
||||
throw new Error('Compiler output not found in the artifact file');
|
||||
}
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return IValidatorContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
abi: ContractAbi,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractAbi },
|
||||
): Promise<IValidatorContract> {
|
||||
assert.isHexString('bytecode', bytecode);
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{ data: txData },
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
||||
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
logUtils.log(`transactionHash: ${txHash}`);
|
||||
const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
logUtils.log(`IValidator successfully deployed at ${txReceipt.contractAddress}`);
|
||||
const contractInstance = new IValidatorContract(
|
||||
txReceipt.contractAddress as string,
|
||||
provider,
|
||||
txDefaults,
|
||||
logDecodeDependencies,
|
||||
);
|
||||
contractInstance.constructorArgs = [];
|
||||
return contractInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The contract ABI
|
||||
*/
|
||||
public static ABI(): ContractAbi {
|
||||
const abi = [
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 'hash',
|
||||
type: 'bytes32',
|
||||
},
|
||||
{
|
||||
name: 'signerAddress',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'signature',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
name: 'isValidSignature',
|
||||
outputs: [
|
||||
{
|
||||
name: 'isValid',
|
||||
type: 'bool',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
] as ContractAbi;
|
||||
return abi;
|
||||
}
|
||||
constructor(
|
||||
address: string,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults?: Partial<TxData>,
|
||||
logDecodeDependencies?: { [contractName: string]: ContractAbi },
|
||||
) {
|
||||
super('IValidator', IValidatorContract.ABI(), address, supportedProvider, txDefaults, logDecodeDependencies);
|
||||
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable:max-file-line-count
|
||||
// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align
|
||||
// tslint:enable:trailing-comma whitespace no-trailing-whitespace
|
220
packages/contract-wrappers/src/generated-wrappers/i_wallet.ts
generated
Normal file
220
packages/contract-wrappers/src/generated-wrappers/i_wallet.ts
generated
Normal file
@ -0,0 +1,220 @@
|
||||
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
|
||||
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace
|
||||
// tslint:disable:no-unused-variable
|
||||
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import {
|
||||
BlockParam,
|
||||
BlockParamLiteral,
|
||||
CallData,
|
||||
ContractAbi,
|
||||
ContractArtifact,
|
||||
DecodedLogArgs,
|
||||
MethodAbi,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
TxData,
|
||||
TxDataPayable,
|
||||
SupportedProvider,
|
||||
} from 'ethereum-types';
|
||||
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
|
||||
import { SimpleContractArtifact } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class IWalletContract extends BaseContract {
|
||||
/**
|
||||
* Verifies that a signature is valid.
|
||||
*/
|
||||
public isValidSignature = {
|
||||
/**
|
||||
* Sends a read-only call to the contract method. Returns the result that would happen if one were to send an
|
||||
* Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas
|
||||
* since they don't modify state.
|
||||
* @param hash Message hash that is signed.
|
||||
* @param signature Proof of signing.
|
||||
* @returns Validity of order signature.
|
||||
*/
|
||||
async callAsync(
|
||||
hash: string,
|
||||
signature: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<boolean> {
|
||||
assert.isString('hash', hash);
|
||||
assert.isString('signature', signature);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as IWalletContract;
|
||||
const encodedData = self._strictEncodeArguments('isValidSignature(bytes32,bytes)', [hash, signature]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<boolean>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before
|
||||
* sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used
|
||||
* to create a 0x transaction (see protocol spec for more details).
|
||||
* @param hash Message hash that is signed.
|
||||
* @param signature Proof of signing.
|
||||
*/
|
||||
getABIEncodedTransactionData(hash: string, signature: string): string {
|
||||
assert.isString('hash', hash);
|
||||
assert.isString('signature', signature);
|
||||
const self = (this as any) as IWalletContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('isValidSignature(bytes32,bytes)', [
|
||||
hash,
|
||||
signature,
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
getABIDecodedTransactionData(callData: string): boolean {
|
||||
const self = (this as any) as IWalletContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedCallData = abiEncoder.strictDecode<boolean>(callData);
|
||||
return abiDecodedCallData;
|
||||
},
|
||||
getABIDecodedReturnData(returnData: string): boolean {
|
||||
const self = (this as any) as IWalletContract;
|
||||
const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)');
|
||||
// tslint:disable boolean-naming
|
||||
const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<boolean>(returnData);
|
||||
return abiDecodedReturnData;
|
||||
},
|
||||
};
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
|
||||
): Promise<IWalletContract> {
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (artifact.compilerOutput === undefined) {
|
||||
throw new Error('Compiler output not found in the artifact file');
|
||||
}
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||
for (const key of Object.keys(logDecodeDependencies)) {
|
||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||
}
|
||||
}
|
||||
return IWalletContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
abi: ContractAbi,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
logDecodeDependencies: { [contractName: string]: ContractAbi },
|
||||
): Promise<IWalletContract> {
|
||||
assert.isHexString('bytecode', bytecode);
|
||||
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{ data: txData },
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
||||
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
logUtils.log(`transactionHash: ${txHash}`);
|
||||
const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
logUtils.log(`IWallet successfully deployed at ${txReceipt.contractAddress}`);
|
||||
const contractInstance = new IWalletContract(
|
||||
txReceipt.contractAddress as string,
|
||||
provider,
|
||||
txDefaults,
|
||||
logDecodeDependencies,
|
||||
);
|
||||
contractInstance.constructorArgs = [];
|
||||
return contractInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The contract ABI
|
||||
*/
|
||||
public static ABI(): ContractAbi {
|
||||
const abi = [
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 'hash',
|
||||
type: 'bytes32',
|
||||
},
|
||||
{
|
||||
name: 'signature',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
name: 'isValidSignature',
|
||||
outputs: [
|
||||
{
|
||||
name: 'isValid',
|
||||
type: 'bool',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
] as ContractAbi;
|
||||
return abi;
|
||||
}
|
||||
constructor(
|
||||
address: string,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults?: Partial<TxData>,
|
||||
logDecodeDependencies?: { [contractName: string]: ContractAbi },
|
||||
) {
|
||||
super('IWallet', IWalletContract.ABI(), address, supportedProvider, txDefaults, logDecodeDependencies);
|
||||
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable:max-file-line-count
|
||||
// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align
|
||||
// tslint:enable:trailing-comma whitespace no-trailing-whitespace
|
1747
packages/contract-wrappers/src/generated-wrappers/multi_asset_proxy.ts
generated
Normal file
1747
packages/contract-wrappers/src/generated-wrappers/multi_asset_proxy.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1662
packages/contract-wrappers/src/generated-wrappers/order_validator.ts
generated
Normal file
1662
packages/contract-wrappers/src/generated-wrappers/order_validator.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1690
packages/contract-wrappers/src/generated-wrappers/weth9.ts
generated
Normal file
1690
packages/contract-wrappers/src/generated-wrappers/weth9.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
1365
packages/contract-wrappers/src/generated-wrappers/zrx_token.ts
generated
Normal file
1365
packages/contract-wrappers/src/generated-wrappers/zrx_token.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,124 +1,26 @@
|
||||
export { ContractAddresses } from '@0x/contract-addresses';
|
||||
export * from './generated-wrappers/asset_proxy_owner';
|
||||
export * from './generated-wrappers/dummy_erc20_token';
|
||||
export * from './generated-wrappers/dummy_erc721_token';
|
||||
export * from './generated-wrappers/dutch_auction';
|
||||
export * from './generated-wrappers/erc20_proxy';
|
||||
export * from './generated-wrappers/erc20_token';
|
||||
export * from './generated-wrappers/erc721_proxy';
|
||||
export * from './generated-wrappers/erc721_token';
|
||||
export * from './generated-wrappers/exchange';
|
||||
export * from './generated-wrappers/forwarder';
|
||||
export * from './generated-wrappers/i_asset_proxy';
|
||||
export * from './generated-wrappers/i_validator';
|
||||
export * from './generated-wrappers/i_wallet';
|
||||
export * from './generated-wrappers/multi_asset_proxy';
|
||||
export * from './generated-wrappers/order_validator';
|
||||
export * from './generated-wrappers/weth9';
|
||||
export * from './generated-wrappers/zrx_token';
|
||||
export * from './generated-wrappers/coordinator';
|
||||
export * from './generated-wrappers/coordinator_registry';
|
||||
export * from './generated-wrappers/eth_balance_checker';
|
||||
|
||||
export {
|
||||
WETH9Events,
|
||||
WETH9WithdrawalEventArgs,
|
||||
WETH9ApprovalEventArgs,
|
||||
WETH9EventArgs,
|
||||
WETH9DepositEventArgs,
|
||||
WETH9TransferEventArgs,
|
||||
ERC20TokenTransferEventArgs,
|
||||
ERC20TokenApprovalEventArgs,
|
||||
ERC20TokenEvents,
|
||||
ERC20TokenEventArgs,
|
||||
ERC721TokenApprovalEventArgs,
|
||||
ERC721TokenApprovalForAllEventArgs,
|
||||
ERC721TokenTransferEventArgs,
|
||||
ERC721TokenEvents,
|
||||
ERC721TokenEventArgs,
|
||||
ExchangeCancelUpToEventArgs,
|
||||
ExchangeAssetProxyRegisteredEventArgs,
|
||||
ExchangeSignatureValidatorApprovalEventArgs,
|
||||
ExchangeFillEventArgs,
|
||||
ExchangeCancelEventArgs,
|
||||
ExchangeEventArgs,
|
||||
ExchangeEvents,
|
||||
} from '@0x/abi-gen-wrappers';
|
||||
export * from '@0x/contract-addresses';
|
||||
|
||||
export { ContractWrappers } from './contract_wrappers';
|
||||
export { CoordinatorWrapper } from './contract_wrappers/coordinator_wrapper';
|
||||
export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
|
||||
export { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
|
||||
export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
|
||||
export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
|
||||
export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
|
||||
export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
|
||||
export { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
|
||||
export { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper';
|
||||
export { DutchAuctionWrapper } from './contract_wrappers/dutch_auction_wrapper';
|
||||
|
||||
export { TransactionEncoder } from './utils/transaction_encoder';
|
||||
|
||||
export { AbiDecoder, DecodedCalldata } from '@0x/utils';
|
||||
|
||||
export {
|
||||
ContractWrappersError,
|
||||
ForwarderWrapperError,
|
||||
IndexedFilterValues,
|
||||
BlockRange,
|
||||
ContractWrappersConfig,
|
||||
MethodOpts,
|
||||
OrderTransactionOpts,
|
||||
TransactionOpts,
|
||||
OrderStatus,
|
||||
OrderInfo,
|
||||
EventCallback,
|
||||
DecodedLogEvent,
|
||||
BalanceAndAllowance,
|
||||
OrderAndTraderInfo,
|
||||
TraderInfo,
|
||||
ValidateOrderFillableOpts,
|
||||
CoordinatorServerCancellationResponse,
|
||||
CoordinatorServerError,
|
||||
} from './types';
|
||||
|
||||
export {
|
||||
AssetData,
|
||||
ERC20AssetData,
|
||||
ERC721AssetData,
|
||||
ERC1155AssetData,
|
||||
SingleAssetData,
|
||||
MultiAssetData,
|
||||
StaticCallAssetData,
|
||||
MultiAssetDataWithRecursiveDecoding,
|
||||
DutchAuctionDetails,
|
||||
DutchAuctionData,
|
||||
Order,
|
||||
SignedOrder,
|
||||
AssetProxyId,
|
||||
SignedZeroExTransaction,
|
||||
ZeroExTransaction,
|
||||
} from '@0x/types';
|
||||
|
||||
export {
|
||||
BlockParamLiteral,
|
||||
BlockParam,
|
||||
ContractEventArg,
|
||||
SupportedProvider,
|
||||
ContractAbi,
|
||||
JSONRPCRequestPayload,
|
||||
JSONRPCResponsePayload,
|
||||
JSONRPCErrorCallback,
|
||||
JSONRPCResponseError,
|
||||
AbiDefinition,
|
||||
LogWithDecodedArgs,
|
||||
LogEntry,
|
||||
DecodedLogEntry,
|
||||
DecodedLogEntryEvent,
|
||||
LogEntryEvent,
|
||||
RawLog,
|
||||
FunctionAbi,
|
||||
EventAbi,
|
||||
EventParameter,
|
||||
DecodedLogArgs,
|
||||
MethodAbi,
|
||||
ConstructorAbi,
|
||||
FallbackAbi,
|
||||
DataItem,
|
||||
TupleDataItem,
|
||||
ConstructorStateMutability,
|
||||
StateMutability,
|
||||
Web3JsProvider,
|
||||
GanacheProvider,
|
||||
EIP1193Provider,
|
||||
ZeroExProvider,
|
||||
EIP1193Event,
|
||||
Web3JsV1Provider,
|
||||
Web3JsV2Provider,
|
||||
Web3JsV3Provider,
|
||||
} from 'ethereum-types';
|
||||
|
||||
export { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher } from '@0x/order-utils';
|
||||
|
||||
export { AssetBalanceAndProxyAllowanceFetcher } from './fetchers/asset_balance_and_proxy_allowance_fetcher';
|
||||
export { OrderFilledCancelledFetcher } from './fetchers/order_filled_cancelled_fetcher';
|
||||
export { CoordinatorWrapper } from './coordinator_wrapper';
|
||||
export { OrderStatus } from './types';
|
||||
|
@ -1,7 +0,0 @@
|
||||
export const methodOptsSchema = {
|
||||
id: '/MethodOpts',
|
||||
properties: {
|
||||
defaultBlock: { $ref: '/blockParamSchema' },
|
||||
},
|
||||
type: 'object',
|
||||
};
|
@ -1,7 +0,0 @@
|
||||
export const validateOrderFillableOptsSchema = {
|
||||
id: '/ValidateOrderFillableOpts',
|
||||
properties: {
|
||||
expectedFillTakerTokenAmount: { $ref: '/wholeNumberSchema' },
|
||||
},
|
||||
type: 'object',
|
||||
};
|
@ -1,47 +1,8 @@
|
||||
import {
|
||||
ERC20TokenEventArgs,
|
||||
ERC20TokenEvents,
|
||||
ERC721TokenEventArgs,
|
||||
ERC721TokenEvents,
|
||||
ExchangeEventArgs,
|
||||
ExchangeEvents,
|
||||
WETH9EventArgs,
|
||||
WETH9Events,
|
||||
} from '@0x/abi-gen-wrappers';
|
||||
import { ContractAddresses } from '@0x/contract-addresses';
|
||||
import { OrderState, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { BlockParam, ContractEventArg, DecodedLogArgs, LogEntryEvent, LogWithDecodedArgs } from 'ethereum-types';
|
||||
import { ContractEventArg, DecodedLogArgs, LogWithDecodedArgs } from 'ethereum-types';
|
||||
|
||||
export enum ExchangeWrapperError {
|
||||
AssetDataMismatch = 'ASSET_DATA_MISMATCH',
|
||||
}
|
||||
|
||||
export enum ForwarderWrapperError {
|
||||
CompleteFillFailed = 'COMPLETE_FILL_FAILED',
|
||||
}
|
||||
|
||||
export enum ContractWrappersError {
|
||||
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
|
||||
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
|
||||
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
|
||||
InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT',
|
||||
InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
|
||||
InvalidJump = 'INVALID_JUMP',
|
||||
OutOfGas = 'OUT_OF_GAS',
|
||||
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
|
||||
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
|
||||
ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND',
|
||||
ERC721NoApproval = 'ERC_721_NO_APPROVAL',
|
||||
SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED',
|
||||
}
|
||||
|
||||
export enum InternalContractWrappersError {
|
||||
NoAbiDecoder = 'NO_ABI_DECODER',
|
||||
}
|
||||
|
||||
export type LogEvent = LogEntryEvent;
|
||||
export interface DecodedLogEvent<ArgsType extends DecodedLogArgs> {
|
||||
isRemoved: boolean;
|
||||
log: LogWithDecodedArgs<ArgsType>;
|
||||
@ -52,30 +13,6 @@ export type EventCallback<ArgsType extends DecodedLogArgs> = (
|
||||
log?: DecodedLogEvent<ArgsType>,
|
||||
) => void;
|
||||
|
||||
export interface ContractEvent {
|
||||
logIndex: number;
|
||||
transactionIndex: number;
|
||||
transactionHash: string;
|
||||
blockHash: string;
|
||||
blockNumber: number;
|
||||
address: string;
|
||||
type: string;
|
||||
event: string;
|
||||
args: ContractEventArgs;
|
||||
}
|
||||
|
||||
export type ContractEventArgs = ExchangeEventArgs | ERC20TokenEventArgs | ERC721TokenEventArgs | WETH9EventArgs;
|
||||
|
||||
// [address, name, symbol, decimals, ipfsHash, swarmHash]
|
||||
export type TokenMetadata = [string, string, string, number, string, string];
|
||||
|
||||
export interface Token {
|
||||
name: string;
|
||||
address: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
}
|
||||
|
||||
export interface TxOpts {
|
||||
from: string;
|
||||
gas?: number;
|
||||
@ -83,29 +20,10 @@ export interface TxOpts {
|
||||
gasPrice?: BigNumber;
|
||||
}
|
||||
|
||||
export interface TokenAddressBySymbol {
|
||||
[symbol: string]: string;
|
||||
}
|
||||
|
||||
export type ContractEvents = ERC20TokenEvents | ERC721TokenEvents | ExchangeEvents | WETH9Events;
|
||||
|
||||
export interface IndexedFilterValues {
|
||||
[index: string]: ContractEventArg;
|
||||
}
|
||||
|
||||
export interface BlockRange {
|
||||
fromBlock: BlockParam;
|
||||
toBlock: BlockParam;
|
||||
}
|
||||
|
||||
export interface OrderFillRequest {
|
||||
signedOrder: SignedOrder;
|
||||
takerAssetFillAmount: BigNumber;
|
||||
}
|
||||
|
||||
export type AsyncMethod = (...args: any[]) => Promise<any>;
|
||||
export type SyncMethod = (...args: any[]) => any;
|
||||
|
||||
/**
|
||||
* networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 42-kovan, 50-testrpc)
|
||||
* gasPrice: Gas price to use with every transaction
|
||||
@ -119,35 +37,6 @@ export interface ContractWrappersConfig {
|
||||
blockPollingIntervalMs?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* `expectedFillTakerTokenAmount`: If specified, the validation method will ensure that the supplied order maker has a sufficient
|
||||
* allowance/balance to fill this amount of the order's takerTokenAmount.
|
||||
*
|
||||
* `validateRemainingOrderAmountIsFillable`: The validation method ensures that the maker has sufficient allowance/balance to fill
|
||||
* the entire remaining order amount. If this option is set to false, the balances
|
||||
* and allowances are calculated to determine the order is fillable for a
|
||||
* non-zero amount (some value less than or equal to the order remaining amount).
|
||||
* We call such orders "partially fillable orders". Default is `true`.
|
||||
*
|
||||
* `simulationTakerAddress`: During the maker transfer simulation, tokens are sent from the maker to the `simulationTakerAddress`. This defaults
|
||||
* to the `takerAddress` specified in the order. Some tokens prevent transfer to the NULL address so this address can be specified.
|
||||
*/
|
||||
export interface ValidateOrderFillableOpts {
|
||||
expectedFillTakerTokenAmount?: BigNumber;
|
||||
validateRemainingOrderAmountIsFillable?: boolean;
|
||||
simulationTakerAddress?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number
|
||||
* let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the
|
||||
* backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive`
|
||||
* flag when running Parity).
|
||||
*/
|
||||
export interface MethodOpts {
|
||||
defaultBlock?: BlockParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* gasPrice: Gas price in Wei to use for a transaction
|
||||
* gasLimit: The amount of gas to send with a transaction (in Gwei)
|
||||
@ -167,18 +56,6 @@ export interface OrderTransactionOpts extends TransactionOpts {
|
||||
shouldValidate?: boolean;
|
||||
}
|
||||
|
||||
export enum TradeSide {
|
||||
Maker = 'maker',
|
||||
Taker = 'taker',
|
||||
}
|
||||
|
||||
export enum TransferType {
|
||||
Trade = 'trade',
|
||||
Fee = 'fee',
|
||||
}
|
||||
|
||||
export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
|
||||
|
||||
export interface OrderInfo {
|
||||
orderStatus: OrderStatus;
|
||||
orderHash: string;
|
||||
@ -195,31 +72,6 @@ export enum OrderStatus {
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
export interface TraderInfo {
|
||||
makerBalance: BigNumber;
|
||||
makerAllowance: BigNumber;
|
||||
takerBalance: BigNumber;
|
||||
takerAllowance: BigNumber;
|
||||
makerZrxBalance: BigNumber;
|
||||
makerZrxAllowance: BigNumber;
|
||||
takerZrxBalance: BigNumber;
|
||||
takerZrxAllowance: BigNumber;
|
||||
}
|
||||
|
||||
export interface OrderAndTraderInfo {
|
||||
orderInfo: OrderInfo;
|
||||
traderInfo: TraderInfo;
|
||||
}
|
||||
|
||||
export interface BalanceAndAllowance {
|
||||
balance: BigNumber;
|
||||
allowance: BigNumber;
|
||||
}
|
||||
|
||||
export enum DutchAuctionWrapperError {
|
||||
AssetDataMismatch = 'ASSET_DATA_MISMATCH',
|
||||
}
|
||||
|
||||
export { CoordinatorServerCancellationResponse, CoordinatorServerError } from './utils/coordinator_server_types';
|
||||
|
||||
export interface CoordinatorTransaction {
|
||||
|
@ -8,7 +8,7 @@ import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { SupportedProvider } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from './constants';
|
||||
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
export const assert = {
|
||||
...sharedAssert,
|
||||
@ -56,7 +56,7 @@ export const assert = {
|
||||
}
|
||||
},
|
||||
allTakerAddressesAreNull(orders: Order[]): void {
|
||||
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', constants.NULL_ADDRESS);
|
||||
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', NULL_ADDRESS);
|
||||
},
|
||||
allMakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void {
|
||||
assert.ordersHaveAtMostOneUniqueValueForProperty(
|
||||
|
@ -1,44 +0,0 @@
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
export const calldataOptimizationUtils = {
|
||||
/**
|
||||
* Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and
|
||||
* all makerAssetData are '0x' except for that of the first order, which retains its original value
|
||||
* @param orders An array of SignedOrder objects
|
||||
* @returns optimized orders
|
||||
*/
|
||||
optimizeForwarderOrders(orders: SignedOrder[]): SignedOrder[] {
|
||||
const optimizedOrders = _.map(orders, (order, index) =>
|
||||
transformOrder(order, {
|
||||
makerAssetData: index === 0 ? order.makerAssetData : constants.NULL_BYTES,
|
||||
takerAssetData: constants.NULL_BYTES,
|
||||
}),
|
||||
);
|
||||
return optimizedOrders;
|
||||
},
|
||||
/**
|
||||
* Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and
|
||||
* all makerAssetData are '0x'
|
||||
* @param orders An array of SignedOrder objects
|
||||
* @returns optimized orders
|
||||
*/
|
||||
optimizeForwarderFeeOrders(orders: SignedOrder[]): SignedOrder[] {
|
||||
const optimizedOrders = _.map(orders, (order, index) =>
|
||||
transformOrder(order, {
|
||||
makerAssetData: constants.NULL_BYTES,
|
||||
takerAssetData: constants.NULL_BYTES,
|
||||
}),
|
||||
);
|
||||
return optimizedOrders;
|
||||
},
|
||||
};
|
||||
|
||||
const transformOrder = (order: SignedOrder, partialOrder: Partial<SignedOrder>) => {
|
||||
return {
|
||||
...order,
|
||||
...partialOrder,
|
||||
};
|
||||
};
|
@ -1,19 +0,0 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
NULL_BYTES: '0x',
|
||||
TESTRPC_NETWORK_ID: 50,
|
||||
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
||||
REVERT: 'revert',
|
||||
OUT_OF_GAS_PATTERN: 'out of gas',
|
||||
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
||||
DEFAULT_BLOCK_POLLING_INTERVAL: 1000,
|
||||
ZERO_AMOUNT: new BigNumber(0),
|
||||
ONE_AMOUNT: new BigNumber(1),
|
||||
ETHER_TOKEN_DECIMALS: 18,
|
||||
METAMASK_USER_DENIED_SIGNATURE_PATTERN: 'User denied transaction signature',
|
||||
TRUST_WALLET_USER_DENIED_SIGNATURE_PATTERN: 'cancelled',
|
||||
};
|
@ -1,8 +1,31 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { AsyncMethod, ContractWrappersError, SyncMethod } from '../types';
|
||||
export enum ContractWrappersError {
|
||||
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
|
||||
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
|
||||
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
|
||||
InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT',
|
||||
InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
|
||||
InvalidJump = 'INVALID_JUMP',
|
||||
OutOfGas = 'OUT_OF_GAS',
|
||||
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
|
||||
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
|
||||
ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND',
|
||||
ERC721NoApproval = 'ERC_721_NO_APPROVAL',
|
||||
SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED',
|
||||
}
|
||||
|
||||
import { constants } from './constants';
|
||||
export type AsyncMethod = (...args: any[]) => Promise<any>;
|
||||
export type SyncMethod = (...args: any[]) => any;
|
||||
|
||||
const constants = {
|
||||
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
||||
REVERT: 'revert',
|
||||
OUT_OF_GAS_PATTERN: 'out of gas',
|
||||
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
|
||||
METAMASK_USER_DENIED_SIGNATURE_PATTERN: 'User denied transaction signature',
|
||||
TRUST_WALLET_USER_DENIED_SIGNATURE_PATTERN: 'cancelled',
|
||||
};
|
||||
|
||||
type ErrorTransformer = (err: Error) => Error;
|
||||
|
||||
|
@ -1,87 +0,0 @@
|
||||
import { ContractAbi, EventAbi, FilterObject, LogEntry } from 'ethereum-types';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as jsSHA3 from 'js-sha3';
|
||||
import * as _ from 'lodash';
|
||||
import * as uuid from 'uuid/v4';
|
||||
|
||||
import { BlockRange, ContractEvents, IndexedFilterValues } from '../types';
|
||||
|
||||
const TOPIC_LENGTH = 32;
|
||||
|
||||
export const filterUtils = {
|
||||
generateUUID(): string {
|
||||
return uuid();
|
||||
},
|
||||
getFilter(
|
||||
address: string,
|
||||
eventName: ContractEvents,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
abi: ContractAbi,
|
||||
blockRange?: BlockRange,
|
||||
): FilterObject {
|
||||
const eventAbi = _.find(abi, { name: eventName }) as EventAbi;
|
||||
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi);
|
||||
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
|
||||
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
|
||||
const topics = [topicForEventSignature, ...topicsForIndexedArgs];
|
||||
let filter: FilterObject = {
|
||||
address,
|
||||
topics,
|
||||
};
|
||||
if (blockRange !== undefined) {
|
||||
filter = {
|
||||
...blockRange,
|
||||
...filter,
|
||||
};
|
||||
}
|
||||
return filter;
|
||||
},
|
||||
getEventSignatureFromAbiByName(eventAbi: EventAbi): string {
|
||||
const types = _.map(eventAbi.inputs, 'type');
|
||||
const signature = `${eventAbi.name}(${types.join(',')})`;
|
||||
return signature;
|
||||
},
|
||||
getTopicsForIndexedArgs(abi: EventAbi, indexFilterValues: IndexedFilterValues): Array<string | null> {
|
||||
const topics: Array<string | null> = [];
|
||||
for (const eventInput of abi.inputs) {
|
||||
if (!eventInput.indexed) {
|
||||
continue;
|
||||
}
|
||||
if (indexFilterValues[eventInput.name] === undefined) {
|
||||
// Null is a wildcard topic in a JSON-RPC call
|
||||
topics.push(null);
|
||||
} else {
|
||||
const value = indexFilterValues[eventInput.name] as string;
|
||||
const buffer = ethUtil.toBuffer(value);
|
||||
const paddedBuffer = ethUtil.setLengthLeft(buffer, TOPIC_LENGTH);
|
||||
const topic = ethUtil.bufferToHex(paddedBuffer);
|
||||
topics.push(topic);
|
||||
}
|
||||
}
|
||||
return topics;
|
||||
},
|
||||
matchesFilter(log: LogEntry, filter: FilterObject): boolean {
|
||||
if (filter.address !== undefined && log.address !== filter.address) {
|
||||
return false;
|
||||
}
|
||||
if (filter.topics !== undefined) {
|
||||
return filterUtils.doesMatchTopics(log.topics, filter.topics);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
doesMatchTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean {
|
||||
const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils));
|
||||
const doesMatchTopics = _.every(matchesTopic);
|
||||
return doesMatchTopics;
|
||||
},
|
||||
matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean {
|
||||
if (_.isArray(filterTopic)) {
|
||||
return _.includes(filterTopic, logTopic);
|
||||
}
|
||||
if (_.isString(filterTopic)) {
|
||||
return filterTopic === logTopic;
|
||||
}
|
||||
// null topic is a wildcard
|
||||
return true;
|
||||
},
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
import { ExchangeContract } from '../index';
|
||||
|
||||
/**
|
||||
* Returns the ABI encoded transaction hash for a given method and arguments
|
||||
* @param methodName Must be a valid name of a function in the Solidity Exchange Contract
|
||||
* @param params The appropriate arguments for the method given, in order
|
||||
*/
|
||||
export function getAbiEncodedTransactionData<K extends keyof ExchangeContract>(
|
||||
contractInstance: ExchangeContract,
|
||||
methodName: K,
|
||||
...params: any[] // tslint:disable-line:trailing-comma
|
||||
): string {
|
||||
// HACK (xianny): we haven't formalised contract method functions into a type interface, and would have to
|
||||
// differentiate contract method members from other class members to get this to work non-hackily
|
||||
const method = (contractInstance[methodName] as any) as {
|
||||
getABIEncodedTransactionData: (...args: any[]) => string;
|
||||
};
|
||||
if (method.getABIEncodedTransactionData) {
|
||||
const abiEncodedData = method.getABIEncodedTransactionData(...params);
|
||||
return abiEncodedData;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
import { ExchangeContract } from '@0x/abi-gen-wrappers';
|
||||
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { transactionHashUtils } from '@0x/order-utils';
|
||||
import { Order, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import _ = require('lodash');
|
||||
|
||||
import { assert } from './assert';
|
||||
|
||||
/**
|
||||
* Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract
|
||||
* in the context of another address. For example, UserA can encode and sign a fillOrder transaction and UserB
|
||||
* can submit this to the blockchain. The Exchange context executes as if UserA had directly submitted this transaction.
|
||||
*/
|
||||
export class TransactionEncoder {
|
||||
private readonly _exchangeInstance: ExchangeContract;
|
||||
constructor(exchangeInstance: ExchangeContract) {
|
||||
this._exchangeInstance = exchangeInstance;
|
||||
}
|
||||
/**
|
||||
* Hashes the transaction data for use with the Exchange contract.
|
||||
* @param data The ABI Encoded 0x Exchange method. I.e fillOrder
|
||||
* @param salt A random value to provide uniqueness and prevent replay attacks.
|
||||
* @param signerAddress The address which will sign this transaction.
|
||||
* @return The hash of the 0x transaction.
|
||||
*/
|
||||
public getTransactionHashHex(data: string, salt: BigNumber, signerAddress: string): string {
|
||||
const exchangeAddress = this._getExchangeContract().address;
|
||||
const transaction = {
|
||||
verifyingContractAddress: exchangeAddress,
|
||||
salt,
|
||||
signerAddress,
|
||||
data,
|
||||
};
|
||||
const hashHex = transactionHashUtils.getTransactionHashHex(transaction);
|
||||
return hashHex;
|
||||
}
|
||||
/**
|
||||
* Encodes a fillOrder transaction.
|
||||
* @param signedOrder An object that conforms to the SignedOrder interface.
|
||||
* @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public fillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
|
||||
const abiEncodedData = this._getExchangeContract().fillOrder.getABIEncodedTransactionData(
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
signedOrder.signature,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a fillOrderNoThrow transaction.
|
||||
* @param signedOrder An object that conforms to the SignedOrder interface.
|
||||
* @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public fillOrderNoThrowTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
|
||||
const abiEncodedData = this._getExchangeContract().fillOrderNoThrow.getABIEncodedTransactionData(
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
signedOrder.signature,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a fillOrKillOrder transaction.
|
||||
* @param signedOrder An object that conforms to the SignedOrder interface.
|
||||
* @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public fillOrKillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
|
||||
const abiEncodedData = this._getExchangeContract().fillOrKillOrder.getABIEncodedTransactionData(
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
signedOrder.signature,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a batchFillOrders transaction.
|
||||
* @param signedOrders An array of signed orders to fill.
|
||||
* @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public batchFillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
_.forEach(takerAssetFillAmounts, takerAssetFillAmount =>
|
||||
assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount),
|
||||
);
|
||||
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
|
||||
const abiEncodedData = this._getExchangeContract().batchFillOrders.getABIEncodedTransactionData(
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
signatures,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a batchFillOrKillOrders transaction.
|
||||
* @param signedOrders An array of signed orders to fill.
|
||||
* @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public batchFillOrKillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
_.forEach(takerAssetFillAmounts, takerAssetFillAmount =>
|
||||
assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount),
|
||||
);
|
||||
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
|
||||
const abiEncodedData = this._getExchangeContract().batchFillOrKillOrders.getABIEncodedTransactionData(
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
signatures,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a batchFillOrdersNoThrow transaction.
|
||||
* @param signedOrders An array of signed orders to fill.
|
||||
* @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public batchFillOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
_.forEach(takerAssetFillAmounts, takerAssetFillAmount =>
|
||||
assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount),
|
||||
);
|
||||
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
|
||||
const abiEncodedData = this._getExchangeContract().batchFillOrdersNoThrow.getABIEncodedTransactionData(
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
signatures,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a batchCancelOrders transaction.
|
||||
* @param signedOrders An array of orders to cancel.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public batchCancelOrdersTx(signedOrders: SignedOrder[]): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
const abiEncodedData = this._getExchangeContract().batchCancelOrders.getABIEncodedTransactionData(signedOrders);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a cancelOrdersUpTo transaction.
|
||||
* @param targetOrderEpoch Target order epoch.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public cancelOrdersUpToTx(targetOrderEpoch: BigNumber): string {
|
||||
assert.isBigNumber('targetOrderEpoch', targetOrderEpoch);
|
||||
const abiEncodedData = this._getExchangeContract().cancelOrdersUpTo.getABIEncodedTransactionData(
|
||||
targetOrderEpoch,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a cancelOrder transaction.
|
||||
* @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public cancelOrderTx(order: Order | SignedOrder): string {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
const abiEncodedData = this._getExchangeContract().cancelOrder.getABIEncodedTransactionData(order);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a marketSellOrders transaction.
|
||||
* @param signedOrders An array of signed orders to fill.
|
||||
* @param takerAssetFillAmount Taker asset fill amount.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public marketSellOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
|
||||
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
|
||||
const abiEncodedData = this._getExchangeContract().marketSellOrders.getABIEncodedTransactionData(
|
||||
signedOrders,
|
||||
takerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a marketSellOrdersNoThrow transaction.
|
||||
* @param signedOrders An array of signed orders to fill.
|
||||
* @param takerAssetFillAmount Taker asset fill amount.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public marketSellOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
|
||||
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
|
||||
const abiEncodedData = this._getExchangeContract().marketSellOrdersNoThrow.getABIEncodedTransactionData(
|
||||
signedOrders,
|
||||
takerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a maketBuyOrders transaction.
|
||||
* @param signedOrders An array of signed orders to fill.
|
||||
* @param makerAssetFillAmount Maker asset fill amount.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public marketBuyOrdersTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount);
|
||||
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
|
||||
const abiEncodedData = this._getExchangeContract().marketBuyOrders.getABIEncodedTransactionData(
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a maketBuyOrdersNoThrow transaction.
|
||||
* @param signedOrders An array of signed orders to fill.
|
||||
* @param makerAssetFillAmount Maker asset fill amount.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public marketBuyOrdersNoThrowTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount);
|
||||
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
|
||||
const abiEncodedData = this._getExchangeContract().marketBuyOrdersNoThrow.getABIEncodedTransactionData(
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
signatures,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a matchOrders transaction.
|
||||
* @param leftOrder First order to match.
|
||||
* @param rightOrder Second order to match.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public matchOrdersTx(leftOrder: SignedOrder, rightOrder: SignedOrder): string {
|
||||
assert.doesConformToSchema('leftOrder', leftOrder, schemas.orderSchema);
|
||||
assert.doesConformToSchema('rightOrder', rightOrder, schemas.orderSchema);
|
||||
const abiEncodedData = this._getExchangeContract().matchOrders.getABIEncodedTransactionData(
|
||||
leftOrder,
|
||||
rightOrder,
|
||||
leftOrder.signature,
|
||||
rightOrder.signature,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a preSign transaction.
|
||||
* @param hash Hash to pre-sign
|
||||
* @param signerAddress Address that should have signed the given hash.
|
||||
* @param signature Proof that the hash has been signed by signer.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public preSignTx(hash: string, signerAddress: string, signature: string): string {
|
||||
assert.isHexString('hash', hash);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
assert.isHexString('signature', signature);
|
||||
const abiEncodedData = this._getExchangeContract().preSign.getABIEncodedTransactionData(
|
||||
hash,
|
||||
signerAddress,
|
||||
signature,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
/**
|
||||
* Encodes a setSignatureValidatorApproval transaction.
|
||||
* @param validatorAddress Validator contract address.
|
||||
* @param isApproved Boolean value to set approval to.
|
||||
* @return Hex encoded abi of the function call.
|
||||
*/
|
||||
public setSignatureValidatorApprovalTx(validatorAddress: string, isApproved: boolean): string {
|
||||
assert.isETHAddressHex('validatorAddress', validatorAddress);
|
||||
assert.isBoolean('isApproved', isApproved);
|
||||
const abiEncodedData = this._getExchangeContract().setSignatureValidatorApproval.getABIEncodedTransactionData(
|
||||
validatorAddress,
|
||||
isApproved,
|
||||
);
|
||||
return abiEncodedData;
|
||||
}
|
||||
private _getExchangeContract(): ExchangeContract {
|
||||
return this._exchangeInstance;
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
export const utils = {
|
||||
getCurrentUnixTimestampSec(): BigNumber {
|
||||
const milisecondsInSecond = 1000;
|
||||
return new BigNumber(Date.now() / milisecondsInSecond).integerValue();
|
||||
},
|
||||
getCurrentUnixTimestampMs(): BigNumber {
|
||||
return new BigNumber(Date.now());
|
||||
},
|
||||
numberPercentageToEtherTokenAmountPercentage(percentage: number): BigNumber {
|
||||
return Web3Wrapper.toBaseUnitAmount(constants.ONE_AMOUNT, constants.ETHER_TOKEN_DECIMALS).multipliedBy(
|
||||
percentage,
|
||||
);
|
||||
},
|
||||
removeUndefinedProperties<T extends object>(obj: T): Partial<T> {
|
||||
return _.pickBy(obj);
|
||||
},
|
||||
};
|
@ -8,6 +8,7 @@ import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
|
||||
import { ContractAddresses, ContractWrappers } from '../src';
|
||||
import { getAbiEncodedTransactionData } from '../src/utils/getAbiEncodedTransactionData';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
@ -80,8 +81,14 @@ describe('ABI Decoding Calldata', () => {
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
const transactionEncoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
matchOrdersTxData = transactionEncoder.matchOrdersTx(signedOrderLeft, signedOrderRight);
|
||||
matchOrdersTxData = getAbiEncodedTransactionData(
|
||||
contractWrappers.exchange,
|
||||
'matchOrders',
|
||||
signedOrderLeft,
|
||||
signedOrderRight,
|
||||
signedOrderLeft.signature,
|
||||
signedOrderRight.signature,
|
||||
);
|
||||
});
|
||||
|
||||
describe('decode', () => {
|
||||
|
@ -1,59 +0,0 @@
|
||||
import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
|
||||
import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils';
|
||||
import { constants } from '../src/utils/constants';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
// utility for generating a set of order objects with mostly NULL values
|
||||
// except for a specified makerAssetData and takerAssetData
|
||||
const FAKE_ORDERS_COUNT = 5;
|
||||
const generateFakeOrders = (makerAssetData: string, takerAssetData: string) =>
|
||||
_.map(_.range(FAKE_ORDERS_COUNT), index => {
|
||||
const order = orderFactory.createOrder(
|
||||
constants.NULL_ADDRESS,
|
||||
constants.ZERO_AMOUNT,
|
||||
makerAssetData,
|
||||
constants.ZERO_AMOUNT,
|
||||
takerAssetData,
|
||||
constants.NULL_ADDRESS,
|
||||
);
|
||||
return {
|
||||
...order,
|
||||
signature: 'dummy signature',
|
||||
};
|
||||
});
|
||||
|
||||
describe('calldataOptimizationUtils', () => {
|
||||
const fakeMakerAssetData = 'fakeMakerAssetData';
|
||||
const fakeTakerAssetData = 'fakeTakerAssetData';
|
||||
const orders = generateFakeOrders(fakeMakerAssetData, fakeTakerAssetData);
|
||||
describe('#optimizeForwarderOrders', () => {
|
||||
it('should make makerAssetData `0x` unless first order', () => {
|
||||
const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders);
|
||||
expect(optimizedOrders[0].makerAssetData).to.equal(fakeMakerAssetData);
|
||||
const ordersWithoutHead = _.slice(optimizedOrders, 1);
|
||||
_.forEach(ordersWithoutHead, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES));
|
||||
});
|
||||
it('should make all takerAssetData `0x`', () => {
|
||||
const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders);
|
||||
_.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES));
|
||||
});
|
||||
});
|
||||
describe('#optimizeForwarderFeeOrders', () => {
|
||||
it('should make all makerAssetData `0x`', () => {
|
||||
const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders);
|
||||
_.forEach(optimizedOrders, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES));
|
||||
});
|
||||
it('should make all takerAssetData `0x`', () => {
|
||||
const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders);
|
||||
_.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES));
|
||||
});
|
||||
});
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
import { CoordinatorRegistryContract } from '@0x/abi-gen-wrappers';
|
||||
import { constants } from '@0x/contracts-test-utils';
|
||||
import { defaultOrmConfig, getAppAsync } from '@0x/coordinator-server';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
@ -16,7 +16,6 @@ import { CoordinatorServerErrorMsg } from '../src/utils/coordinator_server_types
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
@ -71,7 +70,7 @@ describe('CoordinatorWrapper', () => {
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
exchangeContractAddress = contractWrappers.exchange.address;
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress;
|
||||
zrxTokenAddress = contractAddresses.zrxToken;
|
||||
fillScenarios = new FillScenarios(
|
||||
provider,
|
||||
userAddresses,
|
||||
@ -422,7 +421,7 @@ describe('CoordinatorWrapper', () => {
|
||||
txHash = await contractWrappers.coordinator.hardCancelOrdersUpToAsync(targetOrderEpoch, makerAddress);
|
||||
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const orderEpoch = await contractWrappers.exchange.getOrderEpochAsync(
|
||||
const orderEpoch = await contractWrappers.exchange.orderEpoch.callAsync(
|
||||
makerAddress,
|
||||
contractWrappers.coordinator.address,
|
||||
);
|
||||
|
@ -1,143 +0,0 @@
|
||||
import { expectTransactionFailedAsync, getLatestBlockTimestampAsync } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { ERC20AssetData, RevertReason, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { ContractWrappers, DutchAuctionWrapper } from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { DutchAuctionUtils } from './utils/dutch_auction_utils';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
// tslint:disable:custom-no-magic-numbers
|
||||
describe('DutchAuctionWrapper', () => {
|
||||
const makerAssetAmount = new BigNumber(5);
|
||||
const auctionEndTakerAmount = new BigNumber(10);
|
||||
const auctionBeginTakerAmount = auctionEndTakerAmount.times(2);
|
||||
const tenMinutesInSeconds = 10 * 60;
|
||||
let contractWrappers: ContractWrappers;
|
||||
let exchangeContractAddress: string;
|
||||
let userAddresses: string[];
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let buyOrder: SignedOrder;
|
||||
let sellOrder: SignedOrder;
|
||||
let makerTokenAssetData: string;
|
||||
let takerTokenAssetData: string;
|
||||
let auctionBeginTimeSeconds: BigNumber;
|
||||
let auctionEndTimeSeconds: BigNumber;
|
||||
before(async () => {
|
||||
// setup contract wrappers & addresses
|
||||
const contractAddresses = await migrateOnceAsync();
|
||||
await blockchainLifecycle.startAsync();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
exchangeContractAddress = contractWrappers.exchange.address;
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
[, makerAddress, takerAddress] = userAddresses;
|
||||
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
// construct asset data for tokens being swapped
|
||||
[makerTokenAssetData, takerTokenAssetData] = [
|
||||
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
|
||||
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
|
||||
];
|
||||
// setup auction details in maker asset data
|
||||
const currentBlockTimestamp: number = await getLatestBlockTimestampAsync();
|
||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
|
||||
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp + tenMinutesInSeconds);
|
||||
// create auction orders
|
||||
const coinbase = userAddresses[0];
|
||||
const dutchAuctionUtils = new DutchAuctionUtils(
|
||||
web3Wrapper,
|
||||
coinbase,
|
||||
exchangeContractAddress,
|
||||
contractWrappers.erc20Proxy.address,
|
||||
);
|
||||
sellOrder = await dutchAuctionUtils.createSignedSellOrderAsync(
|
||||
auctionBeginTimeSeconds,
|
||||
auctionEndTimeSeconds,
|
||||
auctionBeginTakerAmount,
|
||||
auctionEndTakerAmount,
|
||||
makerAssetAmount,
|
||||
makerTokenAssetData,
|
||||
takerTokenAssetData,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
);
|
||||
buyOrder = await dutchAuctionUtils.createSignedBuyOrderAsync(sellOrder, takerAddress);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('.decodeDutchAuctionAssetData', () => {
|
||||
it('decodes to the encoded values', async () => {
|
||||
const encodedAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData(
|
||||
makerTokenAssetData,
|
||||
auctionBeginTimeSeconds,
|
||||
makerAssetAmount,
|
||||
);
|
||||
const decodedAssetData = DutchAuctionWrapper.decodeDutchAuctionData(encodedAssetData);
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const erc20AssetData = decodedAssetData.assetData as ERC20AssetData;
|
||||
expect(erc20AssetData.tokenAddress).to.eq(makerTokenAddress);
|
||||
expect(decodedAssetData.beginAmount).to.be.bignumber.eq(makerAssetAmount);
|
||||
expect(decodedAssetData.beginTimeSeconds).to.be.bignumber.eq(auctionBeginTimeSeconds);
|
||||
});
|
||||
});
|
||||
describe('#matchOrdersAsync', () => {
|
||||
it('should match two orders', async () => {
|
||||
const txHash = await contractWrappers.dutchAuction.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
it('should throw when invalid transaction and shouldValidate is true', async () => {
|
||||
// request match with bad buy/sell orders
|
||||
const badSellOrder = buyOrder;
|
||||
const badBuyOrder = sellOrder;
|
||||
return expectTransactionFailedAsync(
|
||||
contractWrappers.dutchAuction.matchOrdersAsync(badBuyOrder, badSellOrder, takerAddress, {
|
||||
shouldValidate: true,
|
||||
}),
|
||||
RevertReason.InvalidAssetData,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAuctionDetailsAsync', () => {
|
||||
it('should get auction details', async () => {
|
||||
// get auction details
|
||||
const auctionDetails = await contractWrappers.dutchAuction.getAuctionDetailsAsync(sellOrder);
|
||||
// run some basic sanity checks on the return value
|
||||
expect(auctionDetails.beginTimeSeconds, 'auctionDetails.beginTimeSeconds').to.be.bignumber.equal(
|
||||
auctionBeginTimeSeconds,
|
||||
);
|
||||
expect(auctionDetails.beginAmount, 'auctionDetails.beginAmount').to.be.bignumber.equal(
|
||||
auctionBeginTakerAmount,
|
||||
);
|
||||
expect(auctionDetails.endTimeSeconds, 'auctionDetails.endTimeSeconds').to.be.bignumber.equal(
|
||||
auctionEndTimeSeconds,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,39 +0,0 @@
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { ContractWrappers } from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { provider } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('ERC20ProxyWrapper', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
before(async () => {
|
||||
const contractAddresses = await migrateOnceAsync();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
});
|
||||
describe('#isAuthorizedAsync', () => {
|
||||
it('should return false if the address is not authorized', async () => {
|
||||
const isAuthorized = await contractWrappers.erc20Proxy.isAuthorizedAsync(constants.NULL_ADDRESS);
|
||||
expect(isAuthorized).to.be.false();
|
||||
});
|
||||
});
|
||||
describe('#getAuthorizedAddressesAsync', () => {
|
||||
it('should return the list of authorized addresses', async () => {
|
||||
const authorizedAddresses = await contractWrappers.erc20Proxy.getAuthorizedAddressesAsync();
|
||||
for (const authorizedAddress of authorizedAddresses) {
|
||||
const isAuthorized = await contractWrappers.erc20Proxy.isAuthorizedAsync(authorizedAddress);
|
||||
expect(isAuthorized).to.be.true();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
@ -1,633 +0,0 @@
|
||||
import { ContractAddresses } from '@0x/contract-addresses';
|
||||
import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
|
||||
import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0x/subproviders';
|
||||
import { DoneCallback } from '@0x/types';
|
||||
import { BigNumber, providerUtils } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
ContractWrappers,
|
||||
ContractWrappersConfig,
|
||||
ContractWrappersError,
|
||||
DecodedLogEvent,
|
||||
ERC20TokenApprovalEventArgs,
|
||||
ERC20TokenEvents,
|
||||
ERC20TokenTransferEventArgs,
|
||||
} from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('ERC20Wrapper', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
let contractAddresses: ContractAddresses;
|
||||
let userAddresses: string[];
|
||||
let tokens: string[];
|
||||
let coinbase: string;
|
||||
let addressWithoutFunds: string;
|
||||
let config: ContractWrappersConfig;
|
||||
|
||||
before(async () => {
|
||||
contractAddresses = await migrateOnceAsync();
|
||||
config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
tokens = tokenUtils.getDummyERC20TokenAddresses();
|
||||
coinbase = userAddresses[0];
|
||||
addressWithoutFunds = userAddresses[1];
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#transferAsync', () => {
|
||||
let tokenAddress: string;
|
||||
let transferAmount: BigNumber;
|
||||
before(() => {
|
||||
tokenAddress = tokens[0];
|
||||
transferAmount = new BigNumber(42);
|
||||
});
|
||||
it('should successfully transfer tokens', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const toAddress = addressWithoutFunds;
|
||||
const preBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
|
||||
expect(preBalance).to.be.bignumber.equal(0);
|
||||
await contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount);
|
||||
const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
|
||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||
});
|
||||
it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
|
||||
const fromAddress = addressWithoutFunds;
|
||||
const toAddress = coinbase;
|
||||
return expect(
|
||||
contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount),
|
||||
).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer);
|
||||
});
|
||||
});
|
||||
describe('#transferFromAsync', () => {
|
||||
let tokenAddress: string;
|
||||
let toAddress: string;
|
||||
let senderAddress: string;
|
||||
before(async () => {
|
||||
tokenAddress = tokens[0];
|
||||
toAddress = addressWithoutFunds;
|
||||
senderAddress = userAddresses[2];
|
||||
});
|
||||
it('should fail to transfer tokens if fromAddress has insufficient allowance set', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const transferAmount = new BigNumber(42);
|
||||
|
||||
const fromAddressBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, fromAddress);
|
||||
expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
|
||||
|
||||
const fromAddressAllowance = await contractWrappers.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
);
|
||||
expect(fromAddressAllowance).to.be.bignumber.equal(0);
|
||||
|
||||
return expect(
|
||||
contractWrappers.erc20Token.transferFromAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
senderAddress,
|
||||
transferAmount,
|
||||
),
|
||||
).to.be.rejectedWith(ContractWrappersError.InsufficientAllowanceForTransfer);
|
||||
});
|
||||
it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const transferAmount = new BigNumber(42);
|
||||
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(tokenAddress, fromAddress, toAddress, transferAmount);
|
||||
|
||||
return expect(
|
||||
contractWrappers.erc20Token.transferFromAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
senderAddress,
|
||||
transferAmount,
|
||||
),
|
||||
).to.be.rejectedWith(ContractWrappersError.InsufficientAllowanceForTransfer);
|
||||
});
|
||||
it('should fail to transfer tokens if fromAddress has insufficient balance', async () => {
|
||||
const fromAddress = addressWithoutFunds;
|
||||
const transferAmount = new BigNumber(42);
|
||||
|
||||
const fromAddressBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, fromAddress);
|
||||
expect(fromAddressBalance).to.be.bignumber.equal(0);
|
||||
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
senderAddress,
|
||||
transferAmount,
|
||||
);
|
||||
const fromAddressAllowance = await contractWrappers.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
senderAddress,
|
||||
);
|
||||
expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
|
||||
|
||||
return expect(
|
||||
contractWrappers.erc20Token.transferFromAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
senderAddress,
|
||||
transferAmount,
|
||||
),
|
||||
).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer);
|
||||
});
|
||||
it('should successfully transfer tokens', async () => {
|
||||
const fromAddress = coinbase;
|
||||
|
||||
const preBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
|
||||
expect(preBalance).to.be.bignumber.equal(0);
|
||||
|
||||
const transferAmount = new BigNumber(42);
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
senderAddress,
|
||||
transferAmount,
|
||||
);
|
||||
|
||||
await contractWrappers.erc20Token.transferFromAsync(
|
||||
tokenAddress,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
senderAddress,
|
||||
transferAmount,
|
||||
);
|
||||
const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
|
||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||
});
|
||||
});
|
||||
describe('#getBalanceAsync', () => {
|
||||
describe('With provider with accounts', () => {
|
||||
it('should return the balance for an existing ERC20 token', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const balance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, ownerAddress);
|
||||
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
it('should return a balance of 0 for a non-existent owner address', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593';
|
||||
const balance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, nonExistentOwner);
|
||||
const expectedBalance = new BigNumber(0);
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
});
|
||||
describe('With provider without accounts', () => {
|
||||
let zeroExContractWithoutAccounts: ContractWrappers;
|
||||
before(async () => {
|
||||
const emptyWalletProvider = addEmptyWalletSubprovider(provider);
|
||||
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
|
||||
});
|
||||
it('should return balance even when called with provider instance without addresses', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const balance = await zeroExContractWithoutAccounts.erc20Token.getBalanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
);
|
||||
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#setAllowanceAsync', () => {
|
||||
it("should set the spender's allowance", async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
const allowanceBeforeSet = await contractWrappers.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
|
||||
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
amountInBaseUnits,
|
||||
);
|
||||
|
||||
const allowanceAfterSet = await contractWrappers.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
|
||||
return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
|
||||
});
|
||||
});
|
||||
describe('#setUnlimitedAllowanceAsync', () => {
|
||||
it("should set the unlimited spender's allowance", async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
await contractWrappers.erc20Token.setUnlimitedAllowanceAsync(tokenAddress, ownerAddress, spenderAddress);
|
||||
const allowance = await contractWrappers.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
return expect(allowance).to.be.bignumber.equal(
|
||||
contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
);
|
||||
});
|
||||
it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => {
|
||||
const transferAmount = new BigNumber(5);
|
||||
const zrxAddress = contractAddresses.zrxToken;
|
||||
const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses;
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
zrxAddress,
|
||||
coinbase,
|
||||
userWithNormalAllowance,
|
||||
transferAmount,
|
||||
);
|
||||
await contractWrappers.erc20Token.setUnlimitedAllowanceAsync(
|
||||
zrxAddress,
|
||||
coinbase,
|
||||
userWithUnlimitedAllowance,
|
||||
);
|
||||
|
||||
const initBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||
const initBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
|
||||
userWithUnlimitedAllowance,
|
||||
);
|
||||
|
||||
await contractWrappers.erc20Token.transferFromAsync(
|
||||
zrxAddress,
|
||||
coinbase,
|
||||
userWithNormalAllowance,
|
||||
userWithNormalAllowance,
|
||||
transferAmount,
|
||||
);
|
||||
await contractWrappers.erc20Token.transferFromAsync(
|
||||
zrxAddress,
|
||||
coinbase,
|
||||
userWithUnlimitedAllowance,
|
||||
userWithUnlimitedAllowance,
|
||||
transferAmount,
|
||||
);
|
||||
|
||||
const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||
const finalBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
|
||||
userWithUnlimitedAllowance,
|
||||
);
|
||||
|
||||
const normalGasCost = initBalanceWithNormalAllowance.minus(finalBalanceWithNormalAllowance);
|
||||
const unlimitedGasCost = initBalanceWithUnlimitedAllowance.minus(finalBalanceWithUnlimitedAllowance);
|
||||
|
||||
// In theory the gas cost with unlimited allowance should be smaller, but with testrpc it's actually bigger.
|
||||
// This needs to be investigated in ethereumjs-vm. This test is essentially a repro.
|
||||
// TODO: Make this test pass with inverted assertion.
|
||||
expect(unlimitedGasCost.toNumber()).to.be.gt(normalGasCost.toNumber());
|
||||
});
|
||||
});
|
||||
describe('#getAllowanceAsync', () => {
|
||||
describe('With provider with accounts', () => {
|
||||
it('should get the proxy allowance', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
amountInBaseUnits,
|
||||
);
|
||||
|
||||
const allowance = await contractWrappers.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
const expectedAllowance = amountInBaseUnits;
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
it('should return 0 if no allowance set yet', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
const allowance = await contractWrappers.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
const expectedAllowance = new BigNumber(0);
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
});
|
||||
describe('With provider without accounts', () => {
|
||||
let zeroExContractWithoutAccounts: ContractWrappers;
|
||||
before(async () => {
|
||||
const emptyWalletProvider = addEmptyWalletSubprovider(provider);
|
||||
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
|
||||
});
|
||||
it('should get the proxy allowance', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
amountInBaseUnits,
|
||||
);
|
||||
|
||||
const allowance = await zeroExContractWithoutAccounts.erc20Token.getAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
const expectedAllowance = amountInBaseUnits;
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#getProxyAllowanceAsync', () => {
|
||||
it('should get the proxy allowance', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await contractWrappers.erc20Token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amountInBaseUnits);
|
||||
|
||||
const allowance = await contractWrappers.erc20Token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
|
||||
const expectedAllowance = amountInBaseUnits;
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
});
|
||||
describe('#setProxyAllowanceAsync', () => {
|
||||
it('should set the proxy allowance', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
|
||||
const allowanceBeforeSet = await contractWrappers.erc20Token.getProxyAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
);
|
||||
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
|
||||
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await contractWrappers.erc20Token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amountInBaseUnits);
|
||||
|
||||
const allowanceAfterSet = await contractWrappers.erc20Token.getProxyAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
);
|
||||
const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
|
||||
return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
|
||||
});
|
||||
});
|
||||
describe('#setUnlimitedProxyAllowanceAsync', () => {
|
||||
it('should set the unlimited proxy allowance', async () => {
|
||||
const tokenAddress = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
|
||||
await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, ownerAddress);
|
||||
const allowance = await contractWrappers.erc20Token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
|
||||
return expect(allowance).to.be.bignumber.equal(
|
||||
contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
let tokenAddress: string;
|
||||
const transferAmount = new BigNumber(42);
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
before(() => {
|
||||
tokenAddress = tokens[0];
|
||||
});
|
||||
afterEach(() => {
|
||||
contractWrappers.erc20Token.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
// we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<ERC20TokenTransferEventArgs>) => {
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||
const args = logEvent.log.args;
|
||||
expect(args._from).to.be.equal(coinbase);
|
||||
expect(args._to).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||
},
|
||||
);
|
||||
contractWrappers.erc20Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC20TokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
tokenAddress,
|
||||
coinbase,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(coinbase);
|
||||
expect(args._spender).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||
},
|
||||
);
|
||||
contractWrappers.erc20Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC20TokenEvents.Approval,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
coinbase,
|
||||
addressWithoutFunds,
|
||||
allowanceAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
},
|
||||
);
|
||||
contractWrappers.erc20Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC20TokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)();
|
||||
contractWrappers.unsubscribeAll();
|
||||
contractWrappers.erc20Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC20TokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackToBeCalled,
|
||||
);
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
tokenAddress,
|
||||
coinbase,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
},
|
||||
);
|
||||
const subscriptionToken = contractWrappers.erc20Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC20TokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
contractWrappers.erc20Token.unsubscribe(subscriptionToken);
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
tokenAddress,
|
||||
coinbase,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
describe('#getLogsAsync', () => {
|
||||
let tokenAddress: string;
|
||||
let tokenTransferProxyAddress: string;
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
let txHash: string;
|
||||
before(() => {
|
||||
tokenAddress = tokens[0];
|
||||
tokenTransferProxyAddress = contractWrappers.erc20Proxy.address;
|
||||
});
|
||||
it('should get logs with decoded args emitted by Approval', async () => {
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const eventName = ERC20TokenEvents.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.erc20Token.getLogsAsync<ERC20TokenApprovalEventArgs>(
|
||||
tokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(coinbase);
|
||||
expect(args._spender).to.be.equal(tokenTransferProxyAddress);
|
||||
expect(args._value).to.be.bignumber.equal(contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const differentEventName = ERC20TokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.erc20Token.getLogsAsync(
|
||||
tokenAddress,
|
||||
differentEventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
|
||||
tokenAddress,
|
||||
addressWithoutFunds,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const eventName = ERC20TokenEvents.Approval;
|
||||
const indexFilterValues = {
|
||||
_owner: coinbase,
|
||||
};
|
||||
const logs = await contractWrappers.erc20Token.getLogsAsync<ERC20TokenApprovalEventArgs>(
|
||||
tokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(args._owner).to.be.equal(coinbase);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
||||
|
||||
function addEmptyWalletSubprovider(p: Web3ProviderEngine): Web3ProviderEngine {
|
||||
const providerEngine = new Web3ProviderEngine();
|
||||
providerEngine.addProvider(new EmptyWalletSubprovider());
|
||||
const currentSubproviders = (p as any)._providers;
|
||||
for (const subprovider of currentSubproviders) {
|
||||
providerEngine.addProvider(subprovider);
|
||||
}
|
||||
providerUtils.startProviderEngine(providerEngine);
|
||||
return providerEngine;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { ContractWrappers } from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { provider } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('ERC721ProxyWrapper', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
before(async () => {
|
||||
const contractAddresses = await migrateOnceAsync();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
});
|
||||
describe('#isAuthorizedAsync', () => {
|
||||
it('should return false if the address is not authorized', async () => {
|
||||
const isAuthorized = await contractWrappers.erc721Proxy.isAuthorizedAsync(constants.NULL_ADDRESS);
|
||||
expect(isAuthorized).to.be.false();
|
||||
});
|
||||
});
|
||||
describe('#getAuthorizedAddressesAsync', () => {
|
||||
it('should return the list of authorized addresses', async () => {
|
||||
const authorizedAddresses = await contractWrappers.erc721Proxy.getAuthorizedAddressesAsync();
|
||||
for (const authorizedAddress of authorizedAddresses) {
|
||||
const isAuthorized = await contractWrappers.erc721Proxy.isAuthorizedAsync(authorizedAddress);
|
||||
expect(isAuthorized).to.be.true();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
@ -1,465 +0,0 @@
|
||||
import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
|
||||
import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0x/subproviders';
|
||||
import { DoneCallback } from '@0x/types';
|
||||
import { BigNumber, providerUtils } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
ContractWrappers,
|
||||
ContractWrappersConfig,
|
||||
ContractWrappersError,
|
||||
DecodedLogEvent,
|
||||
ERC721TokenApprovalEventArgs,
|
||||
ERC721TokenApprovalForAllEventArgs,
|
||||
ERC721TokenEvents,
|
||||
ERC721TokenTransferEventArgs,
|
||||
} from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('ERC721Wrapper', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
let userAddresses: string[];
|
||||
let tokens: string[];
|
||||
let ownerAddress: string;
|
||||
let tokenAddress: string;
|
||||
let anotherOwnerAddress: string;
|
||||
let operatorAddress: string;
|
||||
let approvedAddress: string;
|
||||
let receiverAddress: string;
|
||||
let config: ContractWrappersConfig;
|
||||
|
||||
before(async () => {
|
||||
const contractAddresses = await migrateOnceAsync();
|
||||
config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
tokens = tokenUtils.getDummyERC721TokenAddresses();
|
||||
tokenAddress = tokens[0];
|
||||
[ownerAddress, operatorAddress, anotherOwnerAddress, approvedAddress, receiverAddress] = userAddresses;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#transferFromAsync', () => {
|
||||
it('should fail to transfer NFT if fromAddress has no approvals set', async () => {
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
return expect(
|
||||
contractWrappers.erc721Token.transferFromAsync(tokenAddress, receiverAddress, approvedAddress, tokenId),
|
||||
).to.be.rejectedWith(ContractWrappersError.ERC721NoApproval);
|
||||
});
|
||||
it('should successfully transfer tokens when sender is an approved address', async () => {
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
let txHash = await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const owner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
|
||||
expect(owner).to.be.equal(ownerAddress);
|
||||
txHash = await contractWrappers.erc721Token.transferFromAsync(
|
||||
tokenAddress,
|
||||
receiverAddress,
|
||||
approvedAddress,
|
||||
tokenId,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const newOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
|
||||
expect(newOwner).to.be.equal(receiverAddress);
|
||||
});
|
||||
it('should successfully transfer tokens when sender is an approved operator', async () => {
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
const isApprovedForAll = true;
|
||||
let txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
isApprovedForAll,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const owner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
|
||||
expect(owner).to.be.equal(ownerAddress);
|
||||
txHash = await contractWrappers.erc721Token.transferFromAsync(
|
||||
tokenAddress,
|
||||
receiverAddress,
|
||||
operatorAddress,
|
||||
tokenId,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const newOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
|
||||
expect(newOwner).to.be.equal(receiverAddress);
|
||||
});
|
||||
});
|
||||
describe('#getTokenCountAsync', () => {
|
||||
describe('With provider with accounts', () => {
|
||||
it('should return the count for an existing ERC721 token', async () => {
|
||||
let tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress);
|
||||
expect(tokenCount).to.be.bignumber.equal(0);
|
||||
await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress);
|
||||
expect(tokenCount).to.be.bignumber.equal(1);
|
||||
});
|
||||
it('should return a balance of 0 for a non-existent owner address', async () => {
|
||||
const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593';
|
||||
const balance = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, nonExistentOwner);
|
||||
const expectedBalance = new BigNumber(0);
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
});
|
||||
describe('With provider without accounts', () => {
|
||||
let zeroExContractWithoutAccounts: ContractWrappers;
|
||||
before(async () => {
|
||||
const emptyWalletProvider = addEmptyWalletSubprovider(provider);
|
||||
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
|
||||
});
|
||||
it('should return balance even when called with provider instance without addresses', async () => {
|
||||
const balance = await zeroExContractWithoutAccounts.erc721Token.getTokenCountAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
);
|
||||
return expect(balance).to.be.bignumber.equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#getOwnerOfAsync', () => {
|
||||
it('should return the owner for an existing ERC721 token', async () => {
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
const tokenOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
|
||||
expect(tokenOwner).to.be.bignumber.equal(ownerAddress);
|
||||
});
|
||||
it('should return undefined not 0 for a non-existent ERC721', async () => {
|
||||
const fakeTokenId = new BigNumber(42);
|
||||
return expect(contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, fakeTokenId)).to.be.rejectedWith(
|
||||
ContractWrappersError.ERC721OwnerNotFound,
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('#setApprovalForAllAsync/isApprovedForAllAsync', () => {
|
||||
it('should check if operator address is approved', async () => {
|
||||
let isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
);
|
||||
expect(isApprovedForAll).to.be.false();
|
||||
// set
|
||||
isApprovedForAll = true;
|
||||
let txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
isApprovedForAll,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
);
|
||||
expect(isApprovedForAll).to.be.true();
|
||||
// unset
|
||||
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
false,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
);
|
||||
expect(isApprovedForAll).to.be.false();
|
||||
});
|
||||
});
|
||||
describe('#setProxyApprovalForAllAsync/isProxyApprovedForAllAsync', () => {
|
||||
it('should check if proxy address is approved', async () => {
|
||||
let isApprovedForAll = true;
|
||||
const txHash = await contractWrappers.erc721Token.setProxyApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
isApprovedForAll,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
isApprovedForAll = await contractWrappers.erc721Token.isProxyApprovedForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
);
|
||||
expect(isApprovedForAll).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#setApprovalAsync/getApprovedIfExistsAsync', () => {
|
||||
it("should set the spender's approval", async () => {
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
|
||||
const approvalBeforeSet = await contractWrappers.erc721Token.getApprovedIfExistsAsync(
|
||||
tokenAddress,
|
||||
tokenId,
|
||||
);
|
||||
expect(approvalBeforeSet).to.be.undefined();
|
||||
await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId);
|
||||
const approvalAfterSet = await contractWrappers.erc721Token.getApprovedIfExistsAsync(tokenAddress, tokenId);
|
||||
expect(approvalAfterSet).to.be.equal(approvedAddress);
|
||||
});
|
||||
});
|
||||
describe('#setProxyApprovalAsync/isProxyApprovedAsync', () => {
|
||||
it('should set the proxy approval', async () => {
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
|
||||
const isProxyApprovedBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync(
|
||||
tokenAddress,
|
||||
tokenId,
|
||||
);
|
||||
expect(isProxyApprovedBeforeSet).to.be.false();
|
||||
await contractWrappers.erc721Token.setProxyApprovalAsync(tokenAddress, tokenId);
|
||||
const isProxyApprovedAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync(
|
||||
tokenAddress,
|
||||
tokenId,
|
||||
);
|
||||
expect(isProxyApprovedAfterSet).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
afterEach(() => {
|
||||
contractWrappers.erc721Token.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
// we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<ERC721TokenTransferEventArgs>) => {
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||
const args = logEvent.log.args;
|
||||
expect(args._from).to.be.equal(ownerAddress);
|
||||
expect(args._to).to.be.equal(receiverAddress);
|
||||
expect(args._tokenId).to.be.bignumber.equal(tokenId);
|
||||
},
|
||||
);
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
const isApprovedForAll = true;
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
isApprovedForAll,
|
||||
),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
contractWrappers.erc721Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC721TokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc721Token.transferFromAsync(
|
||||
tokenAddress,
|
||||
receiverAddress,
|
||||
operatorAddress,
|
||||
tokenId,
|
||||
),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(ownerAddress);
|
||||
expect(args._approved).to.be.equal(approvedAddress);
|
||||
expect(args._tokenId).to.be.bignumber.equal(tokenId);
|
||||
},
|
||||
);
|
||||
contractWrappers.erc721Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC721TokenEvents.Approval,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
},
|
||||
);
|
||||
contractWrappers.erc721Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC721TokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)();
|
||||
contractWrappers.unsubscribeAll();
|
||||
contractWrappers.erc721Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC721TokenEvents.Approval,
|
||||
indexFilterValues,
|
||||
callbackToBeCalled,
|
||||
);
|
||||
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<ERC721TokenApprovalForAllEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
},
|
||||
);
|
||||
const subscriptionToken = contractWrappers.erc721Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC721TokenEvents.ApprovalForAll,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
contractWrappers.erc721Token.unsubscribe(subscriptionToken);
|
||||
|
||||
const isApproved = true;
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
isApproved,
|
||||
),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
describe('#getLogsAsync', () => {
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
let txHash: string;
|
||||
it('should get logs with decoded args emitted by ApprovalForAll', async () => {
|
||||
const isApprovedForAll = true;
|
||||
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
isApprovedForAll,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const eventName = ERC721TokenEvents.ApprovalForAll;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.erc721Token.getLogsAsync<ERC721TokenApprovalForAllEventArgs>(
|
||||
tokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(ownerAddress);
|
||||
expect(args._operator).to.be.equal(operatorAddress);
|
||||
expect(args._approved).to.be.equal(isApprovedForAll);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
const isApprovedForAll = true;
|
||||
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
isApprovedForAll,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const differentEventName = ERC721TokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.erc721Token.getLogsAsync(
|
||||
tokenAddress,
|
||||
differentEventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
const isApprovedForAll = true;
|
||||
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
operatorAddress,
|
||||
isApprovedForAll,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
|
||||
tokenAddress,
|
||||
anotherOwnerAddress,
|
||||
operatorAddress,
|
||||
isApprovedForAll,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const eventName = ERC721TokenEvents.ApprovalForAll;
|
||||
const indexFilterValues = {
|
||||
_owner: anotherOwnerAddress,
|
||||
};
|
||||
const logs = await contractWrappers.erc721Token.getLogsAsync<ERC721TokenApprovalForAllEventArgs>(
|
||||
tokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(args._owner).to.be.equal(anotherOwnerAddress);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
||||
|
||||
function addEmptyWalletSubprovider(p: Web3ProviderEngine): Web3ProviderEngine {
|
||||
const providerEngine = new Web3ProviderEngine();
|
||||
providerEngine.addProvider(new EmptyWalletSubprovider());
|
||||
const currentSubproviders = (p as any)._providers;
|
||||
for (const subprovider of currentSubproviders) {
|
||||
providerEngine.addProvider(subprovider);
|
||||
}
|
||||
providerUtils.startProviderEngine(providerEngine);
|
||||
return providerEngine;
|
||||
}
|
@ -1,437 +0,0 @@
|
||||
import { ContractAddresses } from '@0x/contract-addresses';
|
||||
import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
|
||||
import { DoneCallback } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
ContractWrappers,
|
||||
ContractWrappersError,
|
||||
WETH9ApprovalEventArgs,
|
||||
WETH9DepositEventArgs,
|
||||
WETH9Events,
|
||||
WETH9TransferEventArgs,
|
||||
WETH9WithdrawalEventArgs,
|
||||
} from '../src';
|
||||
import { DecodedLogEvent } from '../src/types';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction,
|
||||
// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between
|
||||
// the expected balance and actual balance (given the amount of ETH deposited), only deviates by the amount
|
||||
// required to pay gas costs.
|
||||
const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
|
||||
|
||||
describe('EtherTokenWrapper', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
let contractAddresses: ContractAddresses;
|
||||
let userAddresses: string[];
|
||||
let addressWithETH: string;
|
||||
let wethContractAddress: string;
|
||||
let depositWeiAmount: BigNumber;
|
||||
const decimalPlaces = 7;
|
||||
let addressWithoutFunds: string;
|
||||
const gasPrice = new BigNumber(1);
|
||||
const transferAmount = new BigNumber(42);
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
const depositAmount = new BigNumber(42);
|
||||
const withdrawalAmount = new BigNumber(42);
|
||||
before(async () => {
|
||||
contractAddresses = await migrateOnceAsync();
|
||||
const config = {
|
||||
gasPrice,
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
addressWithETH = userAddresses[0];
|
||||
wethContractAddress = contractAddresses.etherToken;
|
||||
depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5));
|
||||
addressWithoutFunds = userAddresses[1];
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#getContractAddressIfExists', async () => {
|
||||
it('should return contract address if connected to a known network', () => {
|
||||
const contractAddressIfExists = contractAddresses.etherToken;
|
||||
expect(contractAddressIfExists).to.not.be.undefined();
|
||||
});
|
||||
it('should throw if connected to a private network and contract addresses are not specified', () => {
|
||||
const UNKNOWN_NETWORK_NETWORK_ID = 10;
|
||||
expect(
|
||||
() =>
|
||||
new ContractWrappers(provider, {
|
||||
networkId: UNKNOWN_NETWORK_NETWORK_ID,
|
||||
} as any),
|
||||
).to.throw();
|
||||
});
|
||||
});
|
||||
describe('#depositAsync', () => {
|
||||
it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => {
|
||||
const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync(
|
||||
wethContractAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
expect(preETHBalance).to.be.bignumber.gt(0);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(0);
|
||||
|
||||
const txHash = await contractWrappers.etherToken.depositAsync(
|
||||
wethContractAddress,
|
||||
depositWeiAmount,
|
||||
addressWithETH,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
|
||||
const postETHBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const postWETHBalanceInBaseUnits = await contractWrappers.erc20Token.getBalanceAsync(
|
||||
wethContractAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
|
||||
expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount);
|
||||
const remainingETHInWei = preETHBalance.minus(depositWeiAmount);
|
||||
const gasCost = remainingETHInWei.minus(postETHBalanceInWei);
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
});
|
||||
it('should throw if user has insufficient ETH balance for deposit', async () => {
|
||||
const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
|
||||
const extraETHBalance = Web3Wrapper.toWei(new BigNumber(5));
|
||||
const overETHBalanceinWei = preETHBalance.plus(extraETHBalance);
|
||||
|
||||
return expect(
|
||||
contractWrappers.etherToken.depositAsync(wethContractAddress, overETHBalanceinWei, addressWithETH),
|
||||
).to.be.rejectedWith(ContractWrappersError.InsufficientEthBalanceForDeposit);
|
||||
});
|
||||
});
|
||||
describe('#withdrawAsync', () => {
|
||||
it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => {
|
||||
const ETHBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
|
||||
await contractWrappers.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH);
|
||||
|
||||
const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount);
|
||||
const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync(
|
||||
wethContractAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
let gasCost = expectedPreETHBalance.minus(preETHBalance);
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount);
|
||||
|
||||
const txHash = await contractWrappers.etherToken.withdrawAsync(
|
||||
wethContractAddress,
|
||||
depositWeiAmount,
|
||||
addressWithETH,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
|
||||
const postETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const postWETHBalanceInBaseUnits = await contractWrappers.erc20Token.getBalanceAsync(
|
||||
wethContractAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
|
||||
expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0);
|
||||
const expectedETHBalance = preETHBalance.plus(depositWeiAmount).integerValue(decimalPlaces);
|
||||
gasCost = expectedETHBalance.minus(postETHBalance);
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
});
|
||||
it('should throw if user has insufficient WETH balance for withdrawal', async () => {
|
||||
const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync(
|
||||
wethContractAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(0);
|
||||
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
const overWETHBalance = preWETHBalance.plus(999999999);
|
||||
|
||||
return expect(
|
||||
contractWrappers.etherToken.withdrawAsync(wethContractAddress, overWETHBalance, addressWithETH),
|
||||
).to.be.rejectedWith(ContractWrappersError.InsufficientWEthBalanceForWithdrawal);
|
||||
});
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
let etherTokenAddress: string;
|
||||
before(async () => {
|
||||
etherTokenAddress = contractAddresses.etherToken;
|
||||
});
|
||||
afterEach(() => {
|
||||
contractWrappers.etherToken.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
// we do need both. A hack is to make the top-level async fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<WETH9TransferEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||
const args = logEvent.log.args;
|
||||
expect(args._from).to.be.equal(addressWithETH);
|
||||
expect(args._to).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||
},
|
||||
);
|
||||
await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
contractWrappers.etherToken.subscribe(
|
||||
etherTokenAddress,
|
||||
WETH9Events.Transfer,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._spender).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||
},
|
||||
);
|
||||
contractWrappers.etherToken.subscribe(
|
||||
etherTokenAddress,
|
||||
WETH9Events.Approval,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await contractWrappers.erc20Token.setAllowanceAsync(
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
allowanceAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<WETH9DepositEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
},
|
||||
);
|
||||
contractWrappers.etherToken.subscribe(
|
||||
etherTokenAddress,
|
||||
WETH9Events.Deposit,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(logEvent: DecodedLogEvent<WETH9WithdrawalEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
},
|
||||
);
|
||||
await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||
contractWrappers.etherToken.subscribe(
|
||||
etherTokenAddress,
|
||||
WETH9Events.Withdrawal,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await contractWrappers.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should cancel outstanding subscriptions when contractWrappers.unsubscribeAll is called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
},
|
||||
);
|
||||
contractWrappers.etherToken.subscribe(
|
||||
etherTokenAddress,
|
||||
WETH9Events.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)();
|
||||
contractWrappers.unsubscribeAll();
|
||||
await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
contractWrappers.etherToken.subscribe(
|
||||
etherTokenAddress,
|
||||
WETH9Events.Transfer,
|
||||
indexFilterValues,
|
||||
callbackToBeCalled,
|
||||
);
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
|
||||
(_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
},
|
||||
);
|
||||
await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
const subscriptionToken = contractWrappers.etherToken.subscribe(
|
||||
etherTokenAddress,
|
||||
WETH9Events.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
contractWrappers.etherToken.unsubscribe(subscriptionToken);
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
describe('#getLogsAsync', () => {
|
||||
let etherTokenAddress: string;
|
||||
let erc20ProxyAddress: string;
|
||||
let blockRange: BlockRange;
|
||||
let txHash: string;
|
||||
before(async () => {
|
||||
addressWithETH = userAddresses[0];
|
||||
etherTokenAddress = contractAddresses.etherToken;
|
||||
erc20ProxyAddress = contractWrappers.erc20Proxy.address;
|
||||
// Start the block range after all migrations to avoid unexpected logs
|
||||
const currentBlock: number = await web3Wrapper.getBlockNumberAsync();
|
||||
const fromBlock = currentBlock + 1;
|
||||
blockRange = {
|
||||
fromBlock,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
});
|
||||
it('should get logs with decoded args emitted by Approval', async () => {
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const eventName = WETH9Events.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.etherToken.getLogsAsync<WETH9ApprovalEventArgs>(
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._spender).to.be.equal(erc20ProxyAddress);
|
||||
expect(args._value).to.be.bignumber.equal(contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
it('should get logs with decoded args emitted by Deposit', async () => {
|
||||
await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||
const eventName = WETH9Events.Deposit;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.etherToken.getLogsAsync<WETH9DepositEventArgs>(
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const differentEventName = WETH9Events.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.etherToken.getLogsAsync(
|
||||
etherTokenAddress,
|
||||
differentEventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
|
||||
etherTokenAddress,
|
||||
addressWithoutFunds,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const eventName = WETH9Events.Approval;
|
||||
const indexFilterValues = {
|
||||
_owner: addressWithETH,
|
||||
};
|
||||
const logs = await contractWrappers.etherToken.getLogsAsync<WETH9ApprovalEventArgs>(
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,8 +1,7 @@
|
||||
import { DummyERC20TokenContract } from '@0x/abi-gen-wrappers';
|
||||
import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils, orderHashUtils, signatureUtils } from '@0x/order-utils';
|
||||
import { DoneCallback, RevertReason, SignedOrder } from '@0x/types';
|
||||
import { DoneCallback, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import { BlockParamLiteral } from 'ethereum-types';
|
||||
@ -10,8 +9,8 @@ import 'mocha';
|
||||
|
||||
import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
|
||||
import { DecodedLogEvent } from '../src/types';
|
||||
import { _getDefaultContractAddresses } from '../src/utils/contract_addresses';
|
||||
|
||||
import { UntransferrableDummyERC20Token } from './artifacts/UntransferrableDummyERC20Token';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
@ -35,7 +34,6 @@ describe('ExchangeWrapper', () => {
|
||||
let takerAddress: string;
|
||||
let makerAssetData: string;
|
||||
let takerAssetData: string;
|
||||
let txHash: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const takerTokenFillAmount = new BigNumber(5);
|
||||
let signedOrder: SignedOrder;
|
||||
@ -52,7 +50,7 @@ describe('ExchangeWrapper', () => {
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
exchangeContractAddress = contractWrappers.exchange.address;
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress;
|
||||
zrxTokenAddress = contractAddresses.zrxToken;
|
||||
fillScenarios = new FillScenarios(
|
||||
provider,
|
||||
userAddresses,
|
||||
@ -94,71 +92,71 @@ describe('ExchangeWrapper', () => {
|
||||
describe('fill order(s)', () => {
|
||||
describe('#fillOrderAsync', () => {
|
||||
it('should fill a valid order', async () => {
|
||||
txHash = await contractWrappers.exchange.fillOrderAsync(
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
takerAddress,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
describe('#fillOrderNoThrowAsync', () => {
|
||||
it('should fill a valid order', async () => {
|
||||
txHash = await contractWrappers.exchange.fillOrderNoThrowAsync(
|
||||
await contractWrappers.exchange.fillOrderNoThrow.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
takerAddress,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
});
|
||||
});
|
||||
describe('#fillOrKillOrderAsync', () => {
|
||||
it('should fill or kill a valid order', async () => {
|
||||
txHash = await contractWrappers.exchange.fillOrKillOrderAsync(
|
||||
await contractWrappers.exchange.fillOrKillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
takerAddress,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
describe('#batchFillOrdersAsync', () => {
|
||||
it('should fill a batch of valid orders', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
||||
txHash = await contractWrappers.exchange.batchFillOrdersAsync(
|
||||
await contractWrappers.exchange.batchFillOrders.awaitTransactionSuccessAsync(
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
takerAddress,
|
||||
signedOrders.map(o => o.signature),
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
describe('#marketBuyOrdersAsync', () => {
|
||||
it('should maker buy', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const makerAssetFillAmount = takerTokenFillAmount;
|
||||
txHash = await contractWrappers.exchange.marketBuyOrdersAsync(
|
||||
await contractWrappers.exchange.marketBuyOrders.awaitTransactionSuccessAsync(
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
takerAddress,
|
||||
signedOrders.map(o => o.signature),
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
describe('#marketBuyOrdersNoThrowAsync', () => {
|
||||
it('should no throw maker buy', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const makerAssetFillAmount = takerTokenFillAmount;
|
||||
txHash = await contractWrappers.exchange.marketBuyOrdersNoThrowAsync(
|
||||
await contractWrappers.exchange.marketBuyOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
takerAddress,
|
||||
signedOrders.map(o => o.signature),
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
});
|
||||
});
|
||||
@ -166,25 +164,25 @@ describe('ExchangeWrapper', () => {
|
||||
it('should maker sell', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const takerAssetFillAmount = takerTokenFillAmount;
|
||||
txHash = await contractWrappers.exchange.marketSellOrdersAsync(
|
||||
await contractWrappers.exchange.marketSellOrders.awaitTransactionSuccessAsync(
|
||||
signedOrders,
|
||||
takerAssetFillAmount,
|
||||
takerAddress,
|
||||
signedOrders.map(o => o.signature),
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
describe('#marketSellOrdersNoThrowAsync', () => {
|
||||
it('should no throw maker sell', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const takerAssetFillAmount = takerTokenFillAmount;
|
||||
txHash = await contractWrappers.exchange.marketSellOrdersNoThrowAsync(
|
||||
await contractWrappers.exchange.marketSellOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||
signedOrders,
|
||||
takerAssetFillAmount,
|
||||
takerAddress,
|
||||
signedOrders.map(o => o.signature),
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
});
|
||||
});
|
||||
@ -192,15 +190,15 @@ describe('ExchangeWrapper', () => {
|
||||
it('should fill a batch of valid orders', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
||||
txHash = await contractWrappers.exchange.batchFillOrdersNoThrowAsync(
|
||||
await contractWrappers.exchange.batchFillOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
takerAddress,
|
||||
signedOrders.map(o => o.signature),
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
let orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
||||
let orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
orderInfo = await contractWrappers.exchange.getOrderInfoAsync(anotherSignedOrder);
|
||||
orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(anotherSignedOrder);
|
||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
});
|
||||
});
|
||||
@ -208,12 +206,12 @@ describe('ExchangeWrapper', () => {
|
||||
it('should fill or kill a batch of valid orders', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
||||
txHash = await contractWrappers.exchange.batchFillOrKillOrdersAsync(
|
||||
await contractWrappers.exchange.batchFillOrKillOrders.awaitTransactionSuccessAsync(
|
||||
signedOrders,
|
||||
takerAssetFillAmounts,
|
||||
takerAddress,
|
||||
signedOrders.map(o => o.signature),
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
describe('#matchOrdersAsync', () => {
|
||||
@ -225,35 +223,39 @@ describe('ExchangeWrapper', () => {
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
txHash = await contractWrappers.exchange.matchOrdersAsync(
|
||||
await contractWrappers.exchange.matchOrders.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
matchingSignedOrder,
|
||||
takerAddress,
|
||||
signedOrder.signature,
|
||||
matchingSignedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('cancel order(s)', () => {
|
||||
describe('#cancelOrderAsync', () => {
|
||||
it('should cancel a valid order', async () => {
|
||||
txHash = await contractWrappers.exchange.cancelOrderAsync(signedOrder);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
await contractWrappers.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrder, {
|
||||
from: makerAddress,
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#batchCancelOrdersAsync', () => {
|
||||
it('should cancel a batch of valid orders', async () => {
|
||||
const orders = [signedOrder, anotherSignedOrder];
|
||||
txHash = await contractWrappers.exchange.batchCancelOrdersAsync(orders);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
await contractWrappers.exchange.batchCancelOrders.awaitTransactionSuccessAsync(orders, {
|
||||
from: makerAddress,
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#cancelOrdersUpTo/getOrderEpochAsync', () => {
|
||||
it('should cancel orders up to target order epoch', async () => {
|
||||
const targetOrderEpoch = new BigNumber(42);
|
||||
txHash = await contractWrappers.exchange.cancelOrdersUpToAsync(targetOrderEpoch, makerAddress);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const orderEpoch = await contractWrappers.exchange.getOrderEpochAsync(
|
||||
await contractWrappers.exchange.cancelOrdersUpTo.awaitTransactionSuccessAsync(targetOrderEpoch, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const orderEpoch = await contractWrappers.exchange.orderEpoch.callAsync(
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
);
|
||||
@ -261,138 +263,35 @@ describe('ExchangeWrapper', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#getZRXAssetData', () => {
|
||||
it('should get the asset data', () => {
|
||||
const ZRX_ASSET_DATA = contractWrappers.exchange.getZRXAssetData();
|
||||
const ASSET_DATA_HEX_LENGTH = 74;
|
||||
expect(ZRX_ASSET_DATA).to.have.length(ASSET_DATA_HEX_LENGTH);
|
||||
});
|
||||
});
|
||||
describe('#getOrderInfoAsync', () => {
|
||||
it('should get the order info', async () => {
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
||||
const orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
expect(orderInfo.orderHash).to.be.equal(orderHash);
|
||||
});
|
||||
});
|
||||
describe('#getOrdersInfoAsync', () => {
|
||||
it('should get the orders info', async () => {
|
||||
const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]);
|
||||
const ordersInfo = await contractWrappers.exchange.getOrdersInfo.callAsync([
|
||||
signedOrder,
|
||||
anotherSignedOrder,
|
||||
]);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
expect(ordersInfo[0].orderHash).to.be.equal(orderHash);
|
||||
const anotherOrderHash = orderHashUtils.getOrderHashHex(anotherSignedOrder);
|
||||
expect(ordersInfo[1].orderHash).to.be.equal(anotherOrderHash);
|
||||
});
|
||||
});
|
||||
describe('#validateOrderFillableOrThrowAsync', () => {
|
||||
it('should throw if signature is invalid', async () => {
|
||||
const signedOrderWithInvalidSignature = {
|
||||
...signedOrder,
|
||||
signature:
|
||||
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403',
|
||||
};
|
||||
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrderWithInvalidSignature),
|
||||
).to.eventually.to.be.rejectedWith(RevertReason.InvalidOrderSignature);
|
||||
});
|
||||
it('should validate the order with the current balances and allowances for the maker', async () => {
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
validateRemainingOrderAmountIsFillable: false,
|
||||
});
|
||||
});
|
||||
it('should validate the order with remaining fillable amount for the order', async () => {
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
it('should validate the order with specified amount', async () => {
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
expectedFillTakerTokenAmount: signedOrder.takerAssetAmount,
|
||||
});
|
||||
});
|
||||
it('should throw if the amount is greater than the allowance/balance', async () => {
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
expectedFillTakerTokenAmount: new BigNumber(2).pow(256).minus(1),
|
||||
}),
|
||||
).to.eventually.to.be.rejected();
|
||||
});
|
||||
it('should throw when the maker does not have enough balance for the remaining order amount', async () => {
|
||||
const makerBalance = await contractWrappers.erc20Token.getBalanceAsync(makerTokenAddress, makerAddress);
|
||||
// Change maker balance to have less than the order amount
|
||||
const remainingBalance = makerBalance.minus(signedOrder.makerAssetAmount.minus(1));
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
makerTokenAddress,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
remainingBalance,
|
||||
),
|
||||
);
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder),
|
||||
).to.eventually.to.be.rejected();
|
||||
});
|
||||
it('should validate the order when remaining order amount has some fillable amount', async () => {
|
||||
const makerBalance = await contractWrappers.erc20Token.getBalanceAsync(makerTokenAddress, makerAddress);
|
||||
// Change maker balance to have less than the order amount
|
||||
const remainingBalance = makerBalance.minus(signedOrder.makerAssetAmount.minus(1));
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
makerTokenAddress,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
remainingBalance,
|
||||
),
|
||||
);
|
||||
// An amount is still transferrable
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
validateRemainingOrderAmountIsFillable: false,
|
||||
});
|
||||
});
|
||||
it('should throw when the ERC20 token has transfer restrictions', async () => {
|
||||
const artifactDependencies = {};
|
||||
const untransferrableToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
UntransferrableDummyERC20Token,
|
||||
provider,
|
||||
{ from: userAddresses[0] },
|
||||
artifactDependencies,
|
||||
'UntransferrableToken',
|
||||
'UTT',
|
||||
new BigNumber(constants.ZRX_DECIMALS),
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
new BigNumber(2).pow(20).minus(1),
|
||||
);
|
||||
const untransferrableMakerAssetData = assetDataUtils.encodeERC20AssetData(untransferrableToken.address);
|
||||
const invalidSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
untransferrableMakerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc20Token.setProxyAllowanceAsync(
|
||||
untransferrableToken.address,
|
||||
makerAddress,
|
||||
signedOrder.makerAssetAmount,
|
||||
),
|
||||
);
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(invalidSignedOrder),
|
||||
).to.eventually.to.be.rejectedWith('TRANSFER_FAILED');
|
||||
});
|
||||
});
|
||||
describe('#isValidSignature', () => {
|
||||
it('should check if the signature is valid', async () => {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
let isValid = await contractWrappers.exchange.isValidSignatureAsync(
|
||||
let isValid = await contractWrappers.exchange.isValidSignature.callAsync(
|
||||
orderHash,
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(isValid).to.be.true();
|
||||
isValid = await contractWrappers.exchange.isValidSignatureAsync(
|
||||
isValid = await contractWrappers.exchange.isValidSignature.callAsync(
|
||||
orderHash,
|
||||
signedOrder.takerAddress,
|
||||
signedOrder.signature,
|
||||
@ -404,7 +303,10 @@ describe('ExchangeWrapper', () => {
|
||||
it('should check if the validator is allowed', async () => {
|
||||
const signerAddress = makerAddress;
|
||||
const validatorAddress = constants.NULL_ADDRESS;
|
||||
const isAllowed = await contractWrappers.exchange.isAllowedValidatorAsync(signerAddress, validatorAddress);
|
||||
const isAllowed = await contractWrappers.exchange.allowedValidators.callAsync(
|
||||
signerAddress,
|
||||
validatorAddress,
|
||||
);
|
||||
expect(isAllowed).to.be.false();
|
||||
});
|
||||
});
|
||||
@ -413,52 +315,50 @@ describe('ExchangeWrapper', () => {
|
||||
const validatorAddress = constants.NULL_ADDRESS;
|
||||
const isApproved = true;
|
||||
const senderAddress = makerAddress;
|
||||
txHash = await contractWrappers.exchange.setSignatureValidatorApprovalAsync(
|
||||
await contractWrappers.exchange.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
|
||||
validatorAddress,
|
||||
isApproved,
|
||||
senderAddress,
|
||||
{ from: senderAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
});
|
||||
});
|
||||
describe('#isTransactionExecutedAsync', () => {
|
||||
it('should check if the transaction is executed', async () => {
|
||||
const transactionHash = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
||||
const isExecuted = await contractWrappers.exchange.isTransactionExecutedAsync(transactionHash);
|
||||
const isExecuted = await contractWrappers.exchange.transactions.callAsync(transactionHash);
|
||||
expect(isExecuted).to.be.false();
|
||||
});
|
||||
});
|
||||
describe('#getAssetProxyBySignatureAsync', () => {
|
||||
it('should fill or kill a valid order', async () => {
|
||||
const erc20ProxyId = await contractWrappers.erc20Proxy.getProxyIdAsync();
|
||||
const erc20ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc20ProxyId);
|
||||
const erc20ProxyId = await contractWrappers.erc20Proxy.getProxyId.callAsync();
|
||||
const erc20ProxyAddressById = await contractWrappers.exchange.getAssetProxy.callAsync(erc20ProxyId);
|
||||
const erc20ProxyAddress = contractWrappers.erc20Proxy.address;
|
||||
expect(erc20ProxyAddressById).to.be.equal(erc20ProxyAddress);
|
||||
const erc721ProxyId = await contractWrappers.erc721Proxy.getProxyIdAsync();
|
||||
const erc721ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc721ProxyId);
|
||||
const erc721ProxyId = await contractWrappers.erc721Proxy.getProxyId.callAsync();
|
||||
const erc721ProxyAddressById = await contractWrappers.exchange.getAssetProxy.callAsync(erc721ProxyId);
|
||||
const erc721ProxyAddress = contractWrappers.erc721Proxy.address;
|
||||
expect(erc721ProxyAddressById).to.be.equal(erc721ProxyAddress);
|
||||
});
|
||||
});
|
||||
describe('#preSignAsync/isPreSignedAsync', () => {
|
||||
describe('#preSign/isPresigned', () => {
|
||||
it('should preSign the hash', async () => {
|
||||
const senderAddress = takerAddress;
|
||||
const hash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const signerAddress = signedOrder.makerAddress;
|
||||
let isPreSigned = await contractWrappers.exchange.isPreSignedAsync(hash, signerAddress);
|
||||
let isPreSigned = await contractWrappers.exchange.preSigned.callAsync(hash, signerAddress);
|
||||
expect(isPreSigned).to.be.false();
|
||||
txHash = await contractWrappers.exchange.preSignAsync(
|
||||
await contractWrappers.exchange.preSign.awaitTransactionSuccessAsync(
|
||||
hash,
|
||||
signerAddress,
|
||||
signedOrder.signature,
|
||||
senderAddress,
|
||||
{ from: senderAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
isPreSigned = await contractWrappers.exchange.isPreSignedAsync(hash, signerAddress);
|
||||
isPreSigned = await contractWrappers.exchange.preSigned.callAsync(hash, signerAddress);
|
||||
expect(isPreSigned).to.be.true();
|
||||
|
||||
const preSignedSignature = '0x06';
|
||||
const isValidSignature = await contractWrappers.exchange.isValidSignatureAsync(
|
||||
const isValidSignature = await contractWrappers.exchange.isValidSignature.callAsync(
|
||||
hash,
|
||||
signerAddress,
|
||||
preSignedSignature,
|
||||
@ -477,7 +377,7 @@ describe('ExchangeWrapper', () => {
|
||||
});
|
||||
describe('#getVersionAsync', () => {
|
||||
it('should return version the hash', async () => {
|
||||
const version = await contractWrappers.exchange.getVersionAsync();
|
||||
const version = await contractWrappers.exchange.VERSION.callAsync();
|
||||
const VERSION = '2.0.0';
|
||||
expect(version).to.be.equal(VERSION);
|
||||
});
|
||||
@ -510,10 +410,11 @@ describe('ExchangeWrapper', () => {
|
||||
},
|
||||
);
|
||||
contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback);
|
||||
await contractWrappers.exchange.fillOrderAsync(
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmountInBaseUnits,
|
||||
takerAddress,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
@ -525,7 +426,9 @@ describe('ExchangeWrapper', () => {
|
||||
},
|
||||
);
|
||||
contractWrappers.exchange.subscribe(ExchangeEvents.Cancel, indexFilterValues, callback);
|
||||
await contractWrappers.exchange.cancelOrderAsync(signedOrder);
|
||||
await contractWrappers.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrder, {
|
||||
from: makerAddress,
|
||||
});
|
||||
})().catch(done);
|
||||
});
|
||||
it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => {
|
||||
@ -545,10 +448,11 @@ describe('ExchangeWrapper', () => {
|
||||
},
|
||||
);
|
||||
contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback);
|
||||
await contractWrappers.exchange.fillOrderAsync(
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmountInBaseUnits,
|
||||
takerAddress,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
@ -565,10 +469,11 @@ describe('ExchangeWrapper', () => {
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
contractWrappers.exchange.unsubscribe(subscriptionToken);
|
||||
await contractWrappers.exchange.fillOrderAsync(
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmountInBaseUnits,
|
||||
takerAddress,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
@ -580,7 +485,12 @@ describe('ExchangeWrapper', () => {
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
it('should get logs with decoded args emitted by Fill', async () => {
|
||||
txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
const eventName = ExchangeEvents.Fill;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.exchange.getLogsAsync(eventName, blockRange, indexFilterValues);
|
||||
@ -588,8 +498,12 @@ describe('ExchangeWrapper', () => {
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
const differentEventName = ExchangeEvents.Cancel;
|
||||
const indexFilterValues = {};
|
||||
const logs = await contractWrappers.exchange.getLogsAsync(
|
||||
@ -600,8 +514,12 @@ describe('ExchangeWrapper', () => {
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
const signedOrderWithAnotherMakerAddress = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
@ -609,13 +527,12 @@ describe('ExchangeWrapper', () => {
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
txHash = await contractWrappers.exchange.fillOrderAsync(
|
||||
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrderWithAnotherMakerAddress,
|
||||
takerTokenFillAmount,
|
||||
takerAddress,
|
||||
signedOrderWithAnotherMakerAddress.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
|
||||
const eventName = ExchangeEvents.Fill;
|
||||
const indexFilterValues = {
|
||||
makerAddress: anotherMakerAddress,
|
||||
|
@ -1,167 +0,0 @@
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { ContractWrappers, OrderStatus } from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
// tslint:disable:custom-no-magic-numbers
|
||||
describe('ForwarderWrapper', () => {
|
||||
const fillableAmount = new BigNumber(5);
|
||||
let contractWrappers: ContractWrappers;
|
||||
let fillScenarios: FillScenarios;
|
||||
let exchangeContractAddress: string;
|
||||
let zrxTokenAddress: string;
|
||||
let userAddresses: string[];
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let makerAssetData: string;
|
||||
let takerAssetData: string;
|
||||
let signedOrder: SignedOrder;
|
||||
let anotherSignedOrder: SignedOrder;
|
||||
before(async () => {
|
||||
const contractAddresses = await migrateOnceAsync();
|
||||
await blockchainLifecycle.startAsync();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
exchangeContractAddress = contractWrappers.exchange.address;
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress;
|
||||
fillScenarios = new FillScenarios(
|
||||
provider,
|
||||
userAddresses,
|
||||
zrxTokenAddress,
|
||||
exchangeContractAddress,
|
||||
contractWrappers.erc20Proxy.address,
|
||||
contractWrappers.erc721Proxy.address,
|
||||
);
|
||||
[, makerAddress, takerAddress] = userAddresses;
|
||||
[makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
takerTokenAddress = contractWrappers.forwarder.etherTokenAddress;
|
||||
[makerAssetData, takerAssetData] = [
|
||||
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
|
||||
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
|
||||
];
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
fillableAmount,
|
||||
);
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#marketBuyOrdersWithEthAsync', () => {
|
||||
it('should market buy orders with eth', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(anotherSignedOrder.makerAssetAmount);
|
||||
const txHash = await contractWrappers.forwarder.marketBuyOrdersWithEthAsync(
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
takerAddress,
|
||||
makerAssetFillAmount,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]);
|
||||
expect(ordersInfo[0].orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
});
|
||||
it('should throw when invalid transaction and shouldValidate is true', async () => {
|
||||
const signedOrders = [signedOrder];
|
||||
// request more makerAsset than what is available
|
||||
const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(100);
|
||||
return expect(
|
||||
contractWrappers.forwarder.marketBuyOrdersWithEthAsync(
|
||||
signedOrders,
|
||||
makerAssetFillAmount,
|
||||
takerAddress,
|
||||
makerAssetFillAmount,
|
||||
[],
|
||||
0,
|
||||
constants.NULL_ADDRESS,
|
||||
{
|
||||
shouldValidate: true,
|
||||
},
|
||||
),
|
||||
).to.be.rejectedWith('COMPLETE_FILL_FAILED');
|
||||
});
|
||||
});
|
||||
describe('#marketSellOrdersWithEthAsync', () => {
|
||||
it('should market sell orders with eth', async () => {
|
||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||
const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(anotherSignedOrder.makerAssetAmount);
|
||||
const txHash = await contractWrappers.forwarder.marketSellOrdersWithEthAsync(
|
||||
signedOrders,
|
||||
takerAddress,
|
||||
makerAssetFillAmount,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]);
|
||||
expect(ordersInfo[0].orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||
expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.Fillable);
|
||||
expect(ordersInfo[1].orderTakerAssetFilledAmount).to.be.bignumber.equal(new BigNumber(4)); // only 95% of ETH is sold
|
||||
});
|
||||
it('should throw when invalid transaction and shouldValidate is true', async () => {
|
||||
// create an order with fees, we try to fill it but we do not provide enough ETH to cover the fees
|
||||
const signedOrderWithFee = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
constants.ZERO_AMOUNT,
|
||||
new BigNumber(100),
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
fillableAmount,
|
||||
constants.NULL_ADDRESS,
|
||||
);
|
||||
const signedOrders = [signedOrderWithFee];
|
||||
const makerAssetFillAmount = signedOrder.makerAssetAmount;
|
||||
return expect(
|
||||
contractWrappers.forwarder.marketSellOrdersWithEthAsync(
|
||||
signedOrders,
|
||||
takerAddress,
|
||||
makerAssetFillAmount,
|
||||
[],
|
||||
0,
|
||||
constants.NULL_ADDRESS,
|
||||
{
|
||||
shouldValidate: true,
|
||||
},
|
||||
),
|
||||
).to.be.rejectedWith('COMPLETE_FILL_FAILED');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,146 +0,0 @@
|
||||
import { ContractAddresses } from '@0x/contract-addresses';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
|
||||
import { ContractWrappers, OrderStatus } from '../src';
|
||||
import { OrderInfo, TraderInfo } from '../src/types';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('OrderValidator', () => {
|
||||
const fillableAmount = new BigNumber(5);
|
||||
let contractWrappers: ContractWrappers;
|
||||
let fillScenarios: FillScenarios;
|
||||
let exchangeContractAddress: string;
|
||||
let zrxTokenAddress: string;
|
||||
let zrxTokenAssetData: string;
|
||||
let userAddresses: string[];
|
||||
let coinbase: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipient: string;
|
||||
let anotherMakerAddress: string;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let makerAssetData: string;
|
||||
let takerAssetData: string;
|
||||
let signedOrder: SignedOrder;
|
||||
let anotherSignedOrder: SignedOrder;
|
||||
let contractAddresses: ContractAddresses;
|
||||
|
||||
before(async () => {
|
||||
contractAddresses = await migrateOnceAsync();
|
||||
await blockchainLifecycle.startAsync();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
exchangeContractAddress = contractWrappers.exchange.address;
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress;
|
||||
zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress);
|
||||
fillScenarios = new FillScenarios(
|
||||
provider,
|
||||
userAddresses,
|
||||
zrxTokenAddress,
|
||||
exchangeContractAddress,
|
||||
contractWrappers.erc20Proxy.address,
|
||||
contractWrappers.erc721Proxy.address,
|
||||
);
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
|
||||
[makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
takerTokenAddress = contractAddresses.etherToken;
|
||||
[makerAssetData, takerAssetData] = [
|
||||
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
|
||||
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
|
||||
];
|
||||
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
fillableAmount,
|
||||
);
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
zrxTokenAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#getOrdersAndTradersInfoAsync', () => {
|
||||
let signedOrders: SignedOrder[];
|
||||
let takerAddresses: string[];
|
||||
let ordersInfo: OrderInfo[];
|
||||
let tradersInfo: TraderInfo[];
|
||||
beforeEach(async () => {
|
||||
signedOrders = [signedOrder, anotherSignedOrder];
|
||||
takerAddresses = [takerAddress, takerAddress];
|
||||
const ordersAndTradersInfo = await contractWrappers.orderValidator.getOrdersAndTradersInfoAsync(
|
||||
signedOrders,
|
||||
takerAddresses,
|
||||
);
|
||||
ordersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.orderInfo);
|
||||
tradersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.traderInfo);
|
||||
});
|
||||
it('should return the same number of order infos and trader infos as input orders', async () => {
|
||||
expect(ordersInfo.length).to.be.equal(signedOrders.length);
|
||||
expect(tradersInfo.length).to.be.equal(takerAddresses.length);
|
||||
});
|
||||
it('should return correct on-chain order info for input orders', async () => {
|
||||
const firstOrderInfo = ordersInfo[0];
|
||||
const secondOrderInfo = ordersInfo[1];
|
||||
expect(firstOrderInfo.orderStatus).to.be.equal(OrderStatus.Fillable);
|
||||
expect(firstOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(secondOrderInfo.orderStatus).to.be.equal(OrderStatus.Fillable);
|
||||
expect(secondOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return correct on-chain trader info for input takers', async () => {
|
||||
const firstTraderInfo = tradersInfo[0];
|
||||
const secondTraderInfo = tradersInfo[1];
|
||||
expect(firstTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(firstTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(firstTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0));
|
||||
expect(firstTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0));
|
||||
expect(firstTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(firstTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(firstTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0));
|
||||
expect(firstTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0));
|
||||
expect(secondTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(secondTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(secondTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0));
|
||||
expect(secondTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0));
|
||||
expect(secondTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(secondTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5));
|
||||
expect(secondTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0));
|
||||
expect(secondTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0));
|
||||
});
|
||||
});
|
||||
});
|
@ -1,115 +0,0 @@
|
||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { runMigrationsAsync } from '@0x/migrations';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { ContractWrappers } from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Revert Validation ExchangeWrapper', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
let userAddresses: string[];
|
||||
let fillScenarios: FillScenarios;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let makerAssetData: string;
|
||||
let takerAssetData: string;
|
||||
let txHash: string;
|
||||
let blockchainLifecycle: BlockchainLifecycle;
|
||||
let web3Wrapper: Web3Wrapper;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const takerTokenFillAmount = new BigNumber(5);
|
||||
let signedOrder: SignedOrder;
|
||||
before(async () => {
|
||||
// vmErrorsOnRPCResponse is useful for quick feedback and testing during development
|
||||
// but is not the default behaviour in production. Here we ensure our failure cases
|
||||
// are handled in an environment which behaves similar to production
|
||||
const provider = web3Factory.getRpcProvider({
|
||||
shouldUseInProcessGanache: true,
|
||||
shouldThrowErrorsOnGanacheRPCResponse: false,
|
||||
});
|
||||
web3Wrapper = new Web3Wrapper(provider);
|
||||
blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
// Re-deploy the artifacts in this provider, rather than in the default provider exposed in
|
||||
// the beforeAll hook. This is due to the fact that the default provider enabled vmErrorsOnRPCResponse
|
||||
// and we are explicity testing with vmErrorsOnRPCResponse disabled.
|
||||
const txDefaults = {
|
||||
gas: devConstants.GAS_LIMIT,
|
||||
from: devConstants.TESTRPC_FIRST_ADDRESS,
|
||||
};
|
||||
await blockchainLifecycle.startAsync();
|
||||
const contractAddresses = await runMigrationsAsync(provider, txDefaults);
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
fillScenarios = new FillScenarios(
|
||||
provider,
|
||||
userAddresses,
|
||||
contractAddresses.zrxToken,
|
||||
contractAddresses.exchange,
|
||||
contractAddresses.erc20Proxy,
|
||||
contractAddresses.erc721Proxy,
|
||||
);
|
||||
[, makerAddress, takerAddress] = userAddresses;
|
||||
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
[makerAssetData, takerAssetData] = [
|
||||
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
|
||||
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
|
||||
];
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#fillOrderAsync', () => {
|
||||
it('should throw the revert reason when shouldValidate is true and a fill would revert', async () => {
|
||||
// Create a scenario where the fill will revert
|
||||
const makerTokenBalance = await contractWrappers.erc20Token.getBalanceAsync(
|
||||
makerTokenAddress,
|
||||
makerAddress,
|
||||
);
|
||||
// Transfer all of the tokens from maker to create a failure scenario
|
||||
txHash = await contractWrappers.erc20Token.transferAsync(
|
||||
makerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerTokenBalance,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
return expect(
|
||||
contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress, {
|
||||
shouldValidate: true,
|
||||
}),
|
||||
).to.be.rejectedWith('TRANSFER_FAILED');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,75 +0,0 @@
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { DoneCallback } from '@0x/types';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import {
|
||||
ContractWrappers,
|
||||
ContractWrappersConfig,
|
||||
DecodedLogEvent,
|
||||
ERC20TokenApprovalEventArgs,
|
||||
ERC20TokenEvents,
|
||||
} from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('SubscriptionTest', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
let config: ContractWrappersConfig;
|
||||
|
||||
before(async () => {
|
||||
const contractAddresses = await migrateOnceAsync();
|
||||
config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
let tokenAddress: string;
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
before(() => {
|
||||
const tokenAddresses = tokenUtils.getDummyERC20TokenAddresses();
|
||||
tokenAddress = tokenAddresses[0];
|
||||
});
|
||||
afterEach(() => {
|
||||
contractWrappers.erc20Token.unsubscribeAll();
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
});
|
||||
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) =>
|
||||
_.noop.bind(_);
|
||||
contractWrappers.erc20Token.subscribe(
|
||||
tokenAddress,
|
||||
ERC20TokenEvents.Approval,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
stubs = [
|
||||
Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockIfExistsAsync').throws(
|
||||
new Error('JSON RPC error'),
|
||||
),
|
||||
];
|
||||
contractWrappers.erc20Token.unsubscribeAll();
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,210 +0,0 @@
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils, signatureUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import 'mocha';
|
||||
|
||||
import { ContractWrappers } from '../src';
|
||||
import { TransactionEncoder } from '../src/utils/transaction_encoder';
|
||||
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
import { tokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('TransactionEncoder', () => {
|
||||
let contractWrappers: ContractWrappers;
|
||||
let userAddresses: string[];
|
||||
let fillScenarios: FillScenarios;
|
||||
let exchangeContractAddress: string;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let coinbase: string;
|
||||
let makerAddress: string;
|
||||
let senderAddress: string;
|
||||
let takerAddress: string;
|
||||
let makerAssetData: string;
|
||||
let takerAssetData: string;
|
||||
let txHash: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const takerTokenFillAmount = new BigNumber(5);
|
||||
let signedOrder: SignedOrder;
|
||||
|
||||
before(async () => {
|
||||
const contractAddresses = await migrateOnceAsync();
|
||||
await blockchainLifecycle.startAsync();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
contractAddresses,
|
||||
blockPollingIntervalMs: 10,
|
||||
};
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
exchangeContractAddress = contractWrappers.exchange.address;
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress;
|
||||
fillScenarios = new FillScenarios(
|
||||
provider,
|
||||
userAddresses,
|
||||
zrxTokenAddress,
|
||||
exchangeContractAddress,
|
||||
contractWrappers.erc20Proxy.address,
|
||||
contractWrappers.erc721Proxy.address,
|
||||
);
|
||||
[coinbase, makerAddress, takerAddress, senderAddress] = userAddresses;
|
||||
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
[makerAssetData, takerAssetData] = [
|
||||
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
|
||||
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
|
||||
];
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('encode and executeTransaction', () => {
|
||||
const executeTransactionOrThrowAsync = async (
|
||||
encoder: TransactionEncoder,
|
||||
data: string,
|
||||
signerAddress: string = takerAddress,
|
||||
): Promise<void> => {
|
||||
const salt = generatePseudoRandomSalt();
|
||||
const transactionHash = encoder.getTransactionHashHex(data, salt, signerAddress);
|
||||
const signature = await signatureUtils.ecSignHashAsync(provider, transactionHash, signerAddress);
|
||||
txHash = await contractWrappers.exchange.executeTransactionAsync(
|
||||
salt,
|
||||
signerAddress,
|
||||
data,
|
||||
signature,
|
||||
senderAddress,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
};
|
||||
describe('#fillOrderTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.fillOrderTx(signedOrder, takerTokenFillAmount);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#fillOrderNoThrowTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.fillOrderNoThrowTx(signedOrder, takerTokenFillAmount);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#fillOrKillOrderTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.fillOrKillOrderTx(signedOrder, takerTokenFillAmount);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#marketSellOrdersTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.marketSellOrdersTx([signedOrder], takerTokenFillAmount);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#marketSellOrdersNoThrowTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.marketSellOrdersNoThrowTx([signedOrder], takerTokenFillAmount);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#marketBuyOrdersTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.marketBuyOrdersTx([signedOrder], fillableAmount);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#marketBuyOrdersNoThrowTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.marketBuyOrdersNoThrowTx([signedOrder], fillableAmount);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#preSignTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const signature = signedOrder.signature;
|
||||
const data = encoder.preSignTx(orderHash, makerAddress, signature);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#setSignatureValidatorApprovalTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const isApproved = true;
|
||||
const data = encoder.setSignatureValidatorApprovalTx(senderAddress, isApproved);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#batchFillOrdersTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.batchFillOrdersTx([signedOrder], [takerTokenFillAmount]);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#batchFillOrKillOrdersTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.batchFillOrKillOrdersTx([signedOrder], [takerTokenFillAmount]);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#batchFillOrdersNoThrowTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.batchFillOrdersNoThrowTx([signedOrder], [takerTokenFillAmount]);
|
||||
await executeTransactionOrThrowAsync(encoder, data);
|
||||
});
|
||||
});
|
||||
describe('#batchCancelOrdersTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.batchCancelOrdersTx([signedOrder]);
|
||||
const signerAddress = makerAddress;
|
||||
await executeTransactionOrThrowAsync(encoder, data, signerAddress);
|
||||
});
|
||||
});
|
||||
describe('#cancelOrderTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const data = encoder.cancelOrderTx(signedOrder);
|
||||
const signerAddress = makerAddress;
|
||||
await executeTransactionOrThrowAsync(encoder, data, signerAddress);
|
||||
});
|
||||
});
|
||||
describe('#cancelOrdersUpToTx', () => {
|
||||
it('should successfully execute the transaction', async () => {
|
||||
const encoder = await contractWrappers.exchange.transactionEncoderAsync();
|
||||
const targetEpoch = signedOrder.salt;
|
||||
const data = encoder.cancelOrdersUpToTx(targetEpoch);
|
||||
const signerAddress = makerAddress;
|
||||
await executeTransactionOrThrowAsync(encoder, data, signerAddress);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user