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
|
*.svg linguist-generated=true
|
||||||
packages/contract-artifacts/artifacts/*json linguist-generated=true
|
packages/contract-artifacts/artifacts/*json linguist-generated=true
|
||||||
packages/abi-gen-wrappers/src/generated-wrappers/*.ts 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",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^3.1.2",
|
"@0x/abi-gen": "^3.1.2",
|
||||||
"@0x/contract-wrappers": "^10.1.0",
|
|
||||||
"@0x/contracts-gen": "^1.0.12",
|
"@0x/contracts-gen": "^1.0.12",
|
||||||
"@0x/contracts-test-utils": "^3.1.12",
|
"@0x/contracts-test-utils": "^3.1.12",
|
||||||
"@0x/dev-utils": "^2.2.6",
|
"@0x/dev-utils": "^2.2.6",
|
||||||
|
@ -47,7 +47,6 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^3.1.2",
|
"@0x/abi-gen": "^3.1.2",
|
||||||
"@0x/contract-wrappers": "^10.1.0",
|
|
||||||
"@0x/contracts-gen": "^1.0.12",
|
"@0x/contracts-gen": "^1.0.12",
|
||||||
"@0x/contracts-test-utils": "^3.1.12",
|
"@0x/contracts-test-utils": "^3.1.12",
|
||||||
"@0x/dev-utils": "^2.2.6",
|
"@0x/dev-utils": "^2.2.6",
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^3.1.2",
|
"@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-gen": "^1.0.12",
|
||||||
"@0x/contracts-test-utils": "^3.1.12",
|
"@0x/contracts-test-utils": "^3.1.12",
|
||||||
"@0x/dev-utils": "^2.2.6",
|
"@0x/dev-utils": "^2.2.6",
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
"config": {
|
"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",
|
"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",
|
"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",
|
"ignoreDependencyVersions": "@types/styled-components @types/node",
|
||||||
"ignoreDependencyVersionsForPackage": "website instant dev-tools-pages"
|
"ignoreDependencyVersionsForPackage": "website instant dev-tools-pages"
|
||||||
},
|
},
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
"@0x/assert": "^2.1.2",
|
"@0x/assert": "^2.1.2",
|
||||||
"@0x/asset-swapper": "^1.0.0",
|
"@0x/asset-swapper": "^1.0.0",
|
||||||
"@0x/base-contract": "^5.3.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-utils": "^8.2.4",
|
||||||
"@0x/order-watcher": "^4.0.16",
|
"@0x/order-watcher": "^4.0.16",
|
||||||
"@0x/subproviders": "^5.0.0",
|
"@0x/subproviders": "^5.0.0",
|
||||||
|
@ -40,6 +40,13 @@ export {
|
|||||||
} from '@0x/contract-wrappers';
|
} from '@0x/contract-wrappers';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
DutchAuctionContract,
|
||||||
|
ERC20ProxyContract,
|
||||||
|
ERC721ProxyContract,
|
||||||
|
ExchangeContract,
|
||||||
|
ForwarderContract,
|
||||||
|
OrderValidatorContract,
|
||||||
|
WETH9Contract,
|
||||||
WETH9Events,
|
WETH9Events,
|
||||||
WETH9WithdrawalEventArgs,
|
WETH9WithdrawalEventArgs,
|
||||||
WETH9ApprovalEventArgs,
|
WETH9ApprovalEventArgs,
|
||||||
@ -102,15 +109,12 @@ export {
|
|||||||
ObjectMap,
|
ObjectMap,
|
||||||
OrderRelevantState,
|
OrderRelevantState,
|
||||||
Stats,
|
Stats,
|
||||||
DutchAuctionDetails,
|
|
||||||
ZeroExTransaction,
|
ZeroExTransaction,
|
||||||
SignedZeroExTransaction,
|
SignedZeroExTransaction,
|
||||||
} from '@0x/types';
|
} from '@0x/types';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
BlockParamLiteral,
|
|
||||||
ContractAbi,
|
ContractAbi,
|
||||||
BlockParam,
|
|
||||||
LogWithDecodedArgs,
|
LogWithDecodedArgs,
|
||||||
ContractEventArg,
|
ContractEventArg,
|
||||||
SupportedProvider,
|
SupportedProvider,
|
||||||
|
@ -83,9 +83,11 @@ export class {{contractName}}Contract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {{contractName}}Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, {{> params inputs=ctor.inputs}});
|
return {{contractName}}Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, {{> params inputs=ctor.inputs}});
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -3119,9 +3119,11 @@ export class AssetProxyOwnerContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return AssetProxyOwnerContract.deployAsync(
|
return AssetProxyOwnerContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -1005,9 +1005,11 @@ export class CoordinatorContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return CoordinatorContract.deployAsync(
|
return CoordinatorContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -298,9 +298,11 @@ export class CoordinatorRegistryContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return CoordinatorRegistryContract.deployAsync(
|
return CoordinatorRegistryContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -1660,9 +1660,11 @@ export class DummyERC20TokenContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return DummyERC20TokenContract.deployAsync(
|
return DummyERC20TokenContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -2116,9 +2116,11 @@ export class DummyERC721TokenContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return DummyERC721TokenContract.deployAsync(
|
return DummyERC721TokenContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -795,9 +795,11 @@ export class DutchAuctionContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return DutchAuctionContract.deployAsync(
|
return DutchAuctionContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -1043,9 +1043,11 @@ export class ERC20ProxyContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ERC20ProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return ERC20ProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -866,9 +866,11 @@ export class ERC20TokenContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ERC20TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return ERC20TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -1043,9 +1043,11 @@ export class ERC721ProxyContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ERC721ProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return ERC721ProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -1428,9 +1428,11 @@ export class ERC721TokenContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ERC721TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return ERC721TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -119,9 +119,11 @@ export class EthBalanceCheckerContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return EthBalanceCheckerContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return EthBalanceCheckerContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -6498,9 +6498,11 @@ export class ExchangeContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ExchangeContract.deployAsync(
|
return ExchangeContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -1501,9 +1501,11 @@ export class ForwarderContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ForwarderContract.deployAsync(
|
return ForwarderContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -1041,9 +1041,11 @@ export class IAssetProxyContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return IAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return IAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -137,9 +137,11 @@ export class IValidatorContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return IValidatorContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return IValidatorContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -127,9 +127,11 @@ export class IWalletContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return IWalletContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return IWalletContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -1345,9 +1345,11 @@ export class MultiAssetProxyContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return MultiAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return MultiAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -1014,9 +1014,11 @@ export class OrderValidatorContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return OrderValidatorContract.deployAsync(
|
return OrderValidatorContract.deployAsync(
|
||||||
bytecode,
|
bytecode,
|
||||||
abi,
|
abi,
|
||||||
|
@ -1265,9 +1265,11 @@ export class WETH9Contract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return WETH9Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return WETH9Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -1009,9 +1009,11 @@ export class ZRXTokenContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ZRXTokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return ZRXTokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -2372,9 +2372,11 @@ export class AbiGenDummyContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return AbiGenDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return AbiGenDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -45,9 +45,11 @@ export class LibDummyContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return LibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return LibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -173,9 +173,11 @@ export class TestLibDummyContract extends BaseContract {
|
|||||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||||
const abi = artifact.compilerOutput.abi;
|
const abi = artifact.compilerOutput.abi;
|
||||||
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
|
||||||
|
if (Object.keys(logDecodeDependencies) !== undefined) {
|
||||||
for (const key of Object.keys(logDecodeDependencies)) {
|
for (const key of Object.keys(logDecodeDependencies)) {
|
||||||
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return TestLibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
return TestLibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
|
||||||
}
|
}
|
||||||
public static async deployAsync(
|
public static async deployAsync(
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^2.1.2",
|
"@0x/assert": "^2.1.2",
|
||||||
"@0x/connect": "^5.0.15",
|
"@0x/connect": "^5.0.15",
|
||||||
"@0x/contract-wrappers": "^10.1.0",
|
"@0x/contract-wrappers": "10.1.0",
|
||||||
"@0x/json-schemas": "^3.1.12",
|
"@0x/json-schemas": "^3.1.12",
|
||||||
"@0x/order-utils": "^8.2.4",
|
"@0x/order-utils": "^8.2.4",
|
||||||
"@0x/subproviders": "^5.0.0",
|
"@0x/subproviders": "^5.0.0",
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
"@0x/assert": "^2.1.2",
|
"@0x/assert": "^2.1.2",
|
||||||
"@0x/connect": "^5.0.15",
|
"@0x/connect": "^5.0.15",
|
||||||
"@0x/contract-addresses": "^3.0.2",
|
"@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/dev-utils": "^2.2.6",
|
||||||
"@0x/fill-scenarios": "^3.0.15",
|
"@0x/fill-scenarios": "^3.0.15",
|
||||||
"@0x/json-schemas": "^3.1.12",
|
"@0x/json-schemas": "^3.1.12",
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
||||||
import { tokenUtils } from '@0x/contract-wrappers/lib/test/utils/token_utils';
|
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
|
||||||
import { FillScenarios } from '@0x/fill-scenarios';
|
import { FillScenarios } from '@0x/fill-scenarios';
|
||||||
import { assetDataUtils } from '@0x/order-utils';
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
import { MarketOperation, SignedOrder } from '@0x/types';
|
import { MarketOperation, SignedOrder } from '@0x/types';
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
||||||
import { tokenUtils } from '@0x/contract-wrappers/lib/test/utils/token_utils';
|
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
|
||||||
import { assetDataUtils } from '@0x/order-utils';
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
import { MarketOperation, SignedOrder } from '@0x/types';
|
import { MarketOperation, SignedOrder } from '@0x/types';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
|
||||||
import { tokenUtils } from '@0x/contract-wrappers/lib/test/utils/token_utils';
|
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
|
||||||
import { assetDataUtils } from '@0x/order-utils';
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
import { MarketOperation, SignedOrder } from '@0x/types';
|
import { MarketOperation, SignedOrder } from '@0x/types';
|
||||||
import { BigNumber } from '@0x/utils';
|
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",
|
"version": "10.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
## @0x/contract-wrappers
|
## @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.
|
Wrappers for 0x smart contracts, generated using @0x/abi-gen.
|
||||||
|
|
||||||
### Read the [Documentation](https://0xproject.com/docs/0x.js).
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -14,7 +12,7 @@ npm install @0x/contract-wrappers --save
|
|||||||
|
|
||||||
**Import**
|
**Import**
|
||||||
|
|
||||||
```javascript
|
```typescript
|
||||||
import { ContractWrappers } from '@0x/contract-wrappers';
|
import { ContractWrappers } from '@0x/contract-wrappers';
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -28,7 +26,7 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
|||||||
|
|
||||||
## Contributing
|
## 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.
|
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
|
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
|
### Clean
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -87,3 +69,9 @@ yarn lint
|
|||||||
```bash
|
```bash
|
||||||
yarn test
|
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",
|
"name": "@0x/contract-wrappers",
|
||||||
"version": "10.1.0",
|
"version": "11.0.0",
|
||||||
"description": "Smart TS wrappers for 0x smart contracts",
|
"engines": {
|
||||||
|
"node": ">=6.12"
|
||||||
|
},
|
||||||
|
"description": "Wrappers for 0x smart contract wrappers generated using @0x/abi-gen",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"0xproject",
|
"0xproject",
|
||||||
"ethereum",
|
"ethereum",
|
||||||
@ -10,34 +13,43 @@
|
|||||||
],
|
],
|
||||||
"main": "lib/src/index.js",
|
"main": "lib/src/index.js",
|
||||||
"types": "lib/src/index.d.ts",
|
"types": "lib/src/index.d.ts",
|
||||||
|
"directories": {
|
||||||
|
"test": "test"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -b",
|
"build": "yarn pre_build && tsc -b",
|
||||||
"build:ci": "yarn build",
|
"build:ci": "yarn build",
|
||||||
"lint": "tslint --format stylish --project . --exclude **/lib/**/*",
|
"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:circleci": "run-s test:coverage",
|
||||||
"test": "yarn run_mocha",
|
"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",
|
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||||
"clean": "shx rm -rf _bundles lib test_temp generated_docs",
|
"pre_build": "yarn generate_contract_wrappers && yarn prettier_contract_wrappers",
|
||||||
"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",
|
"prettier": "prettier --write **/* --config ../../.prettierrc",
|
||||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
"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": {
|
"config": {
|
||||||
"postpublish": {
|
"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"
|
||||||
"assets": []
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/0xProject/0x-monorepo"
|
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"bugs": {
|
||||||
"node": ">=6.0.0"
|
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||||
},
|
},
|
||||||
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contract-wrappers/README.md",
|
||||||
"devDependencies": {
|
"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/contracts-test-utils": "^3.1.12",
|
||||||
"@0x/coordinator-server": "^0.1.3",
|
"@0x/coordinator-server": "^0.1.3",
|
||||||
"@0x/dev-utils": "^2.2.6",
|
"@0x/dev-utils": "^2.2.6",
|
||||||
@ -45,52 +57,34 @@
|
|||||||
"@0x/migrations": "^4.1.11",
|
"@0x/migrations": "^4.1.11",
|
||||||
"@0x/subproviders": "^5.0.0",
|
"@0x/subproviders": "^5.0.0",
|
||||||
"@0x/tslint-config": "^3.0.1",
|
"@0x/tslint-config": "^3.0.1",
|
||||||
"@types/lodash": "4.14.104",
|
"@0x/types": "^2.4.1",
|
||||||
"@types/mocha": "^5.2.7",
|
"@0x/utils": "^4.4.2",
|
||||||
"@types/nock": "^10.0.1",
|
"@0x/web3-wrapper": "^6.0.9",
|
||||||
"@types/node": "*",
|
"@types/nock": "^10.0.3",
|
||||||
"@types/sinon": "^2.2.2",
|
"ethereum-types": "^2.1.4",
|
||||||
"@types/uuid": "^3.4.3",
|
"ethers": "~4.0.4",
|
||||||
"@types/web3-provider-engine": "^14.0.0",
|
"lodash": "^4.17.11",
|
||||||
|
"shx": "^0.2.2",
|
||||||
"chai": "^4.0.1",
|
"chai": "^4.0.1",
|
||||||
"chai-as-promised": "^7.1.0",
|
"chai-as-promised": "^7.1.0",
|
||||||
"chai-bignumber": "^3.0.0",
|
"chai-bignumber": "^3.0.0",
|
||||||
"dirty-chai": "^2.0.1",
|
"dirty-chai": "^2.0.1",
|
||||||
"make-promises-safe": "^1.1.0",
|
|
||||||
"mocha": "^6.2.0",
|
"mocha": "^6.2.0",
|
||||||
"nock": "^10.0.6",
|
"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"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/abi-gen-wrappers": "^5.1.0",
|
"@0x/abi-gen-wrappers": "^5.1.0",
|
||||||
"@0x/assert": "^2.1.2",
|
|
||||||
"@0x/base-contract": "^5.3.0",
|
"@0x/base-contract": "^5.3.0",
|
||||||
"@0x/contract-addresses": "^3.0.2",
|
"@0x/contract-addresses": "^3.0.2",
|
||||||
"@0x/contract-artifacts": "^2.0.3",
|
"@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/order-utils": "^8.2.4",
|
||||||
"@0x/types": "^2.4.1",
|
"@0x/subproviders": "^5.0.0",
|
||||||
"@0x/typescript-typings": "^4.2.4",
|
"http-status-codes": "^1.3.2"
|
||||||
"@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"
|
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"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 { SupportedProvider } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { CoordinatorWrapper } from './contract_wrappers/coordinator_wrapper';
|
import { CoordinatorWrapper } from './coordinator_wrapper';
|
||||||
import { DutchAuctionWrapper } from './contract_wrappers/dutch_auction_wrapper';
|
import { DutchAuctionContract } from './generated-wrappers/dutch_auction';
|
||||||
import { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
|
import { ERC20ProxyContract } from './generated-wrappers/erc20_proxy';
|
||||||
import { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
|
import { ERC721ProxyContract } from './generated-wrappers/erc721_proxy';
|
||||||
import { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
|
import { ExchangeContract } from './generated-wrappers/exchange';
|
||||||
import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
|
import { ForwarderContract } from './generated-wrappers/forwarder';
|
||||||
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
|
import { OrderValidatorContract } from './generated-wrappers/order_validator';
|
||||||
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
|
|
||||||
import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
|
import { WETH9Contract } from './generated-wrappers/weth9';
|
||||||
import { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper';
|
|
||||||
import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema';
|
import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema';
|
||||||
import { ContractWrappersConfig } from './types';
|
import { ContractWrappersConfig } from './types';
|
||||||
import { assert } from './utils/assert';
|
import { assert } from './utils/assert';
|
||||||
import { constants } from './utils/constants';
|
|
||||||
import { _getDefaultContractAddresses } from './utils/contract_addresses';
|
import { _getDefaultContractAddresses } from './utils/contract_addresses';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,45 +34,36 @@ import { _getDefaultContractAddresses } from './utils/contract_addresses';
|
|||||||
*/
|
*/
|
||||||
export class ContractWrappers {
|
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.
|
* An instance of the ERC20ProxyContract class containing methods for interacting with the
|
||||||
*/
|
|
||||||
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
|
|
||||||
* erc20Proxy smart contract.
|
* 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.
|
* 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.
|
* 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 => {
|
_.forEach(artifactsArray, artifact => {
|
||||||
this._web3Wrapper.abiDecoder.addABI(artifact.compilerOutput.abi, artifact.contractName);
|
this._web3Wrapper.abiDecoder.addABI(artifact.compilerOutput.abi, artifact.contractName);
|
||||||
});
|
});
|
||||||
const blockPollingIntervalMs =
|
|
||||||
config.blockPollingIntervalMs === undefined
|
|
||||||
? constants.DEFAULT_BLOCK_POLLING_INTERVAL
|
|
||||||
: config.blockPollingIntervalMs;
|
|
||||||
const contractAddresses =
|
const contractAddresses =
|
||||||
config.contractAddresses === undefined
|
config.contractAddresses === undefined
|
||||||
? _getDefaultContractAddresses(config.networkId)
|
? _getDefaultContractAddresses(config.networkId)
|
||||||
: config.contractAddresses;
|
: config.contractAddresses;
|
||||||
this.erc20Proxy = new ERC20ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc20Proxy);
|
this.erc20Proxy = new ERC20ProxyContract(contractAddresses.erc20Proxy, this.getProvider());
|
||||||
this.erc721Proxy = new ERC721ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc721Proxy);
|
this.erc721Proxy = new ERC721ProxyContract(contractAddresses.erc721Proxy, this.getProvider());
|
||||||
this.erc20Token = new ERC20TokenWrapper(this._web3Wrapper, this.erc20Proxy, blockPollingIntervalMs);
|
this.weth9 = new WETH9Contract(contractAddresses.etherToken, this.getProvider());
|
||||||
this.erc721Token = new ERC721TokenWrapper(this._web3Wrapper, this.erc721Proxy, blockPollingIntervalMs);
|
this.exchange = new ExchangeContract(contractAddresses.exchange, this.getProvider());
|
||||||
this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.erc20Token, blockPollingIntervalMs);
|
this.forwarder = new ForwarderContract(contractAddresses.forwarder, this.getProvider());
|
||||||
this.exchange = new ExchangeWrapper(
|
this.orderValidator = new OrderValidatorContract(contractAddresses.orderValidator, this.getProvider());
|
||||||
this._web3Wrapper,
|
this.dutchAuction = new DutchAuctionContract(contractAddresses.dutchAuction, this.getProvider());
|
||||||
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.coordinator = new CoordinatorWrapper(
|
this.coordinator = new CoordinatorWrapper(
|
||||||
this._web3Wrapper,
|
this._web3Wrapper,
|
||||||
config.networkId,
|
config.networkId,
|
||||||
@ -161,9 +122,9 @@ export class ContractWrappers {
|
|||||||
*/
|
*/
|
||||||
public unsubscribeAll(): void {
|
public unsubscribeAll(): void {
|
||||||
this.exchange.unsubscribeAll();
|
this.exchange.unsubscribeAll();
|
||||||
this.erc20Token.unsubscribeAll();
|
this.erc20Proxy.unsubscribeAll();
|
||||||
this.erc721Token.unsubscribeAll();
|
this.erc721Proxy.unsubscribeAll();
|
||||||
this.etherToken.unsubscribeAll();
|
this.weth9.unsubscribeAll();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get the provider instance currently used by contract-wrappers
|
* 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 { getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses';
|
||||||
import { Coordinator } from '@0x/contract-artifacts';
|
import { Coordinator } from '@0x/contract-artifacts';
|
||||||
import { schemas } from '@0x/json-schemas';
|
import { schemas } from '@0x/json-schemas';
|
||||||
@ -10,10 +9,12 @@ import { ContractAbi } from 'ethereum-types';
|
|||||||
import * as HttpStatus from 'http-status-codes';
|
import * as HttpStatus from 'http-status-codes';
|
||||||
import { flatten } from 'lodash';
|
import { flatten } from 'lodash';
|
||||||
|
|
||||||
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
|
import { CoordinatorContract, CoordinatorRegistryContract, ExchangeContract } from './index';
|
||||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
|
||||||
import { CoordinatorTransaction, OrderTransactionOpts } from '../types';
|
import { orderTxOptsSchema } from './schemas/order_tx_opts_schema';
|
||||||
import { assert } from '../utils/assert';
|
import { txOptsSchema } from './schemas/tx_opts_schema';
|
||||||
|
import { CoordinatorTransaction, OrderTransactionOpts } from './types';
|
||||||
|
import { assert } from './utils/assert';
|
||||||
import {
|
import {
|
||||||
CoordinatorServerApprovalRawResponse,
|
CoordinatorServerApprovalRawResponse,
|
||||||
CoordinatorServerApprovalResponse,
|
CoordinatorServerApprovalResponse,
|
||||||
@ -21,9 +22,9 @@ import {
|
|||||||
CoordinatorServerError,
|
CoordinatorServerError,
|
||||||
CoordinatorServerErrorMsg,
|
CoordinatorServerErrorMsg,
|
||||||
CoordinatorServerResponse,
|
CoordinatorServerResponse,
|
||||||
} from '../utils/coordinator_server_types';
|
} from './utils/coordinator_server_types';
|
||||||
import { decorators } from '../utils/decorators';
|
import { decorators } from './utils/decorators';
|
||||||
import { TransactionEncoder } from '../utils/transaction_encoder';
|
import { getAbiEncodedTransactionData } from './utils/getAbiEncodedTransactionData';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to filling or cancelling orders through
|
* 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 _contractInstance: CoordinatorContract;
|
||||||
private readonly _registryInstance: CoordinatorRegistryContract;
|
private readonly _registryInstance: CoordinatorRegistryContract;
|
||||||
private readonly _exchangeInstance: ExchangeContract;
|
private readonly _exchangeInstance: ExchangeContract;
|
||||||
private readonly _transactionEncoder: TransactionEncoder;
|
|
||||||
private readonly _feeRecipientToEndpoint: { [feeRecipient: string]: string } = {};
|
private readonly _feeRecipientToEndpoint: { [feeRecipient: string]: string } = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,8 +82,6 @@ export class CoordinatorWrapper {
|
|||||||
this._web3Wrapper.getProvider(),
|
this._web3Wrapper.getProvider(),
|
||||||
this._web3Wrapper.getContractDefaults(),
|
this._web3Wrapper.getContractDefaults(),
|
||||||
);
|
);
|
||||||
|
|
||||||
this._transactionEncoder = new TransactionEncoder(this._exchangeInstance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,7 +110,12 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -139,7 +142,12 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -167,7 +175,12 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -201,7 +214,13 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -230,7 +249,13 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -259,7 +284,13 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -291,7 +322,13 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -323,7 +360,13 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -350,7 +393,13 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -377,7 +426,13 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
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);
|
const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@ -394,7 +449,7 @@ export class CoordinatorWrapper {
|
|||||||
assert.isETHAddressHex('feeRecipientAddress', order.feeRecipientAddress);
|
assert.isETHAddressHex('feeRecipientAddress', order.feeRecipientAddress);
|
||||||
assert.isSenderAddressAsync('makerAddress', order.makerAddress, this._web3Wrapper);
|
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 transaction = await this._generateSignedZeroExTransactionAsync(data, order.makerAddress);
|
||||||
const endpoint = await this._getServerEndpointOrThrowAsync(order.feeRecipientAddress);
|
const endpoint = await this._getServerEndpointOrThrowAsync(order.feeRecipientAddress);
|
||||||
|
|
||||||
@ -428,7 +483,7 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
|
assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
|
||||||
const makerAddress = getMakerAddressOrThrow(orders);
|
const makerAddress = getMakerAddressOrThrow(orders);
|
||||||
assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
|
assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
|
||||||
const data = this._transactionEncoder.batchCancelOrdersTx(orders);
|
const data = this._getAbiEncodedTransactionData('batchCancelOrders', orders);
|
||||||
|
|
||||||
const serverEndpointsToOrders = await this._mapServerEndpointsToOrdersAsync(orders);
|
const serverEndpointsToOrders = await this._mapServerEndpointsToOrdersAsync(orders);
|
||||||
|
|
||||||
@ -486,7 +541,7 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('makerAddress', order.makerAddress, this._web3Wrapper);
|
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 transaction = await this._generateSignedZeroExTransactionAsync(data, order.makerAddress);
|
||||||
|
|
||||||
const approvalSignatures = new Array();
|
const approvalSignatures = new Array();
|
||||||
@ -519,7 +574,7 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
|
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 transaction = await this._generateSignedZeroExTransactionAsync(data, makerAddress);
|
||||||
|
|
||||||
const approvalSignatures = new Array();
|
const approvalSignatures = new Array();
|
||||||
@ -554,7 +609,7 @@ export class CoordinatorWrapper {
|
|||||||
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
|
||||||
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
|
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 transaction = await this._generateSignedZeroExTransactionAsync(data, senderAddress);
|
||||||
|
|
||||||
const approvalSignatures = new Array();
|
const approvalSignatures = new Array();
|
||||||
@ -618,6 +673,10 @@ export class CoordinatorWrapper {
|
|||||||
return signerAddress;
|
return signerAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _getAbiEncodedTransactionData<K extends keyof ExchangeContract>(methodName: K, ...args: any[]): string {
|
||||||
|
return getAbiEncodedTransactionData(this._exchangeInstance, methodName, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
private async _handleFillsAsync(
|
private async _handleFillsAsync(
|
||||||
data: string,
|
data: string,
|
||||||
takerAddress: 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 {
|
export * from '@0x/contract-addresses';
|
||||||
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 { ContractWrappers } from './contract_wrappers';
|
export { ContractWrappers } from './contract_wrappers';
|
||||||
export { CoordinatorWrapper } from './contract_wrappers/coordinator_wrapper';
|
export { CoordinatorWrapper } from './coordinator_wrapper';
|
||||||
export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
|
export { OrderStatus } from './types';
|
||||||
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';
|
|
||||||
|
@ -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 { ContractAddresses } from '@0x/contract-addresses';
|
||||||
import { OrderState, SignedOrder } from '@0x/types';
|
|
||||||
import { BigNumber } from '@0x/utils';
|
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> {
|
export interface DecodedLogEvent<ArgsType extends DecodedLogArgs> {
|
||||||
isRemoved: boolean;
|
isRemoved: boolean;
|
||||||
log: LogWithDecodedArgs<ArgsType>;
|
log: LogWithDecodedArgs<ArgsType>;
|
||||||
@ -52,30 +13,6 @@ export type EventCallback<ArgsType extends DecodedLogArgs> = (
|
|||||||
log?: DecodedLogEvent<ArgsType>,
|
log?: DecodedLogEvent<ArgsType>,
|
||||||
) => void;
|
) => 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 {
|
export interface TxOpts {
|
||||||
from: string;
|
from: string;
|
||||||
gas?: number;
|
gas?: number;
|
||||||
@ -83,29 +20,10 @@ export interface TxOpts {
|
|||||||
gasPrice?: BigNumber;
|
gasPrice?: BigNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TokenAddressBySymbol {
|
|
||||||
[symbol: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ContractEvents = ERC20TokenEvents | ERC721TokenEvents | ExchangeEvents | WETH9Events;
|
|
||||||
|
|
||||||
export interface IndexedFilterValues {
|
export interface IndexedFilterValues {
|
||||||
[index: string]: ContractEventArg;
|
[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)
|
* 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
|
* gasPrice: Gas price to use with every transaction
|
||||||
@ -119,35 +37,6 @@ export interface ContractWrappersConfig {
|
|||||||
blockPollingIntervalMs?: number;
|
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
|
* gasPrice: Gas price in Wei to use for a transaction
|
||||||
* gasLimit: The amount of gas to send with a transaction (in Gwei)
|
* gasLimit: The amount of gas to send with a transaction (in Gwei)
|
||||||
@ -167,18 +56,6 @@ export interface OrderTransactionOpts extends TransactionOpts {
|
|||||||
shouldValidate?: boolean;
|
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 {
|
export interface OrderInfo {
|
||||||
orderStatus: OrderStatus;
|
orderStatus: OrderStatus;
|
||||||
orderHash: string;
|
orderHash: string;
|
||||||
@ -195,31 +72,6 @@ export enum OrderStatus {
|
|||||||
Cancelled,
|
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 { CoordinatorServerCancellationResponse, CoordinatorServerError } from './utils/coordinator_server_types';
|
||||||
|
|
||||||
export interface CoordinatorTransaction {
|
export interface CoordinatorTransaction {
|
||||||
|
@ -8,7 +8,7 @@ import { Web3Wrapper } from '@0x/web3-wrapper';
|
|||||||
import { SupportedProvider } from 'ethereum-types';
|
import { SupportedProvider } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { constants } from './constants';
|
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||||
|
|
||||||
export const assert = {
|
export const assert = {
|
||||||
...sharedAssert,
|
...sharedAssert,
|
||||||
@ -56,7 +56,7 @@ export const assert = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
allTakerAddressesAreNull(orders: Order[]): void {
|
allTakerAddressesAreNull(orders: Order[]): void {
|
||||||
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', constants.NULL_ADDRESS);
|
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', NULL_ADDRESS);
|
||||||
},
|
},
|
||||||
allMakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void {
|
allMakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void {
|
||||||
assert.ordersHaveAtMostOneUniqueValueForProperty(
|
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 * 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;
|
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 'mocha';
|
||||||
|
|
||||||
import { ContractAddresses, ContractWrappers } from '../src';
|
import { ContractAddresses, ContractWrappers } from '../src';
|
||||||
|
import { getAbiEncodedTransactionData } from '../src/utils/getAbiEncodedTransactionData';
|
||||||
|
|
||||||
import { chaiSetup } from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import { migrateOnceAsync } from './utils/migrate';
|
import { migrateOnceAsync } from './utils/migrate';
|
||||||
@ -80,8 +81,14 @@ describe('ABI Decoding Calldata', () => {
|
|||||||
blockPollingIntervalMs: 10,
|
blockPollingIntervalMs: 10,
|
||||||
};
|
};
|
||||||
contractWrappers = new ContractWrappers(provider, config);
|
contractWrappers = new ContractWrappers(provider, config);
|
||||||
const transactionEncoder = await contractWrappers.exchange.transactionEncoderAsync();
|
matchOrdersTxData = getAbiEncodedTransactionData(
|
||||||
matchOrdersTxData = transactionEncoder.matchOrdersTx(signedOrderLeft, signedOrderRight);
|
contractWrappers.exchange,
|
||||||
|
'matchOrders',
|
||||||
|
signedOrderLeft,
|
||||||
|
signedOrderRight,
|
||||||
|
signedOrderLeft.signature,
|
||||||
|
signedOrderRight.signature,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('decode', () => {
|
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 { CoordinatorRegistryContract } from '@0x/abi-gen-wrappers';
|
||||||
import { constants } from '@0x/contracts-test-utils';
|
import { constants } from '@0x/contracts-test-utils';
|
||||||
import { defaultOrmConfig, getAppAsync } from '@0x/coordinator-server';
|
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 { FillScenarios } from '@0x/fill-scenarios';
|
||||||
import { assetDataUtils } from '@0x/order-utils';
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
import { SignedOrder } from '@0x/types';
|
import { SignedOrder } from '@0x/types';
|
||||||
@ -16,7 +16,6 @@ import { CoordinatorServerErrorMsg } from '../src/utils/coordinator_server_types
|
|||||||
|
|
||||||
import { chaiSetup } from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import { migrateOnceAsync } from './utils/migrate';
|
import { migrateOnceAsync } from './utils/migrate';
|
||||||
import { tokenUtils } from './utils/token_utils';
|
|
||||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
@ -71,7 +70,7 @@ describe('CoordinatorWrapper', () => {
|
|||||||
contractWrappers = new ContractWrappers(provider, config);
|
contractWrappers = new ContractWrappers(provider, config);
|
||||||
exchangeContractAddress = contractWrappers.exchange.address;
|
exchangeContractAddress = contractWrappers.exchange.address;
|
||||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress;
|
zrxTokenAddress = contractAddresses.zrxToken;
|
||||||
fillScenarios = new FillScenarios(
|
fillScenarios = new FillScenarios(
|
||||||
provider,
|
provider,
|
||||||
userAddresses,
|
userAddresses,
|
||||||
@ -422,7 +421,7 @@ describe('CoordinatorWrapper', () => {
|
|||||||
txHash = await contractWrappers.coordinator.hardCancelOrdersUpToAsync(targetOrderEpoch, makerAddress);
|
txHash = await contractWrappers.coordinator.hardCancelOrdersUpToAsync(targetOrderEpoch, makerAddress);
|
||||||
|
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||||
const orderEpoch = await contractWrappers.exchange.getOrderEpochAsync(
|
const orderEpoch = await contractWrappers.exchange.orderEpoch.callAsync(
|
||||||
makerAddress,
|
makerAddress,
|
||||||
contractWrappers.coordinator.address,
|
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 { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
|
||||||
import { FillScenarios } from '@0x/fill-scenarios';
|
import { FillScenarios } from '@0x/fill-scenarios';
|
||||||
import { assetDataUtils, orderHashUtils, signatureUtils } from '@0x/order-utils';
|
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 { BigNumber } from '@0x/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import { BlockParamLiteral } from 'ethereum-types';
|
import { BlockParamLiteral } from 'ethereum-types';
|
||||||
@ -10,8 +9,8 @@ import 'mocha';
|
|||||||
|
|
||||||
import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
|
import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
|
||||||
import { DecodedLogEvent } from '../src/types';
|
import { DecodedLogEvent } from '../src/types';
|
||||||
|
import { _getDefaultContractAddresses } from '../src/utils/contract_addresses';
|
||||||
|
|
||||||
import { UntransferrableDummyERC20Token } from './artifacts/UntransferrableDummyERC20Token';
|
|
||||||
import { chaiSetup } from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { migrateOnceAsync } from './utils/migrate';
|
import { migrateOnceAsync } from './utils/migrate';
|
||||||
@ -35,7 +34,6 @@ describe('ExchangeWrapper', () => {
|
|||||||
let takerAddress: string;
|
let takerAddress: string;
|
||||||
let makerAssetData: string;
|
let makerAssetData: string;
|
||||||
let takerAssetData: string;
|
let takerAssetData: string;
|
||||||
let txHash: string;
|
|
||||||
const fillableAmount = new BigNumber(5);
|
const fillableAmount = new BigNumber(5);
|
||||||
const takerTokenFillAmount = new BigNumber(5);
|
const takerTokenFillAmount = new BigNumber(5);
|
||||||
let signedOrder: SignedOrder;
|
let signedOrder: SignedOrder;
|
||||||
@ -52,7 +50,7 @@ describe('ExchangeWrapper', () => {
|
|||||||
contractWrappers = new ContractWrappers(provider, config);
|
contractWrappers = new ContractWrappers(provider, config);
|
||||||
exchangeContractAddress = contractWrappers.exchange.address;
|
exchangeContractAddress = contractWrappers.exchange.address;
|
||||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress;
|
zrxTokenAddress = contractAddresses.zrxToken;
|
||||||
fillScenarios = new FillScenarios(
|
fillScenarios = new FillScenarios(
|
||||||
provider,
|
provider,
|
||||||
userAddresses,
|
userAddresses,
|
||||||
@ -94,71 +92,71 @@ describe('ExchangeWrapper', () => {
|
|||||||
describe('fill order(s)', () => {
|
describe('fill order(s)', () => {
|
||||||
describe('#fillOrderAsync', () => {
|
describe('#fillOrderAsync', () => {
|
||||||
it('should fill a valid order', async () => {
|
it('should fill a valid order', async () => {
|
||||||
txHash = await contractWrappers.exchange.fillOrderAsync(
|
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
signedOrder,
|
signedOrder,
|
||||||
takerTokenFillAmount,
|
takerTokenFillAmount,
|
||||||
takerAddress,
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#fillOrderNoThrowAsync', () => {
|
describe('#fillOrderNoThrowAsync', () => {
|
||||||
it('should fill a valid order', async () => {
|
it('should fill a valid order', async () => {
|
||||||
txHash = await contractWrappers.exchange.fillOrderNoThrowAsync(
|
await contractWrappers.exchange.fillOrderNoThrow.awaitTransactionSuccessAsync(
|
||||||
signedOrder,
|
signedOrder,
|
||||||
takerTokenFillAmount,
|
takerTokenFillAmount,
|
||||||
takerAddress,
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
const orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||||
const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
|
||||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#fillOrKillOrderAsync', () => {
|
describe('#fillOrKillOrderAsync', () => {
|
||||||
it('should fill or kill a valid order', async () => {
|
it('should fill or kill a valid order', async () => {
|
||||||
txHash = await contractWrappers.exchange.fillOrKillOrderAsync(
|
await contractWrappers.exchange.fillOrKillOrder.awaitTransactionSuccessAsync(
|
||||||
signedOrder,
|
signedOrder,
|
||||||
takerTokenFillAmount,
|
takerTokenFillAmount,
|
||||||
takerAddress,
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#batchFillOrdersAsync', () => {
|
describe('#batchFillOrdersAsync', () => {
|
||||||
it('should fill a batch of valid orders', async () => {
|
it('should fill a batch of valid orders', async () => {
|
||||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||||
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
||||||
txHash = await contractWrappers.exchange.batchFillOrdersAsync(
|
await contractWrappers.exchange.batchFillOrders.awaitTransactionSuccessAsync(
|
||||||
signedOrders,
|
signedOrders,
|
||||||
takerAssetFillAmounts,
|
takerAssetFillAmounts,
|
||||||
takerAddress,
|
signedOrders.map(o => o.signature),
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#marketBuyOrdersAsync', () => {
|
describe('#marketBuyOrdersAsync', () => {
|
||||||
it('should maker buy', async () => {
|
it('should maker buy', async () => {
|
||||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||||
const makerAssetFillAmount = takerTokenFillAmount;
|
const makerAssetFillAmount = takerTokenFillAmount;
|
||||||
txHash = await contractWrappers.exchange.marketBuyOrdersAsync(
|
await contractWrappers.exchange.marketBuyOrders.awaitTransactionSuccessAsync(
|
||||||
signedOrders,
|
signedOrders,
|
||||||
makerAssetFillAmount,
|
makerAssetFillAmount,
|
||||||
takerAddress,
|
signedOrders.map(o => o.signature),
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#marketBuyOrdersNoThrowAsync', () => {
|
describe('#marketBuyOrdersNoThrowAsync', () => {
|
||||||
it('should no throw maker buy', async () => {
|
it('should no throw maker buy', async () => {
|
||||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||||
const makerAssetFillAmount = takerTokenFillAmount;
|
const makerAssetFillAmount = takerTokenFillAmount;
|
||||||
txHash = await contractWrappers.exchange.marketBuyOrdersNoThrowAsync(
|
await contractWrappers.exchange.marketBuyOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||||
signedOrders,
|
signedOrders,
|
||||||
makerAssetFillAmount,
|
makerAssetFillAmount,
|
||||||
takerAddress,
|
signedOrders.map(o => o.signature),
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
const orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||||
const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
|
||||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -166,25 +164,25 @@ describe('ExchangeWrapper', () => {
|
|||||||
it('should maker sell', async () => {
|
it('should maker sell', async () => {
|
||||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||||
const takerAssetFillAmount = takerTokenFillAmount;
|
const takerAssetFillAmount = takerTokenFillAmount;
|
||||||
txHash = await contractWrappers.exchange.marketSellOrdersAsync(
|
await contractWrappers.exchange.marketSellOrders.awaitTransactionSuccessAsync(
|
||||||
signedOrders,
|
signedOrders,
|
||||||
takerAssetFillAmount,
|
takerAssetFillAmount,
|
||||||
takerAddress,
|
signedOrders.map(o => o.signature),
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#marketSellOrdersNoThrowAsync', () => {
|
describe('#marketSellOrdersNoThrowAsync', () => {
|
||||||
it('should no throw maker sell', async () => {
|
it('should no throw maker sell', async () => {
|
||||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||||
const takerAssetFillAmount = takerTokenFillAmount;
|
const takerAssetFillAmount = takerTokenFillAmount;
|
||||||
txHash = await contractWrappers.exchange.marketSellOrdersNoThrowAsync(
|
await contractWrappers.exchange.marketSellOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||||
signedOrders,
|
signedOrders,
|
||||||
takerAssetFillAmount,
|
takerAssetFillAmount,
|
||||||
takerAddress,
|
signedOrders.map(o => o.signature),
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
const orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||||
const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
|
||||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -192,15 +190,15 @@ describe('ExchangeWrapper', () => {
|
|||||||
it('should fill a batch of valid orders', async () => {
|
it('should fill a batch of valid orders', async () => {
|
||||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||||
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
||||||
txHash = await contractWrappers.exchange.batchFillOrdersNoThrowAsync(
|
await contractWrappers.exchange.batchFillOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||||
signedOrders,
|
signedOrders,
|
||||||
takerAssetFillAmounts,
|
takerAssetFillAmounts,
|
||||||
takerAddress,
|
signedOrders.map(o => o.signature),
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
let orderInfo = await contractWrappers.exchange.getOrderInfo.callAsync(signedOrder);
|
||||||
let orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder);
|
|
||||||
expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled);
|
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);
|
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 () => {
|
it('should fill or kill a batch of valid orders', async () => {
|
||||||
const signedOrders = [signedOrder, anotherSignedOrder];
|
const signedOrders = [signedOrder, anotherSignedOrder];
|
||||||
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount];
|
||||||
txHash = await contractWrappers.exchange.batchFillOrKillOrdersAsync(
|
await contractWrappers.exchange.batchFillOrKillOrders.awaitTransactionSuccessAsync(
|
||||||
signedOrders,
|
signedOrders,
|
||||||
takerAssetFillAmounts,
|
takerAssetFillAmounts,
|
||||||
takerAddress,
|
signedOrders.map(o => o.signature),
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#matchOrdersAsync', () => {
|
describe('#matchOrdersAsync', () => {
|
||||||
@ -225,35 +223,39 @@ describe('ExchangeWrapper', () => {
|
|||||||
takerAddress,
|
takerAddress,
|
||||||
fillableAmount,
|
fillableAmount,
|
||||||
);
|
);
|
||||||
txHash = await contractWrappers.exchange.matchOrdersAsync(
|
await contractWrappers.exchange.matchOrders.awaitTransactionSuccessAsync(
|
||||||
signedOrder,
|
signedOrder,
|
||||||
matchingSignedOrder,
|
matchingSignedOrder,
|
||||||
takerAddress,
|
signedOrder.signature,
|
||||||
|
matchingSignedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('cancel order(s)', () => {
|
describe('cancel order(s)', () => {
|
||||||
describe('#cancelOrderAsync', () => {
|
describe('#cancelOrderAsync', () => {
|
||||||
it('should cancel a valid order', async () => {
|
it('should cancel a valid order', async () => {
|
||||||
txHash = await contractWrappers.exchange.cancelOrderAsync(signedOrder);
|
await contractWrappers.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrder, {
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
from: makerAddress,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#batchCancelOrdersAsync', () => {
|
describe('#batchCancelOrdersAsync', () => {
|
||||||
it('should cancel a batch of valid orders', async () => {
|
it('should cancel a batch of valid orders', async () => {
|
||||||
const orders = [signedOrder, anotherSignedOrder];
|
const orders = [signedOrder, anotherSignedOrder];
|
||||||
txHash = await contractWrappers.exchange.batchCancelOrdersAsync(orders);
|
await contractWrappers.exchange.batchCancelOrders.awaitTransactionSuccessAsync(orders, {
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
from: makerAddress,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#cancelOrdersUpTo/getOrderEpochAsync', () => {
|
describe('#cancelOrdersUpTo/getOrderEpochAsync', () => {
|
||||||
it('should cancel orders up to target order epoch', async () => {
|
it('should cancel orders up to target order epoch', async () => {
|
||||||
const targetOrderEpoch = new BigNumber(42);
|
const targetOrderEpoch = new BigNumber(42);
|
||||||
txHash = await contractWrappers.exchange.cancelOrdersUpToAsync(targetOrderEpoch, makerAddress);
|
await contractWrappers.exchange.cancelOrdersUpTo.awaitTransactionSuccessAsync(targetOrderEpoch, {
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
from: makerAddress,
|
||||||
const orderEpoch = await contractWrappers.exchange.getOrderEpochAsync(
|
});
|
||||||
|
const orderEpoch = await contractWrappers.exchange.orderEpoch.callAsync(
|
||||||
makerAddress,
|
makerAddress,
|
||||||
constants.NULL_ADDRESS,
|
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', () => {
|
describe('#getOrderInfoAsync', () => {
|
||||||
it('should get the order info', async () => {
|
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);
|
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||||
expect(orderInfo.orderHash).to.be.equal(orderHash);
|
expect(orderInfo.orderHash).to.be.equal(orderHash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getOrdersInfoAsync', () => {
|
describe('#getOrdersInfoAsync', () => {
|
||||||
it('should get the orders info', async () => {
|
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);
|
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||||
expect(ordersInfo[0].orderHash).to.be.equal(orderHash);
|
expect(ordersInfo[0].orderHash).to.be.equal(orderHash);
|
||||||
const anotherOrderHash = orderHashUtils.getOrderHashHex(anotherSignedOrder);
|
const anotherOrderHash = orderHashUtils.getOrderHashHex(anotherSignedOrder);
|
||||||
expect(ordersInfo[1].orderHash).to.be.equal(anotherOrderHash);
|
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', () => {
|
describe('#isValidSignature', () => {
|
||||||
it('should check if the signature is valid', async () => {
|
it('should check if the signature is valid', async () => {
|
||||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||||
let isValid = await contractWrappers.exchange.isValidSignatureAsync(
|
let isValid = await contractWrappers.exchange.isValidSignature.callAsync(
|
||||||
orderHash,
|
orderHash,
|
||||||
signedOrder.makerAddress,
|
signedOrder.makerAddress,
|
||||||
signedOrder.signature,
|
signedOrder.signature,
|
||||||
);
|
);
|
||||||
expect(isValid).to.be.true();
|
expect(isValid).to.be.true();
|
||||||
isValid = await contractWrappers.exchange.isValidSignatureAsync(
|
isValid = await contractWrappers.exchange.isValidSignature.callAsync(
|
||||||
orderHash,
|
orderHash,
|
||||||
signedOrder.takerAddress,
|
signedOrder.takerAddress,
|
||||||
signedOrder.signature,
|
signedOrder.signature,
|
||||||
@ -404,7 +303,10 @@ describe('ExchangeWrapper', () => {
|
|||||||
it('should check if the validator is allowed', async () => {
|
it('should check if the validator is allowed', async () => {
|
||||||
const signerAddress = makerAddress;
|
const signerAddress = makerAddress;
|
||||||
const validatorAddress = constants.NULL_ADDRESS;
|
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();
|
expect(isAllowed).to.be.false();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -413,52 +315,50 @@ describe('ExchangeWrapper', () => {
|
|||||||
const validatorAddress = constants.NULL_ADDRESS;
|
const validatorAddress = constants.NULL_ADDRESS;
|
||||||
const isApproved = true;
|
const isApproved = true;
|
||||||
const senderAddress = makerAddress;
|
const senderAddress = makerAddress;
|
||||||
txHash = await contractWrappers.exchange.setSignatureValidatorApprovalAsync(
|
await contractWrappers.exchange.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
|
||||||
validatorAddress,
|
validatorAddress,
|
||||||
isApproved,
|
isApproved,
|
||||||
senderAddress,
|
{ from: senderAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#isTransactionExecutedAsync', () => {
|
describe('#isTransactionExecutedAsync', () => {
|
||||||
it('should check if the transaction is executed', async () => {
|
it('should check if the transaction is executed', async () => {
|
||||||
const transactionHash = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
const transactionHash = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
||||||
const isExecuted = await contractWrappers.exchange.isTransactionExecutedAsync(transactionHash);
|
const isExecuted = await contractWrappers.exchange.transactions.callAsync(transactionHash);
|
||||||
expect(isExecuted).to.be.false();
|
expect(isExecuted).to.be.false();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getAssetProxyBySignatureAsync', () => {
|
describe('#getAssetProxyBySignatureAsync', () => {
|
||||||
it('should fill or kill a valid order', async () => {
|
it('should fill or kill a valid order', async () => {
|
||||||
const erc20ProxyId = await contractWrappers.erc20Proxy.getProxyIdAsync();
|
const erc20ProxyId = await contractWrappers.erc20Proxy.getProxyId.callAsync();
|
||||||
const erc20ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc20ProxyId);
|
const erc20ProxyAddressById = await contractWrappers.exchange.getAssetProxy.callAsync(erc20ProxyId);
|
||||||
const erc20ProxyAddress = contractWrappers.erc20Proxy.address;
|
const erc20ProxyAddress = contractWrappers.erc20Proxy.address;
|
||||||
expect(erc20ProxyAddressById).to.be.equal(erc20ProxyAddress);
|
expect(erc20ProxyAddressById).to.be.equal(erc20ProxyAddress);
|
||||||
const erc721ProxyId = await contractWrappers.erc721Proxy.getProxyIdAsync();
|
const erc721ProxyId = await contractWrappers.erc721Proxy.getProxyId.callAsync();
|
||||||
const erc721ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc721ProxyId);
|
const erc721ProxyAddressById = await contractWrappers.exchange.getAssetProxy.callAsync(erc721ProxyId);
|
||||||
const erc721ProxyAddress = contractWrappers.erc721Proxy.address;
|
const erc721ProxyAddress = contractWrappers.erc721Proxy.address;
|
||||||
expect(erc721ProxyAddressById).to.be.equal(erc721ProxyAddress);
|
expect(erc721ProxyAddressById).to.be.equal(erc721ProxyAddress);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#preSignAsync/isPreSignedAsync', () => {
|
describe('#preSign/isPresigned', () => {
|
||||||
it('should preSign the hash', async () => {
|
it('should preSign the hash', async () => {
|
||||||
const senderAddress = takerAddress;
|
const senderAddress = takerAddress;
|
||||||
const hash = orderHashUtils.getOrderHashHex(signedOrder);
|
const hash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||||
const signerAddress = signedOrder.makerAddress;
|
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();
|
expect(isPreSigned).to.be.false();
|
||||||
txHash = await contractWrappers.exchange.preSignAsync(
|
await contractWrappers.exchange.preSign.awaitTransactionSuccessAsync(
|
||||||
hash,
|
hash,
|
||||||
signerAddress,
|
signerAddress,
|
||||||
signedOrder.signature,
|
signedOrder.signature,
|
||||||
senderAddress,
|
{ from: senderAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
isPreSigned = await contractWrappers.exchange.preSigned.callAsync(hash, signerAddress);
|
||||||
isPreSigned = await contractWrappers.exchange.isPreSignedAsync(hash, signerAddress);
|
|
||||||
expect(isPreSigned).to.be.true();
|
expect(isPreSigned).to.be.true();
|
||||||
|
|
||||||
const preSignedSignature = '0x06';
|
const preSignedSignature = '0x06';
|
||||||
const isValidSignature = await contractWrappers.exchange.isValidSignatureAsync(
|
const isValidSignature = await contractWrappers.exchange.isValidSignature.callAsync(
|
||||||
hash,
|
hash,
|
||||||
signerAddress,
|
signerAddress,
|
||||||
preSignedSignature,
|
preSignedSignature,
|
||||||
@ -477,7 +377,7 @@ describe('ExchangeWrapper', () => {
|
|||||||
});
|
});
|
||||||
describe('#getVersionAsync', () => {
|
describe('#getVersionAsync', () => {
|
||||||
it('should return version the hash', async () => {
|
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';
|
const VERSION = '2.0.0';
|
||||||
expect(version).to.be.equal(VERSION);
|
expect(version).to.be.equal(VERSION);
|
||||||
});
|
});
|
||||||
@ -510,10 +410,11 @@ describe('ExchangeWrapper', () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback);
|
contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback);
|
||||||
await contractWrappers.exchange.fillOrderAsync(
|
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
signedOrder,
|
signedOrder,
|
||||||
takerTokenFillAmountInBaseUnits,
|
takerTokenFillAmountInBaseUnits,
|
||||||
takerAddress,
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
@ -525,7 +426,9 @@ describe('ExchangeWrapper', () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
contractWrappers.exchange.subscribe(ExchangeEvents.Cancel, indexFilterValues, callback);
|
contractWrappers.exchange.subscribe(ExchangeEvents.Cancel, indexFilterValues, callback);
|
||||||
await contractWrappers.exchange.cancelOrderAsync(signedOrder);
|
await contractWrappers.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrder, {
|
||||||
|
from: makerAddress,
|
||||||
|
});
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => {
|
it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => {
|
||||||
@ -545,10 +448,11 @@ describe('ExchangeWrapper', () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback);
|
contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback);
|
||||||
await contractWrappers.exchange.fillOrderAsync(
|
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
signedOrder,
|
signedOrder,
|
||||||
takerTokenFillAmountInBaseUnits,
|
takerTokenFillAmountInBaseUnits,
|
||||||
takerAddress,
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
@ -565,10 +469,11 @@ describe('ExchangeWrapper', () => {
|
|||||||
callbackNeverToBeCalled,
|
callbackNeverToBeCalled,
|
||||||
);
|
);
|
||||||
contractWrappers.exchange.unsubscribe(subscriptionToken);
|
contractWrappers.exchange.unsubscribe(subscriptionToken);
|
||||||
await contractWrappers.exchange.fillOrderAsync(
|
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
signedOrder,
|
signedOrder,
|
||||||
takerTokenFillAmountInBaseUnits,
|
takerTokenFillAmountInBaseUnits,
|
||||||
takerAddress,
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
done();
|
done();
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
@ -580,7 +485,12 @@ describe('ExchangeWrapper', () => {
|
|||||||
toBlock: BlockParamLiteral.Latest,
|
toBlock: BlockParamLiteral.Latest,
|
||||||
};
|
};
|
||||||
it('should get logs with decoded args emitted by Fill', async () => {
|
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 eventName = ExchangeEvents.Fill;
|
||||||
const indexFilterValues = {};
|
const indexFilterValues = {};
|
||||||
const logs = await contractWrappers.exchange.getLogsAsync(eventName, blockRange, indexFilterValues);
|
const logs = await contractWrappers.exchange.getLogsAsync(eventName, blockRange, indexFilterValues);
|
||||||
@ -588,8 +498,12 @@ describe('ExchangeWrapper', () => {
|
|||||||
expect(logs[0].event).to.be.equal(eventName);
|
expect(logs[0].event).to.be.equal(eventName);
|
||||||
});
|
});
|
||||||
it('should only get the logs with the correct event name', async () => {
|
it('should only get the logs with the correct event name', async () => {
|
||||||
txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
signedOrder,
|
||||||
|
takerTokenFillAmount,
|
||||||
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
|
);
|
||||||
const differentEventName = ExchangeEvents.Cancel;
|
const differentEventName = ExchangeEvents.Cancel;
|
||||||
const indexFilterValues = {};
|
const indexFilterValues = {};
|
||||||
const logs = await contractWrappers.exchange.getLogsAsync(
|
const logs = await contractWrappers.exchange.getLogsAsync(
|
||||||
@ -600,8 +514,12 @@ describe('ExchangeWrapper', () => {
|
|||||||
expect(logs).to.have.length(0);
|
expect(logs).to.have.length(0);
|
||||||
});
|
});
|
||||||
it('should only get the logs with the correct indexed fields', async () => {
|
it('should only get the logs with the correct indexed fields', async () => {
|
||||||
txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
signedOrder,
|
||||||
|
takerTokenFillAmount,
|
||||||
|
signedOrder.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
|
);
|
||||||
const signedOrderWithAnotherMakerAddress = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrderWithAnotherMakerAddress = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerAssetData,
|
makerAssetData,
|
||||||
takerAssetData,
|
takerAssetData,
|
||||||
@ -609,13 +527,12 @@ describe('ExchangeWrapper', () => {
|
|||||||
takerAddress,
|
takerAddress,
|
||||||
fillableAmount,
|
fillableAmount,
|
||||||
);
|
);
|
||||||
txHash = await contractWrappers.exchange.fillOrderAsync(
|
await contractWrappers.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
signedOrderWithAnotherMakerAddress,
|
signedOrderWithAnotherMakerAddress,
|
||||||
takerTokenFillAmount,
|
takerTokenFillAmount,
|
||||||
takerAddress,
|
signedOrderWithAnotherMakerAddress.signature,
|
||||||
|
{ from: takerAddress },
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
|
||||||
|
|
||||||
const eventName = ExchangeEvents.Fill;
|
const eventName = ExchangeEvents.Fill;
|
||||||
const indexFilterValues = {
|
const indexFilterValues = {
|
||||||
makerAddress: anotherMakerAddress,
|
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