Merge development
This commit is contained in:
commit
2f2582a0da
@ -56,6 +56,16 @@ jobs:
|
||||
# HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
|
||||
# initialized
|
||||
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test contracts
|
||||
test-publish:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
- image: verdaccio/verdaccio
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn test:publish:circleci
|
||||
test-rest:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
@ -80,6 +90,7 @@ jobs:
|
||||
- run: yarn wsrun test:circleci @0xproject/sra-report
|
||||
- run: yarn wsrun test:circleci @0xproject/subproviders
|
||||
- run: yarn wsrun test:circleci @0xproject/web3-wrapper
|
||||
- run: yarn wsrun test:circleci @0xproject/utils
|
||||
- save_cache:
|
||||
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
@ -231,6 +242,9 @@ workflows:
|
||||
- static-tests:
|
||||
requires:
|
||||
- build
|
||||
- test-publish:
|
||||
requires:
|
||||
- build
|
||||
- submit-coverage:
|
||||
requires:
|
||||
- test-rest
|
||||
|
@ -15,6 +15,7 @@ lib
|
||||
/packages/contract-wrappers/src/artifacts
|
||||
/packages/order-watcher/src/artifacts
|
||||
/packages/metacoin/artifacts
|
||||
/packages/sra-api/public/
|
||||
/packages/contract-wrappers/test/artifacts
|
||||
/packages/order-watcher/test/artifacts
|
||||
/packages/migrations/artifacts/1.0.0
|
||||
|
@ -20,8 +20,8 @@
|
||||
|
||||
<!--- The following points should be used to indicate the progress of your PR. Put an `x` in all the boxes that apply right now, and come back over time and check them off as you make progress. If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
|
||||
* [ ] Prefixed the title of this PR with `[WIP]` if it is a work in progress.
|
||||
* [ ] Prefixed the title of this PR with bracketed package name(s) corresponding to the changed package(s). For example: `[sol-cov] Fixed bug`.
|
||||
* [ ] Added tests to cover my changes, or decided that tests would be too impractical.
|
||||
* [ ] Updated documentation, or decided that no doc change is needed.
|
||||
* [ ] Added new entries to the relevant CHANGELOG.jsons.
|
||||
* [ ] Prefix PR title with `[WIP]` if necessary.
|
||||
* [ ] Prefix PR title with bracketed package name(s) corresponding to the changed package(s). For example: `[sol-cov] Fixed bug`.
|
||||
* [ ] Add tests to cover changes as needed.
|
||||
* [ ] Update documentation as needed.
|
||||
* [ ] Add new entries to the relevant CHANGELOG.jsons.
|
||||
|
@ -14,6 +14,8 @@
|
||||
"report_coverage": "lcov-result-merger 'packages/*/coverage/lcov.info' | coveralls",
|
||||
"test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js",
|
||||
"test:installation:local": "IS_LOCAL_PUBLISH=true node ./packages/monorepo-scripts/lib/test_installation.js",
|
||||
"test:publish:circleci:comment": "HACK(albrow) We need an automated way to login to npm and echo+sleep piped to stdin was the only way I could find to do it.",
|
||||
"test:publish:circleci": "{ echo \"test\"; sleep 1; echo \"test\"; sleep 1; echo \"test@example.com\"; } | npm login --registry=http://localhost:4873 && IS_LOCAL_PUBLISH=true run-s script:publish test:installation:local",
|
||||
"run:publish": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild:no_website script:publish",
|
||||
"run:publish:local": "IS_LOCAL_PUBLISH=true yarn run:publish",
|
||||
"script:prepublish_checks": "node ./packages/monorepo-scripts/lib/prepublish_checks.js",
|
||||
|
@ -1,4 +1,17 @@
|
||||
[
|
||||
{
|
||||
"version": "1.0.1-rc.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
},
|
||||
{
|
||||
"pr": 914,
|
||||
"note": "Update ecSignOrderHashAsync to return the signature as a string for immediate use in contracts"
|
||||
}
|
||||
],
|
||||
"timestamp": 1534210131
|
||||
},
|
||||
{
|
||||
"version": "1.0.1-rc.2",
|
||||
"changes": [
|
||||
|
@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.1-rc.3 - _August 13, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
* Update ecSignOrderHashAsync to return the signature as a string for immediate use in contracts (#914)
|
||||
|
||||
## v1.0.1-rc.2 - _July 26, 2018_
|
||||
|
||||
* Fixed bug caused by importing non-existent dep
|
||||
@ -17,11 +22,11 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0-rc.2 - _July 20, 2018_
|
||||
## v1.0.0-rc.2 - _July 19, 2018_
|
||||
|
||||
* Remove `zeroEx.assetData` and instead re-export it's static functions directly off `ZeroEx`
|
||||
|
||||
## v1.0.0-rc.1 - _July 20, 2018_
|
||||
## v1.0.0-rc.1 - _July 19, 2018_
|
||||
|
||||
* Remove tokenRegistry wrapper (#863)
|
||||
* Rename `zeroEx.token` to `zeroEx.erc20Token`, and add `zeroEx.erc721Token` (#863)
|
||||
@ -61,7 +66,7 @@ CHANGELOG
|
||||
* Renamed createOrderStateWatcher to createOrderWatcherAsync since it is now async (#579)
|
||||
* Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage (#579)
|
||||
|
||||
## v0.37.2 - _May 5, 2018_
|
||||
## v0.37.2 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "0x.js",
|
||||
"version": "1.0.1-rc.2",
|
||||
"version": "1.0.1-rc.3",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -50,9 +50,11 @@
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@0xproject/dev-utils": "^1.0.3",
|
||||
"@0xproject/migrations": "^1.0.3",
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/abi-gen": "^1.0.5",
|
||||
"@0xproject/dev-utils": "^1.0.4",
|
||||
"@0xproject/migrations": "^1.0.4",
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/node": "^8.0.53",
|
||||
@ -65,7 +67,7 @@
|
||||
"dirty-chai": "^2.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"opn-cli": "^3.1.0",
|
||||
@ -74,23 +76,23 @@
|
||||
"source-map-support": "^0.5.0",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.7.1",
|
||||
"typescript": "2.9.2",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^1.0.4",
|
||||
"@0xproject/base-contract": "^1.0.4",
|
||||
"@0xproject/contract-wrappers": "^1.0.1-rc.2",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.2",
|
||||
"@0xproject/sol-compiler": "^1.0.4",
|
||||
"@0xproject/subproviders": "^1.0.4",
|
||||
"@0xproject/types": "^1.0.1-rc.3",
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/web3-wrapper": "^1.1.2",
|
||||
"ethereum-types": "^1.0.3",
|
||||
"@0xproject/assert": "^1.0.5",
|
||||
"@0xproject/base-contract": "^2.0.0-rc.1",
|
||||
"@0xproject/contract-wrappers": "^1.0.1-rc.3",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.3",
|
||||
"@0xproject/sol-compiler": "^1.0.5",
|
||||
"@0xproject/subproviders": "^1.0.5",
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"@0xproject/web3-wrapper": "^1.2.0",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"ethers": "3.0.22",
|
||||
"lodash": "^4.17.4"
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -9,17 +9,11 @@ import {
|
||||
EtherTokenWrapper,
|
||||
ExchangeWrapper,
|
||||
} from '@0xproject/contract-wrappers';
|
||||
import {
|
||||
assetDataUtils,
|
||||
generatePseudoRandomSalt,
|
||||
signatureUtils,
|
||||
MessagePrefixOpts,
|
||||
orderHashUtils,
|
||||
} from '@0xproject/order-utils';
|
||||
import { assetDataUtils, generatePseudoRandomSalt, signatureUtils, orderHashUtils } from '@0xproject/order-utils';
|
||||
// HACK: Since we export assetDataUtils from ZeroEx and it has AssetProxyId, ERC20AssetData and ERC721AssetData
|
||||
// in it's public interface, we need to import these types here.
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import { AssetProxyId, ECSignature, ERC20AssetData, ERC721AssetData, Order, SignedOrder } from '@0xproject/types';
|
||||
import { AssetProxyId, ERC20AssetData, ERC721AssetData, Order, SignedOrder, SignerType } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
@ -237,19 +231,21 @@ export class ZeroEx {
|
||||
* @param orderHash Hex encoded orderHash to sign.
|
||||
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
|
||||
* must be available via the Provider supplied to 0x.js.
|
||||
* @param messagePrefixOpts Options regarding the desired prefix and whether to add it before calling `eth_sign`
|
||||
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
|
||||
* @param signerType the signer type that will perform the `eth_sign` operation. E.g Default, Metamask, Ledger or Trezor.
|
||||
* Some implementations exhibit different behaviour. Default will assume a spec compliant eth_sign implementation.
|
||||
* This parameter is defaulted to `SignerType.Default`.
|
||||
* @return A hex encoded string of the Elliptic curve signature parameters generated by signing the orderHash and signature type.
|
||||
*/
|
||||
public async ecSignOrderHashAsync(
|
||||
orderHash: string,
|
||||
signerAddress: string,
|
||||
messagePrefixOpts: MessagePrefixOpts,
|
||||
): Promise<ECSignature> {
|
||||
signerType: SignerType = SignerType.Default,
|
||||
): Promise<string> {
|
||||
const signature = await signatureUtils.ecSignOrderHashAsync(
|
||||
this._contractWrappers.getProvider(),
|
||||
orderHash,
|
||||
signerAddress,
|
||||
messagePrefixOpts,
|
||||
signerType,
|
||||
);
|
||||
return signature;
|
||||
}
|
||||
|
@ -48,8 +48,6 @@ export {
|
||||
OrderInfo,
|
||||
} from '@0xproject/contract-wrappers';
|
||||
|
||||
export { MessagePrefixType, MessagePrefixOpts } from '@0xproject/order-utils';
|
||||
|
||||
export {
|
||||
ExchangeContractErrs,
|
||||
Order,
|
||||
|
@ -48,10 +48,11 @@ describe('ZeroEx library', () => {
|
||||
const ethSignSignature =
|
||||
'0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
|
||||
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
||||
it("should return false if the data doesn't pertain to the signature & address", async () => {
|
||||
return expect((zeroEx.exchange as any).isValidSignatureAsync('0x0', address, ethSignSignature)).to.become(
|
||||
false,
|
||||
);
|
||||
return expect(
|
||||
(zeroEx.exchange as any).isValidSignatureAsync(bytes32Zeros, address, ethSignSignature),
|
||||
).to.become(false);
|
||||
});
|
||||
it("should return false if the address doesn't pertain to the signature & data", async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1534210131,
|
||||
"version": "1.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1532619515,
|
||||
"version": "1.0.4",
|
||||
|
@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.5 - _August 13, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.4 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -21,7 +25,7 @@ CHANGELOG
|
||||
|
||||
* Fix the abi-gen entry point in package.json (#901)
|
||||
|
||||
## v1.0.0 - _July 20, 2018_
|
||||
## v1.0.0 - _July 19, 2018_
|
||||
|
||||
* Convert e_r_c to erc in generated file names (#822)
|
||||
* Remove the output directory before writing to it (#822)
|
||||
@ -39,7 +43,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.3.1 - _June 1, 2018_
|
||||
## v0.3.1 - _May 31, 2018_
|
||||
|
||||
* Incorrect publish that was unpublished
|
||||
|
||||
@ -47,7 +51,7 @@ CHANGELOG
|
||||
|
||||
* Properly export the executable binary (#588)
|
||||
|
||||
## v0.2.13 - _May 5, 2018_
|
||||
## v0.2.13 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/abi-gen",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -31,13 +31,13 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
||||
"dependencies": {
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"chalk": "^2.3.0",
|
||||
"ethereum-types": "^1.0.3",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"glob": "^7.1.2",
|
||||
"handlebars": "^4.0.11",
|
||||
"lodash": "^4.17.4",
|
||||
"lodash": "^4.17.5",
|
||||
"mkdirp": "^0.5.1",
|
||||
"sleep": "^5.1.1",
|
||||
"tmp": "^0.0.33",
|
||||
@ -45,7 +45,7 @@
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/glob": "5.0.35",
|
||||
"@types/handlebars": "^4.0.36",
|
||||
"@types/mkdirp": "^0.5.1",
|
||||
@ -61,7 +61,7 @@
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1534210131,
|
||||
"version": "1.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1532619515,
|
||||
"version": "1.0.4",
|
||||
|
@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.5 - _August 13, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.4 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -21,7 +25,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0 - _July 20, 2018_
|
||||
## v1.0.0 - _July 19, 2018_
|
||||
|
||||
* Fix bug in string enum assertion. We erroneously were checking against the enum keys, not values (#821)
|
||||
|
||||
@ -37,7 +41,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.11 - _June 1, 2018_
|
||||
## v0.2.11 - _May 31, 2018_
|
||||
|
||||
* Incorrect publish that was unpublished
|
||||
|
||||
@ -45,7 +49,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.9 - _May 5, 2018_
|
||||
## v0.2.9 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/assert",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -29,7 +29,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/valid-url": "^1.0.2",
|
||||
@ -37,18 +37,18 @@
|
||||
"copyfiles": "^1.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/json-schemas": "^1.0.1-rc.3",
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"lodash": "^4.17.4",
|
||||
"@0xproject/json-schemas": "^1.0.1-rc.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"lodash": "^4.17.5",
|
||||
"valid-url": "^1.0.9"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -1,4 +1,14 @@
|
||||
[
|
||||
{
|
||||
"version": "2.0.0-rc.1",
|
||||
"changes": [
|
||||
{
|
||||
"pr": 915,
|
||||
"note": "Added strict encoding/decoding checks for sendTransaction and call"
|
||||
}
|
||||
],
|
||||
"timestamp": 1534210131
|
||||
},
|
||||
{
|
||||
"timestamp": 1532619515,
|
||||
"version": "1.0.4",
|
||||
|
@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.0.0-rc.1 - _August 13, 2018_
|
||||
|
||||
* Added strict encoding/decoding checks for sendTransaction and call (#915)
|
||||
|
||||
## v1.0.4 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -21,7 +25,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0 - _July 20, 2018_
|
||||
## v1.0.0 - _July 19, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@ -37,7 +41,7 @@ CHANGELOG
|
||||
|
||||
* Update EthersJs to fix the `value.toLowerCase()` is not a function bug caused by `ethers.js` breaking patch version https://github.com/ethers-io/ethers.js/issues/201
|
||||
|
||||
## v0.3.3 - _June 1, 2018_
|
||||
## v0.3.3 - _May 31, 2018_
|
||||
|
||||
* Incorrect publish that was unpublished
|
||||
|
||||
@ -45,7 +49,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.3.1 - _May 5, 2018_
|
||||
## v0.3.1 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/base-contract",
|
||||
"version": "1.0.4",
|
||||
"version": "2.0.0-rc.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -29,24 +29,24 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/web3-wrapper": "^1.1.2",
|
||||
"ethereum-types": "^1.0.3",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"@0xproject/web3-wrapper": "^1.2.0",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"ethers": "3.0.22",
|
||||
"lodash": "^4.17.4"
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -82,6 +82,27 @@ export class BaseContract {
|
||||
}
|
||||
return txDataWithDefaults;
|
||||
}
|
||||
// Throws if the given arguments cannot be safely/correctly encoded based on
|
||||
// the given inputAbi. An argument may not be considered safely encodeable
|
||||
// if it overflows the corresponding Solidity type, there is a bug in the
|
||||
// encoder, or the encoder performs unsafe type coercion.
|
||||
public static strictArgumentEncodingCheck(inputAbi: DataItem[], args: any[]): void {
|
||||
const coder = ethers.utils.AbiCoder.defaultCoder;
|
||||
const params = abiUtils.parseEthersParams(inputAbi);
|
||||
const rawEncoded = coder.encode(params.names, params.types, args);
|
||||
const rawDecoded = coder.decode(params.names, params.types, rawEncoded);
|
||||
for (let i = 0; i < rawDecoded.length; i++) {
|
||||
const original = args[i];
|
||||
const decoded = rawDecoded[i];
|
||||
if (!abiUtils.isAbiDataEqual(params.names[i], params.types[i], original, decoded)) {
|
||||
throw new Error(
|
||||
`Cannot safely encode argument: ${params.names[i]} (${original}) of type ${
|
||||
params.types[i]
|
||||
}. (Possible type overflow or other encoding error)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected _lookupEthersInterface(functionSignature: string): ethers.Interface {
|
||||
const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature];
|
||||
if (_.isUndefined(ethersInterface)) {
|
||||
|
114
packages/base-contract/test/base_contract_test.ts
Normal file
114
packages/base-contract/test/base_contract_test.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { BaseContract } from '../src';
|
||||
|
||||
const { expect } = chai;
|
||||
|
||||
describe('BaseContract', () => {
|
||||
describe('strictArgumentEncodingCheck', () => {
|
||||
it('works for simple types', () => {
|
||||
BaseContract.strictArgumentEncodingCheck(
|
||||
[{ name: 'to', type: 'address' }],
|
||||
['0xe834ec434daba538cd1b9fe1582052b880bd7e63'],
|
||||
);
|
||||
});
|
||||
it('works for array types', () => {
|
||||
const inputAbi = [
|
||||
{
|
||||
name: 'takerAssetFillAmounts',
|
||||
type: 'uint256[]',
|
||||
},
|
||||
];
|
||||
const args = [
|
||||
['9000000000000000000', '79000000000000000000', '979000000000000000000', '7979000000000000000000'],
|
||||
];
|
||||
BaseContract.strictArgumentEncodingCheck(inputAbi, args);
|
||||
});
|
||||
it('works for tuple/struct types', () => {
|
||||
const inputAbi = [
|
||||
{
|
||||
components: [
|
||||
{
|
||||
name: 'makerAddress',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'takerAddress',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'feeRecipientAddress',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'senderAddress',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'makerAssetAmount',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'takerAssetAmount',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'makerFee',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'takerFee',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'expirationTimeSeconds',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'salt',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'makerAssetData',
|
||||
type: 'bytes',
|
||||
},
|
||||
{
|
||||
name: 'takerAssetData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
name: 'order',
|
||||
type: 'tuple',
|
||||
},
|
||||
];
|
||||
const args = [
|
||||
{
|
||||
makerAddress: '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb',
|
||||
takerAddress: '0x0000000000000000000000000000000000000000',
|
||||
feeRecipientAddress: '0xe834ec434daba538cd1b9fe1582052b880bd7e63',
|
||||
senderAddress: '0x0000000000000000000000000000000000000000',
|
||||
makerAssetAmount: '0',
|
||||
takerAssetAmount: '200000000000000000000',
|
||||
makerFee: '1000000000000000000',
|
||||
takerFee: '1000000000000000000',
|
||||
expirationTimeSeconds: '1532563026',
|
||||
salt: '59342956082154660870994022243365949771115859664887449740907298019908621891376',
|
||||
makerAssetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
takerAssetData: '0xf47261b00000000000000000000000001d7022f5b17d2f8b695918fb48fa1089c9f85401',
|
||||
},
|
||||
];
|
||||
BaseContract.strictArgumentEncodingCheck(inputAbi, args);
|
||||
});
|
||||
it('throws for integer overflows', () => {
|
||||
expect(() =>
|
||||
BaseContract.strictArgumentEncodingCheck([{ name: 'amount', type: 'uint8' }], ['256']),
|
||||
).to.throw();
|
||||
});
|
||||
it('throws for fixed byte array overflows', () => {
|
||||
expect(() =>
|
||||
BaseContract.strictArgumentEncodingCheck([{ name: 'hash', type: 'bytes8' }], ['0x001122334455667788']),
|
||||
).to.throw();
|
||||
});
|
||||
});
|
||||
});
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1534210131,
|
||||
"version": "1.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1532619515,
|
||||
"version": "1.0.4",
|
||||
|
@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.5 - _August 13, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.4 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -21,7 +25,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0 - _July 20, 2018_
|
||||
## v1.0.0 - _July 19, 2018_
|
||||
|
||||
* Remove `WebSocketOrderbookChannel` from the public interface and replace with `orderbookChannelFactory`
|
||||
|
||||
@ -45,7 +49,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.6.12 - _May 5, 2018_
|
||||
## v0.6.12 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/connect",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -48,15 +48,15 @@
|
||||
"@0xproject/assert": "^0.2.14",
|
||||
"@0xproject/json-schemas": "^0.8.3",
|
||||
"@0xproject/types": "^0.8.2",
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"lodash": "^4.17.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"lodash": "^4.17.5",
|
||||
"query-string": "^5.0.1",
|
||||
"sinon": "^4.0.0",
|
||||
"websocket": "^1.0.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/fetch-mock": "^5.12.2",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
@ -70,13 +70,13 @@
|
||||
"dirty-chai": "^2.0.1",
|
||||
"fetch-mock": "^5.13.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"version": "1.0.1-rc.3",
|
||||
"version": "1.0.1-rc.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Export missing ExchangeSignatureValidatorApprovalEventArgs type",
|
||||
@ -8,6 +8,24 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.1-rc.3",
|
||||
"changes": [
|
||||
{
|
||||
"pr": 915,
|
||||
"note": "Added strict encoding/decoding checks for sendTransaction and call"
|
||||
},
|
||||
{
|
||||
"note": "Add ForwarderWrapper",
|
||||
"pr": 934
|
||||
},
|
||||
{
|
||||
"note": "Optimize orders in ForwarderWrapper",
|
||||
"pr": 936
|
||||
}
|
||||
],
|
||||
"timestamp": 1534210131
|
||||
},
|
||||
{
|
||||
"version": "1.0.1-rc.2",
|
||||
"changes": [
|
||||
|
@ -5,6 +5,12 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.1-rc.3 - _August 13, 2018_
|
||||
|
||||
* Added strict encoding/decoding checks for sendTransaction and call (#915)
|
||||
* Add ForwarderWrapper (#934)
|
||||
* Optimize orders in ForwarderWrapper (#936)
|
||||
|
||||
## v1.0.1-rc.2 - _July 26, 2018_
|
||||
|
||||
* Fixed bug caused by importing non-existent dep
|
||||
@ -17,7 +23,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0-rc.1 - _July 20, 2018_
|
||||
## v1.0.0-rc.1 - _July 19, 2018_
|
||||
|
||||
* Update blockstream to v5.0 and propogate up caught errors to active subscriptions (#815)
|
||||
* Update to v2 of 0x rpotocol (#822)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/contract-wrappers",
|
||||
"version": "1.0.1-rc.2",
|
||||
"version": "1.0.1-rc.3",
|
||||
"description": "Smart TS wrappers for 0x smart contracts",
|
||||
"keywords": [
|
||||
"0xproject",
|
||||
@ -14,7 +14,7 @@
|
||||
"watch_without_deps": "yarn pre_build && tsc -w",
|
||||
"build": "yarn pre_build && tsc",
|
||||
"pre_build": "run-s update_artifacts_v2_beta update_artifacts_v2 generate_contract_wrappers copy_artifacts",
|
||||
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers",
|
||||
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers",
|
||||
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*",
|
||||
"test:circleci": "run-s test:coverage",
|
||||
"test": "yarn run_mocha",
|
||||
@ -29,7 +29,7 @@
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||
},
|
||||
"config": {
|
||||
"contracts_v2_beta": "Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken",
|
||||
"contracts_v2_beta": "Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder",
|
||||
"contracts_v2": "DummyERC20Token DummyERC721Token",
|
||||
"postpublish": {
|
||||
"assets": [],
|
||||
@ -45,12 +45,12 @@
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/abi-gen": "^1.0.4",
|
||||
"@0xproject/dev-utils": "^1.0.3",
|
||||
"@0xproject/migrations": "^1.0.3",
|
||||
"@0xproject/sol-compiler": "^1.0.4",
|
||||
"@0xproject/subproviders": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/abi-gen": "^1.0.5",
|
||||
"@0xproject/dev-utils": "^1.0.4",
|
||||
"@0xproject/migrations": "^1.0.4",
|
||||
"@0xproject/sol-compiler": "^1.0.5",
|
||||
"@0xproject/subproviders": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/node": "^8.0.53",
|
||||
@ -63,7 +63,7 @@
|
||||
"copyfiles": "^1.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"opn-cli": "^3.1.0",
|
||||
@ -72,25 +72,25 @@
|
||||
"source-map-support": "^0.5.0",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.7.1",
|
||||
"typescript": "2.9.2",
|
||||
"web3-provider-engine": "14.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^1.0.4",
|
||||
"@0xproject/base-contract": "^1.0.4",
|
||||
"@0xproject/fill-scenarios": "^1.0.1-rc.2",
|
||||
"@0xproject/json-schemas": "^1.0.1-rc.3",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.2",
|
||||
"@0xproject/types": "^1.0.1-rc.3",
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/web3-wrapper": "^1.1.2",
|
||||
"ethereum-types": "^1.0.3",
|
||||
"@0xproject/assert": "^1.0.5",
|
||||
"@0xproject/base-contract": "^2.0.0-rc.1",
|
||||
"@0xproject/fill-scenarios": "^1.0.1-rc.3",
|
||||
"@0xproject/json-schemas": "^1.0.1-rc.4",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.3",
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"@0xproject/web3-wrapper": "^1.2.0",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"ethereumjs-blockstream": "5.0.0",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"ethers": "3.0.22",
|
||||
"js-sha3": "^0.7.0",
|
||||
"lodash": "^4.17.4",
|
||||
"lodash": "^4.17.5",
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -7,6 +7,7 @@ import * as ERC20Token from './artifacts/ERC20Token.json';
|
||||
import * as ERC721Proxy from './artifacts/ERC721Proxy.json';
|
||||
import * as ERC721Token from './artifacts/ERC721Token.json';
|
||||
import * as Exchange from './artifacts/Exchange.json';
|
||||
import * as Forwarder from './artifacts/Forwarder.json';
|
||||
import * as EtherToken from './artifacts/WETH9.json';
|
||||
import * as ZRXToken from './artifacts/ZRXToken.json';
|
||||
|
||||
@ -20,4 +21,5 @@ export const artifacts = {
|
||||
EtherToken: (EtherToken as any) as ContractArtifact,
|
||||
ERC20Proxy: (ERC20Proxy as any) as ContractArtifact,
|
||||
ERC721Proxy: (ERC721Proxy as any) as ContractArtifact,
|
||||
Forwarder: (Forwarder as any) as ContractArtifact,
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ import { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
|
||||
import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
|
||||
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
|
||||
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
|
||||
import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
|
||||
import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema';
|
||||
import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema';
|
||||
import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema';
|
||||
@ -47,6 +48,11 @@ export class ContractWrappers {
|
||||
* erc721Proxy smart contract.
|
||||
*/
|
||||
public erc721Proxy: ERC721ProxyWrapper;
|
||||
/**
|
||||
* An instance of the ForwarderWrapper class containing methods for interacting with any Forwarder smart contract.
|
||||
*/
|
||||
public forwarder: ForwarderWrapper;
|
||||
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
/**
|
||||
* Instantiates a new ContractWrappers instance.
|
||||
@ -104,6 +110,12 @@ export class ContractWrappers {
|
||||
config.zrxContractAddress,
|
||||
blockPollingIntervalMs,
|
||||
);
|
||||
this.forwarder = new ForwarderWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
config.forwarderContractAddress,
|
||||
config.zrxContractAddress,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
|
||||
|
@ -882,15 +882,35 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async getOrderInfoAsync(order: Order | SignedOrder, methodOpts: MethodOpts = {}): Promise<OrderInfo> {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
if (!_.isUndefined(methodOpts)) {
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
}
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
|
||||
const txData = {};
|
||||
const orderInfo = await exchangeInstance.getOrderInfo.callAsync(order, txData, methodOpts.defaultBlock);
|
||||
return orderInfo;
|
||||
}
|
||||
/**
|
||||
* Get order info for multiple orders
|
||||
* @param orders Orders
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @returns Array of Order infos
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async getOrdersInfoAsync(
|
||||
orders: Array<Order | SignedOrder>,
|
||||
methodOpts: MethodOpts = {},
|
||||
): Promise<OrderInfo[]> {
|
||||
assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
|
||||
if (!_.isUndefined(methodOpts)) {
|
||||
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
|
||||
}
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const txData = {};
|
||||
const ordersInfo = await exchangeInstance.getOrdersInfo.callAsync(orders, txData, methodOpts.defaultBlock);
|
||||
return ordersInfo;
|
||||
}
|
||||
/**
|
||||
* Cancel a given order.
|
||||
* @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel.
|
||||
|
@ -0,0 +1,220 @@
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { AssetProxyId, SignedOrder } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from '../artifacts';
|
||||
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
|
||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
||||
import { TransactionOpts } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { calldataOptimizationUtils } from '../utils/calldata_optimization_utils';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { ContractWrapper } from './contract_wrapper';
|
||||
import { ForwarderContract } from './generated/forwarder';
|
||||
|
||||
/**
|
||||
* This class includes the functionality related to interacting with the Forwarder contract.
|
||||
*/
|
||||
export class ForwarderWrapper extends ContractWrapper {
|
||||
public abi: ContractAbi = artifacts.Forwarder.compilerOutput.abi;
|
||||
private _forwarderContractIfExists?: ForwarderContract;
|
||||
private _contractAddressIfExists?: string;
|
||||
private _zrxContractAddressIfExists?: string;
|
||||
constructor(
|
||||
web3Wrapper: Web3Wrapper,
|
||||
networkId: number,
|
||||
contractAddressIfExists?: string,
|
||||
zrxContractAddressIfExists?: string,
|
||||
) {
|
||||
super(web3Wrapper, networkId);
|
||||
this._contractAddressIfExists = contractAddressIfExists;
|
||||
this._zrxContractAddressIfExists = zrxContractAddressIfExists;
|
||||
}
|
||||
/**
|
||||
* 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 txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async marketSellOrdersWithEthAsync(
|
||||
signedOrders: SignedOrder[],
|
||||
takerAddress: string,
|
||||
ethAmount: BigNumber,
|
||||
signedFeeOrders: SignedOrder[] = [],
|
||||
feePercentage: BigNumber = constants.ZERO_AMOUNT,
|
||||
feeRecipientAddress: string = constants.NULL_ADDRESS,
|
||||
txOpts: TransactionOpts = {},
|
||||
): 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.isBigNumber('feePercentage', feePercentage);
|
||||
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
// other assertions
|
||||
assert.ordersCanBeUsedForForwarderContract(signedOrders, this.getEtherTokenAddress());
|
||||
assert.feeOrdersCanBeUsedForForwarderContract(
|
||||
signedFeeOrders,
|
||||
this.getZRXTokenAddress(),
|
||||
this.getEtherTokenAddress(),
|
||||
);
|
||||
// lowercase input addresses
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
|
||||
// optimize orders
|
||||
const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders);
|
||||
const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders);
|
||||
// send transaction
|
||||
const forwarderContractInstance = await this._getForwarderContractAsync();
|
||||
const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync(
|
||||
optimizedMarketOrders,
|
||||
_.map(optimizedMarketOrders, order => order.signature),
|
||||
optimizedFeeOrders,
|
||||
_.map(optimizedFeeOrders, order => order.signature),
|
||||
feePercentage,
|
||||
feeRecipientAddress,
|
||||
{
|
||||
value: ethAmount,
|
||||
from: normalizedTakerAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
},
|
||||
);
|
||||
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 txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async marketBuyOrdersWithEthAsync(
|
||||
signedOrders: SignedOrder[],
|
||||
makerAssetFillAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
ethAmount: BigNumber,
|
||||
signedFeeOrders: SignedOrder[] = [],
|
||||
feePercentage: BigNumber = constants.ZERO_AMOUNT,
|
||||
feeRecipientAddress: string = constants.NULL_ADDRESS,
|
||||
txOpts: TransactionOpts = {},
|
||||
): 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.isBigNumber('feePercentage', feePercentage);
|
||||
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
|
||||
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
|
||||
// other assertions
|
||||
assert.ordersCanBeUsedForForwarderContract(signedOrders, this.getEtherTokenAddress());
|
||||
assert.feeOrdersCanBeUsedForForwarderContract(
|
||||
signedFeeOrders,
|
||||
this.getZRXTokenAddress(),
|
||||
this.getEtherTokenAddress(),
|
||||
);
|
||||
// lowercase input addresses
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
|
||||
// optimize orders
|
||||
const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders);
|
||||
const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders);
|
||||
// send transaction
|
||||
const forwarderContractInstance = await this._getForwarderContractAsync();
|
||||
const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync(
|
||||
optimizedMarketOrders,
|
||||
makerAssetFillAmount,
|
||||
_.map(optimizedMarketOrders, order => order.signature),
|
||||
optimizedFeeOrders,
|
||||
_.map(optimizedFeeOrders, order => order.signature),
|
||||
feePercentage,
|
||||
feeRecipientAddress,
|
||||
{
|
||||
value: ethAmount,
|
||||
from: normalizedTakerAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
},
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Retrieves the Ethereum address of the Forwarder contract deployed on the network
|
||||
* that the user-passed web3 provider is connected to.
|
||||
* @returns The Ethereum address of the Forwarder contract being used.
|
||||
*/
|
||||
public getContractAddress(): string {
|
||||
const contractAddress = this._getContractAddress(artifacts.Forwarder, this._contractAddressIfExists);
|
||||
return contractAddress;
|
||||
}
|
||||
/**
|
||||
* Returns the ZRX token address used by the forwarder contract.
|
||||
* @return Address of ZRX token
|
||||
*/
|
||||
public getZRXTokenAddress(): string {
|
||||
const contractAddress = this._getContractAddress(artifacts.ZRXToken, this._zrxContractAddressIfExists);
|
||||
return contractAddress;
|
||||
}
|
||||
/**
|
||||
* Returns the Ether token address used by the forwarder contract.
|
||||
* @return Address of Ether token
|
||||
*/
|
||||
public getEtherTokenAddress(): string {
|
||||
const contractAddress = this._getContractAddress(artifacts.EtherToken);
|
||||
return contractAddress;
|
||||
}
|
||||
// HACK: We don't want this method to be visible to the other units within that package but not to the end user.
|
||||
// TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused.
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
private _invalidateContractInstance(): void {
|
||||
delete this._forwarderContractIfExists;
|
||||
}
|
||||
private async _getForwarderContractAsync(): Promise<ForwarderContract> {
|
||||
if (!_.isUndefined(this._forwarderContractIfExists)) {
|
||||
return this._forwarderContractIfExists;
|
||||
}
|
||||
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||
artifacts.Forwarder,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new ForwarderContract(
|
||||
abi,
|
||||
address,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
this._forwarderContractIfExists = contractInstance;
|
||||
return this._forwarderContractIfExists;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ 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 {
|
||||
ContractWrappersError,
|
||||
|
@ -5,11 +5,11 @@ export const contractWrappersPrivateNetworkConfigSchema = {
|
||||
type: 'number',
|
||||
minimum: 1,
|
||||
},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
zrxContractAddress: { $ref: '/Address' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
erc20ProxyContractAddress: { $ref: '/Address' },
|
||||
erc721ProxyContractAddress: { $ref: '/Address' },
|
||||
gasPrice: { $ref: '/numberSchema' },
|
||||
zrxContractAddress: { $ref: '/addressSchema' },
|
||||
exchangeContractAddress: { $ref: '/addressSchema' },
|
||||
erc20ProxyContractAddress: { $ref: '/addressSchema' },
|
||||
erc721ProxyContractAddress: { $ref: '/addressSchema' },
|
||||
blockPollingIntervalMs: { type: 'number' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
|
@ -19,11 +19,11 @@ export const contractWrappersPublicNetworkConfigSchema = {
|
||||
networkNameToId.ganache,
|
||||
],
|
||||
},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
zrxContractAddress: { $ref: '/Address' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
erc20ProxyContractAddress: { $ref: '/Address' },
|
||||
erc721ProxyContractAddress: { $ref: '/Address' },
|
||||
gasPrice: { $ref: '/numberSchema' },
|
||||
zrxContractAddress: { $ref: '/addressSchema' },
|
||||
exchangeContractAddress: { $ref: '/addressSchema' },
|
||||
erc20ProxyContractAddress: { $ref: '/addressSchema' },
|
||||
erc721ProxyContractAddress: { $ref: '/addressSchema' },
|
||||
blockPollingIntervalMs: { type: 'number' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
|
@ -1,7 +1,7 @@
|
||||
export const methodOptsSchema = {
|
||||
id: '/MethodOpts',
|
||||
properties: {
|
||||
defaultBlock: { $ref: '/BlockParam' },
|
||||
defaultBlock: { $ref: '/blockParamSchema' },
|
||||
},
|
||||
type: 'object',
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
export const txOptsSchema = {
|
||||
id: '/TxOpts',
|
||||
properties: {
|
||||
gasPrice: { $ref: '/Number' },
|
||||
gasPrice: { $ref: '/numberSchema' },
|
||||
gasLimit: { type: 'number' },
|
||||
},
|
||||
type: 'object',
|
||||
|
@ -109,6 +109,7 @@ export type SyncMethod = (...args: any[]) => any;
|
||||
* zrxContractAddress: The address of the ZRX contract to use
|
||||
* erc20ProxyContractAddress: The address of the erc20 token transfer proxy contract to use
|
||||
* erc721ProxyContractAddress: The address of the erc721 token transfer proxy contract to use
|
||||
* forwarderContractAddress: The address of the forwarder contract to use
|
||||
* orderWatcherConfig: All the configs related to the orderWatcher
|
||||
* blockPollingIntervalMs: The interval to use for block polling in event watching methods (defaults to 1000)
|
||||
*/
|
||||
@ -119,6 +120,7 @@ export interface ContractWrappersConfig {
|
||||
zrxContractAddress?: string;
|
||||
erc20ProxyContractAddress?: string;
|
||||
erc721ProxyContractAddress?: string;
|
||||
forwarderContractAddress?: string;
|
||||
blockPollingIntervalMs?: number;
|
||||
}
|
||||
|
||||
@ -172,13 +174,13 @@ export enum TransferType {
|
||||
export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
|
||||
|
||||
export interface OrderInfo {
|
||||
orderStatus: number;
|
||||
orderStatus: OrderStatus;
|
||||
orderHash: string;
|
||||
orderTakerAssetFilledAmount: BigNumber;
|
||||
}
|
||||
|
||||
export enum OrderStatus {
|
||||
INVALID,
|
||||
INVALID = 0,
|
||||
INVALID_MAKER_ASSET_AMOUNT,
|
||||
INVALID_TAKER_ASSET_AMOUNT,
|
||||
FILLABLE,
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { assert as sharedAssert } from '@0xproject/assert';
|
||||
// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here
|
||||
import { Schema } from '@0xproject/json-schemas'; // tslint:disable-line:no-unused-variable
|
||||
import { signatureUtils } from '@0xproject/order-utils';
|
||||
import { ECSignature } from '@0xproject/types'; // tslint:disable-line:no-unused-variable
|
||||
import { signatureUtils, assetDataUtils } from '@0xproject/order-utils';
|
||||
import { Order } from '@0xproject/types'; // tslint:disable-line:no-unused-variable
|
||||
import { BigNumber } from '@0xproject/utils'; // tslint:disable-line:no-unused-variable
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import { Provider } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
export const assert = {
|
||||
...sharedAssert,
|
||||
@ -16,12 +19,12 @@ export const assert = {
|
||||
signerAddress: string,
|
||||
): Promise<void> {
|
||||
const isValid = await signatureUtils.isValidSignatureAsync(provider, orderHash, signature, signerAddress);
|
||||
this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||
sharedAssert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||
},
|
||||
isValidSubscriptionToken(variableName: string, subscriptionToken: string): void {
|
||||
const uuidRegex = new RegExp('^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$');
|
||||
const isValid = uuidRegex.test(subscriptionToken);
|
||||
this.assert(isValid, `Expected ${variableName} to be a valid subscription token`);
|
||||
sharedAssert.assert(isValid, `Expected ${variableName} to be a valid subscription token`);
|
||||
},
|
||||
async isSenderAddressAsync(
|
||||
variableName: string,
|
||||
@ -35,4 +38,53 @@ export const assert = {
|
||||
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
},
|
||||
ordersCanBeUsedForForwarderContract(orders: Order[], etherTokenAddress: string): void {
|
||||
sharedAssert.assert(!_.isEmpty(orders), 'Expected at least 1 signed order. Found no orders');
|
||||
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'makerAssetData');
|
||||
assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress);
|
||||
assert.allTakerAddressesAreNull(orders);
|
||||
},
|
||||
feeOrdersCanBeUsedForForwarderContract(orders: Order[], zrxTokenAddress: string, etherTokenAddress: string): void {
|
||||
if (!_.isEmpty(orders)) {
|
||||
assert.allMakerAssetDatasAreErc20Token(orders, zrxTokenAddress);
|
||||
assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress);
|
||||
}
|
||||
},
|
||||
allTakerAddressesAreNull(orders: Order[]): void {
|
||||
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', constants.NULL_ADDRESS);
|
||||
},
|
||||
allMakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void {
|
||||
assert.ordersHaveAtMostOneUniqueValueForProperty(
|
||||
orders,
|
||||
'makerAssetData',
|
||||
assetDataUtils.encodeERC20AssetData(tokenAddress),
|
||||
);
|
||||
},
|
||||
allTakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void {
|
||||
assert.ordersHaveAtMostOneUniqueValueForProperty(
|
||||
orders,
|
||||
'takerAssetData',
|
||||
assetDataUtils.encodeERC20AssetData(tokenAddress),
|
||||
);
|
||||
},
|
||||
/*
|
||||
* Asserts that all the orders have the same value for the provided propertyName
|
||||
* If the value parameter is provided, this asserts that all orders have the prope
|
||||
*/
|
||||
ordersHaveAtMostOneUniqueValueForProperty(orders: Order[], propertyName: string, value?: any): void {
|
||||
const allValues = _.map(orders, order => _.get(order, propertyName));
|
||||
sharedAssert.hasAtMostOneUniqueValue(
|
||||
allValues,
|
||||
`Expected all orders to have the same ${propertyName} field. Found the following ${propertyName} values: ${JSON.stringify(
|
||||
allValues,
|
||||
)}`,
|
||||
);
|
||||
if (!_.isUndefined(value)) {
|
||||
const firstValue = _.head(allValues);
|
||||
sharedAssert.assert(
|
||||
firstValue === value,
|
||||
`Expected all orders to have a ${propertyName} field with value: ${value}. Found: ${firstValue}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -0,0 +1,44 @@
|
||||
import { SignedOrder } from '@0xproject/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,
|
||||
};
|
||||
};
|
@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils';
|
||||
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
NULL_BYTES: '0x',
|
||||
TESTRPC_NETWORK_ID: 50,
|
||||
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
||||
REVERT: 'revert',
|
||||
@ -10,4 +11,5 @@ export const constants = {
|
||||
// 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),
|
||||
};
|
||||
|
@ -0,0 +1,60 @@
|
||||
import { orderFactory } from '@0xproject/order-utils';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
|
||||
import { assert } from '../src/utils/assert';
|
||||
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));
|
||||
});
|
||||
});
|
||||
});
|
@ -277,6 +277,15 @@ describe('ExchangeWrapper', () => {
|
||||
expect(orderInfo.orderHash).to.be.equal(orderHash);
|
||||
});
|
||||
});
|
||||
describe('#getOrdersInfoAsync', () => {
|
||||
it('should get the orders info', async () => {
|
||||
const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
expect(ordersInfo[0].orderHash).to.be.equal(orderHash);
|
||||
const anotherOrderHash = orderHashUtils.getOrderHashHex(anotherSignedOrder);
|
||||
expect(ordersInfo[1].orderHash).to.be.equal(anotherOrderHash);
|
||||
});
|
||||
});
|
||||
describe('#isValidSignature', () => {
|
||||
it('should check if the signature is valid', async () => {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
@ -295,7 +304,7 @@ describe('ExchangeWrapper', () => {
|
||||
});
|
||||
});
|
||||
describe('#isAllowedValidatorAsync', () => {
|
||||
it('should check if the validator is alllowed', async () => {
|
||||
it('should check if the validator is allowed', async () => {
|
||||
const signerAddress = makerAddress;
|
||||
const validatorAddress = constants.NULL_ADDRESS;
|
||||
const isAllowed = await contractWrappers.exchange.isAllowedValidatorAsync(signerAddress, validatorAddress);
|
||||
|
130
packages/contract-wrappers/test/forwarder_wrapper_test.ts
Normal file
130
packages/contract-wrappers/test/forwarder_wrapper_test.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
|
||||
import { FillScenarios } from '@0xproject/fill-scenarios';
|
||||
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
|
||||
import { DoneCallback, SignedOrder } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as chai from 'chai';
|
||||
import { BlockParamLiteral } from 'ethereum-types';
|
||||
import 'mocha';
|
||||
|
||||
import {
|
||||
ContractWrappers,
|
||||
DecodedLogEvent,
|
||||
ExchangeCancelEventArgs,
|
||||
ExchangeEvents,
|
||||
ExchangeFillEventArgs,
|
||||
OrderStatus,
|
||||
} from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
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('ForwarderWrapper', () => {
|
||||
const contractWrappersConfig = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
blockPollingIntervalMs: 0,
|
||||
};
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const takerTokenFillAmount = new BigNumber(5);
|
||||
let contractWrappers: ContractWrappers;
|
||||
let fillScenarios: FillScenarios;
|
||||
let forwarderContractAddress: string;
|
||||
let exchangeContractAddress: string;
|
||||
let zrxTokenAddress: 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;
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
contractWrappers = new ContractWrappers(provider, contractWrappersConfig);
|
||||
forwarderContractAddress = contractWrappers.forwarder.getContractAddress();
|
||||
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
|
||||
fillScenarios = new FillScenarios(
|
||||
provider,
|
||||
userAddresses,
|
||||
zrxTokenAddress,
|
||||
exchangeContractAddress,
|
||||
contractWrappers.erc20Proxy.getContractAddress(),
|
||||
contractWrappers.erc721Proxy.getContractAddress(),
|
||||
);
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
|
||||
[makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
takerTokenAddress = tokenUtils.getWethTokenAddress();
|
||||
[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.FULLY_FILLED);
|
||||
expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FULLY_FILLED);
|
||||
});
|
||||
});
|
||||
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.FULLY_FILLED);
|
||||
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
|
||||
});
|
||||
});
|
||||
});
|
@ -7,6 +7,7 @@ async callAsync(
|
||||
const functionSignature = '{{this.functionSignature}}';
|
||||
const inputAbi = self._lookupAbi(functionSignature).inputs;
|
||||
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
||||
BaseContract.strictArgumentEncodingCheck(inputAbi, [{{> params inputs=inputs}}]);
|
||||
const ethersFunction = self._lookupEthersInterface(functionSignature).functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
) as ethers.CallDescription;
|
||||
|
@ -11,6 +11,7 @@ public {{this.tsName}} = {
|
||||
const self = this as any as {{contractName}}Contract;
|
||||
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
|
||||
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
||||
BaseContract.strictArgumentEncodingCheck(inputAbi, [{{> params inputs=inputs}}]);
|
||||
const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
).data;
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "contracts",
|
||||
"version": "2.1.39",
|
||||
"version": "2.1.40",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -46,11 +46,11 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/abi-gen": "^1.0.4",
|
||||
"@0xproject/dev-utils": "^1.0.3",
|
||||
"@0xproject/sol-cov": "^1.0.3",
|
||||
"@0xproject/subproviders": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/abi-gen": "^1.0.5",
|
||||
"@0xproject/dev-utils": "^1.0.4",
|
||||
"@0xproject/sol-cov": "^2.0.0",
|
||||
"@0xproject/subproviders": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/ethereumjs-abi": "^0.6.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
@ -62,30 +62,30 @@
|
||||
"copyfiles": "^1.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solc": "^0.4.24",
|
||||
"solhint": "^1.2.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.7.1",
|
||||
"typescript": "2.9.2",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/base-contract": "^1.0.4",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.2",
|
||||
"@0xproject/sol-compiler": "^1.0.4",
|
||||
"@0xproject/types": "^1.0.1-rc.3",
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/web3-wrapper": "^1.1.2",
|
||||
"@0xproject/base-contract": "^2.0.0-rc.1",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.3",
|
||||
"@0xproject/sol-compiler": "^1.0.5",
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"@0xproject/web3-wrapper": "^1.2.0",
|
||||
"@types/js-combinatorics": "^0.5.29",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereum-types": "^1.0.3",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"ethereumjs-abi": "0.6.5",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"ethers": "3.0.22",
|
||||
"js-combinatorics": "^0.5.3",
|
||||
"lodash": "^4.17.4"
|
||||
"lodash": "^4.17.5"
|
||||
}
|
||||
}
|
||||
|
@ -36,28 +36,25 @@ contract MixinAssets is
|
||||
|
||||
bytes4 constant internal ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));
|
||||
|
||||
/// @dev Withdraws ERC20 tokens from this contract. The contract requires a ZRX balance in order to
|
||||
/// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to
|
||||
/// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be
|
||||
/// used to withdraw tokens that were accidentally sent to this contract.
|
||||
/// @param token Address of ERC20 token to withdraw.
|
||||
/// used to withdraw assets that were accidentally sent to this contract.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of ERC20 token to withdraw.
|
||||
function withdrawERC20(
|
||||
address token,
|
||||
function withdrawAsset(
|
||||
bytes assetData,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
require(
|
||||
IERC20Token(token).transfer(msg.sender, amount),
|
||||
"WITHDRAWAL_FAILED"
|
||||
);
|
||||
transferAssetToSender(assetData, amount);
|
||||
}
|
||||
|
||||
/// @dev Transfers given amount of asset to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferPurchasedAssetToSender(
|
||||
function transferAssetToSender(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
|
@ -139,7 +139,7 @@ contract MixinExchangeWrapper is
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyWithWeth(
|
||||
function marketBuyExactAmountWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
@ -180,10 +180,16 @@ contract MixinExchangeWrapper is
|
||||
addFillResults(totalFillResults, singleFillResults);
|
||||
|
||||
// Stop execution if the entire amount of makerAsset has been bought
|
||||
if (totalFillResults.makerAssetFilledAmount >= makerAssetFillAmount) {
|
||||
uint256 makerAssetFilledAmount = totalFillResults.makerAssetFilledAmount;
|
||||
if (makerAssetFilledAmount >= makerAssetFillAmount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
require(
|
||||
makerAssetFilledAmount >= makerAssetFillAmount,
|
||||
"COMPLETE_FILL_FAILED"
|
||||
);
|
||||
return totalFillResults;
|
||||
}
|
||||
|
||||
@ -196,7 +202,7 @@ contract MixinExchangeWrapper is
|
||||
/// @param zrxBuyAmount Desired amount of ZRX to buy.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return totalFillResults Amounts filled and fees paid by maker and taker.
|
||||
function marketBuyZrxWithWeth(
|
||||
function marketBuyExactZrxWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 zrxBuyAmount,
|
||||
bytes[] memory signatures
|
||||
@ -248,6 +254,10 @@ contract MixinExchangeWrapper is
|
||||
}
|
||||
}
|
||||
|
||||
require(
|
||||
zrxPurchased >= zrxBuyAmount,
|
||||
"COMPLETE_FILL_FAILED"
|
||||
);
|
||||
return totalFillResults;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import "./libs/LibConstants.sol";
|
||||
import "./mixins/MWeth.sol";
|
||||
import "./mixins/MAssets.sol";
|
||||
import "./mixins/MExchangeWrapper.sol";
|
||||
import "./mixins/MForwarderCore.sol";
|
||||
import "./interfaces/IForwarderCore.sol";
|
||||
import "../utils/LibBytes/LibBytes.sol";
|
||||
import "../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../protocol/Exchange/libs/LibFillResults.sol";
|
||||
@ -37,7 +37,7 @@ contract MixinForwarderCore is
|
||||
MWeth,
|
||||
MAssets,
|
||||
MExchangeWrapper,
|
||||
MForwarderCore
|
||||
IForwarderCore
|
||||
{
|
||||
|
||||
using LibBytes for bytes;
|
||||
@ -117,7 +117,7 @@ contract MixinForwarderCore is
|
||||
);
|
||||
// Buy back all ZRX spent on fees.
|
||||
zrxBuyAmount = orderFillResults.takerFeePaid;
|
||||
feeOrderFillResults = marketBuyZrxWithWeth(
|
||||
feeOrderFillResults = marketBuyExactZrxWithWeth(
|
||||
feeOrders,
|
||||
zrxBuyAmount,
|
||||
feeSignatures
|
||||
@ -125,13 +125,6 @@ contract MixinForwarderCore is
|
||||
makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;
|
||||
}
|
||||
|
||||
// Ensure that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold.
|
||||
assertValidFillResults(
|
||||
orderFillResults,
|
||||
feeOrderFillResults,
|
||||
zrxBuyAmount
|
||||
);
|
||||
|
||||
// Transfer feePercentage of total ETH spent on primary orders to feeRecipient.
|
||||
// Refund remaining ETH to msg.sender.
|
||||
transferEthFeeAndRefund(
|
||||
@ -142,7 +135,7 @@ contract MixinForwarderCore is
|
||||
);
|
||||
|
||||
// Transfer purchased assets to msg.sender.
|
||||
transferPurchasedAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);
|
||||
transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);
|
||||
}
|
||||
|
||||
/// @dev Attempt to purchase makerAssetFillAmount of makerAsset by selling ETH provided with transaction.
|
||||
@ -180,7 +173,7 @@ contract MixinForwarderCore is
|
||||
if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) {
|
||||
// If the makerAsset is ZRX, it is not necessary to pay fees out of this
|
||||
// contracts's ZRX balance because fees are factored into the price of the order.
|
||||
orderFillResults = marketBuyZrxWithWeth(
|
||||
orderFillResults = marketBuyExactZrxWithWeth(
|
||||
orders,
|
||||
makerAssetFillAmount,
|
||||
signatures
|
||||
@ -190,14 +183,14 @@ contract MixinForwarderCore is
|
||||
} else {
|
||||
// Attemp to purchase desired amount of makerAsset.
|
||||
// ZRX fees are payed with this contract's balance.
|
||||
orderFillResults = marketBuyWithWeth(
|
||||
orderFillResults = marketBuyExactAmountWithWeth(
|
||||
orders,
|
||||
makerAssetFillAmount,
|
||||
signatures
|
||||
);
|
||||
// Buy back all ZRX spent on fees.
|
||||
zrxBuyAmount = orderFillResults.takerFeePaid;
|
||||
feeOrderFillResults = marketBuyZrxWithWeth(
|
||||
feeOrderFillResults = marketBuyExactZrxWithWeth(
|
||||
feeOrders,
|
||||
zrxBuyAmount,
|
||||
feeSignatures
|
||||
@ -205,13 +198,6 @@ contract MixinForwarderCore is
|
||||
makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;
|
||||
}
|
||||
|
||||
// Ensure that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold.
|
||||
assertValidFillResults(
|
||||
orderFillResults,
|
||||
feeOrderFillResults,
|
||||
zrxBuyAmount
|
||||
);
|
||||
|
||||
// Transfer feePercentage of total ETH spent on primary orders to feeRecipient.
|
||||
// Refund remaining ETH to msg.sender.
|
||||
transferEthFeeAndRefund(
|
||||
@ -222,33 +208,6 @@ contract MixinForwarderCore is
|
||||
);
|
||||
|
||||
// Transfer purchased assets to msg.sender.
|
||||
transferPurchasedAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);
|
||||
}
|
||||
|
||||
/// @dev Ensures that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold.
|
||||
/// @param orderFillResults Amounts filled and fees paid for primary orders.
|
||||
/// @param feeOrderFillResults Amounts filled and fees paid for fee orders.
|
||||
/// @param zrxBuyAmount The amount of ZRX that needed to be repurchased after filling primary orders.
|
||||
function assertValidFillResults(
|
||||
FillResults memory orderFillResults,
|
||||
FillResults memory feeOrderFillResults,
|
||||
uint256 zrxBuyAmount
|
||||
)
|
||||
internal
|
||||
view
|
||||
{
|
||||
// Ensure that all ZRX spent while filling primary orders has been repurchased.
|
||||
uint256 zrxPurchased = safeSub(feeOrderFillResults.makerAssetFilledAmount, feeOrderFillResults.takerFeePaid);
|
||||
require(
|
||||
zrxPurchased >= zrxBuyAmount,
|
||||
"COMPLETE_FILL_FAILED"
|
||||
);
|
||||
|
||||
// Ensure that no extra WETH owned by this contract has been sold.
|
||||
uint256 wethSold = safeAdd(orderFillResults.takerAssetFilledAmount, feeOrderFillResults.takerAssetFilledAmount);
|
||||
require(
|
||||
wethSold <= msg.value,
|
||||
"OVERSOLD_WETH"
|
||||
);
|
||||
transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);
|
||||
}
|
||||
}
|
||||
|
@ -71,12 +71,16 @@ contract MixinWeth is
|
||||
"FEE_PERCENTAGE_TOO_LARGE"
|
||||
);
|
||||
|
||||
// Calculate amount of WETH that hasn't been sold.
|
||||
uint256 wethRemaining = safeSub(
|
||||
msg.value,
|
||||
safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx)
|
||||
// Ensure that no extra WETH owned by this contract has been sold.
|
||||
uint256 wethSold = safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx);
|
||||
require(
|
||||
wethSold <= msg.value,
|
||||
"OVERSOLD_WETH"
|
||||
);
|
||||
|
||||
// Calculate amount of WETH that hasn't been sold.
|
||||
uint256 wethRemaining = safeSub(msg.value, wethSold);
|
||||
|
||||
// Calculate ETH fee to pay to feeRecipient.
|
||||
uint256 ethFee = getPartialAmount(
|
||||
feePercentage,
|
||||
|
@ -21,13 +21,13 @@ pragma solidity 0.4.24;
|
||||
|
||||
contract IAssets {
|
||||
|
||||
/// @dev Withdraws ERC20 tokens from this contract. The contract requires a ZRX balance in order to
|
||||
/// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to
|
||||
/// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be
|
||||
/// used to withdraw tokens that were accidentally sent to this contract.
|
||||
/// @param token Address of ERC20 token to withdraw.
|
||||
/// used to withdraw assets that were accidentally sent to this contract.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of ERC20 token to withdraw.
|
||||
function withdrawERC20(
|
||||
address token,
|
||||
function withdrawAsset(
|
||||
bytes assetData,
|
||||
uint256 amount
|
||||
)
|
||||
external;
|
||||
|
@ -28,7 +28,7 @@ contract MAssets is
|
||||
/// @dev Transfers given amount of asset to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferPurchasedAssetToSender(
|
||||
function transferAssetToSender(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
|
@ -60,7 +60,7 @@ contract MExchangeWrapper {
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyWithWeth(
|
||||
function marketBuyExactAmountWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
@ -77,7 +77,7 @@ contract MExchangeWrapper {
|
||||
/// @param zrxBuyAmount Desired amount of ZRX to buy.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return totalFillResults Amounts filled and fees paid by maker and taker.
|
||||
function marketBuyZrxWithWeth(
|
||||
function marketBuyExactZrxWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 zrxBuyAmount,
|
||||
bytes[] memory signatures
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../protocol/Exchange/libs/LibFillResults.sol";
|
||||
import "../interfaces/IForwarderCore.sol";
|
||||
|
||||
|
||||
contract MForwarderCore is
|
||||
IForwarderCore
|
||||
{
|
||||
|
||||
/// @dev Ensures that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold.
|
||||
/// @param orderFillResults Amounts filled and fees paid for primary orders.
|
||||
/// @param feeOrderFillResults Amounts filled and fees paid for fee orders.
|
||||
/// @param zrxBuyAmount The amount of ZRX that needed to be repurchased after filling primary orders.
|
||||
function assertValidFillResults(
|
||||
LibFillResults.FillResults memory orderFillResults,
|
||||
LibFillResults.FillResults memory feeOrderFillResults,
|
||||
uint256 zrxBuyAmount
|
||||
)
|
||||
internal
|
||||
view;
|
||||
}
|
@ -96,14 +96,15 @@ contract MixinSignatureValidator is
|
||||
"LENGTH_GREATER_THAN_0_REQUIRED"
|
||||
);
|
||||
|
||||
// Ensure signature is supported
|
||||
// Pop last byte off of signature byte array.
|
||||
uint8 signatureTypeRaw = uint8(signature.popLastByte());
|
||||
|
||||
// Ensure signature is supported
|
||||
require(
|
||||
signatureTypeRaw < uint8(SignatureType.NSignatureTypes),
|
||||
"SIGNATURE_UNSUPPORTED"
|
||||
);
|
||||
|
||||
// Pop last byte off of signature byte array.
|
||||
SignatureType signatureType = SignatureType(signatureTypeRaw);
|
||||
|
||||
// Variables are not scoped in Solidity.
|
||||
@ -141,7 +142,12 @@ contract MixinSignatureValidator is
|
||||
v = uint8(signature[0]);
|
||||
r = signature.readBytes32(1);
|
||||
s = signature.readBytes32(33);
|
||||
recovered = ecrecover(hash, v, r, s);
|
||||
recovered = ecrecover(
|
||||
hash,
|
||||
v,
|
||||
r,
|
||||
s
|
||||
);
|
||||
isValid = signerAddress == recovered;
|
||||
return isValid;
|
||||
|
||||
@ -197,7 +203,6 @@ contract MixinSignatureValidator is
|
||||
// | 0x14 + x | 1 | Signature type is always "\x06" |
|
||||
} else if (signatureType == SignatureType.Validator) {
|
||||
// Pop last 20 bytes off of signature byte array.
|
||||
|
||||
address validatorAddress = signature.popLast20Bytes();
|
||||
|
||||
// Ensure signer has approved validator.
|
||||
|
@ -123,22 +123,25 @@ contract MixinTransactions is
|
||||
bytes32 dataHash = keccak256(data);
|
||||
|
||||
// Assembly for more efficiently computing:
|
||||
// keccak256(abi.encode(
|
||||
// keccak256(abi.encodePacked(
|
||||
// EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH,
|
||||
// salt,
|
||||
// signerAddress,
|
||||
// bytes32(signerAddress),
|
||||
// keccak256(data)
|
||||
// ));
|
||||
|
||||
assembly {
|
||||
// Load free memory pointer
|
||||
let memPtr := mload(64)
|
||||
mstore(memPtr, schemaHash)
|
||||
mstore(add(memPtr, 32), salt)
|
||||
mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff))
|
||||
mstore(add(memPtr, 96), dataHash)
|
||||
|
||||
mstore(memPtr, schemaHash) // hash of schema
|
||||
mstore(add(memPtr, 32), salt) // salt
|
||||
mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress
|
||||
mstore(add(memPtr, 96), dataHash) // hash of data
|
||||
|
||||
// Compute hash
|
||||
result := keccak256(memPtr, 128)
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -24,20 +24,17 @@ import "./LibOrder.sol";
|
||||
|
||||
contract LibAbiEncoder {
|
||||
|
||||
/// @dev ABI encodes calldata for `fillOrder` in memory and returns the address range.
|
||||
/// This range can be passed into `call` or `delegatecall` to invoke an external
|
||||
/// call to `fillOrder`.
|
||||
/// @dev ABI encodes calldata for `fillOrder`.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return calldataBegin Memory address of ABI encoded calldata.
|
||||
/// @return calldataLength Lenfgth of ABI encoded calldata.
|
||||
/// @return ABI encoded calldata for `fillOrder`.
|
||||
function abiEncodeFillOrder(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory fillOrderCalldata)
|
||||
{
|
||||
@ -207,10 +204,10 @@ contract LibAbiEncoder {
|
||||
}
|
||||
|
||||
// Set length of calldata
|
||||
mstore(
|
||||
fillOrderCalldata,
|
||||
sub(dataAreaEnd, add(fillOrderCalldata, 0x20))
|
||||
)
|
||||
mstore(fillOrderCalldata, sub(dataAreaEnd, add(fillOrderCalldata, 0x20)))
|
||||
|
||||
// Increment free memory pointer
|
||||
mstore(0x40, dataAreaEnd)
|
||||
}
|
||||
|
||||
return fillOrderCalldata;
|
||||
|
@ -30,7 +30,7 @@ contract LibEIP712 {
|
||||
string constant internal EIP712_DOMAIN_VERSION = "2";
|
||||
|
||||
// Hash of the EIP712 Domain Separator Schema
|
||||
bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(
|
||||
bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(
|
||||
"EIP712Domain(",
|
||||
"string name,",
|
||||
"string version,",
|
||||
@ -45,11 +45,11 @@ contract LibEIP712 {
|
||||
constructor ()
|
||||
public
|
||||
{
|
||||
EIP712_DOMAIN_HASH = keccak256(abi.encode(
|
||||
EIP712_DOMAIN_HASH = keccak256(abi.encodePacked(
|
||||
EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
|
||||
keccak256(bytes(EIP712_DOMAIN_NAME)),
|
||||
keccak256(bytes(EIP712_DOMAIN_VERSION)),
|
||||
address(this)
|
||||
bytes32(address(this))
|
||||
));
|
||||
}
|
||||
|
||||
@ -59,8 +59,28 @@ contract LibEIP712 {
|
||||
function hashEIP712Message(bytes32 hashStruct)
|
||||
internal
|
||||
view
|
||||
returns (bytes32)
|
||||
returns (bytes32 result)
|
||||
{
|
||||
return keccak256(abi.encodePacked(EIP191_HEADER, EIP712_DOMAIN_HASH, hashStruct));
|
||||
bytes32 eip712DomainHash = EIP712_DOMAIN_HASH;
|
||||
|
||||
// Assembly for more efficient computing:
|
||||
// keccak256(abi.encodePacked(
|
||||
// EIP191_HEADER,
|
||||
// EIP712_DOMAIN_HASH,
|
||||
// hashStruct
|
||||
// ));
|
||||
|
||||
assembly {
|
||||
// Load free memory pointer
|
||||
let memPtr := mload(64)
|
||||
|
||||
mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header
|
||||
mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash
|
||||
mstore(add(memPtr, 34), hashStruct) // Hash of struct
|
||||
|
||||
// Compute hash
|
||||
result := keccak256(memPtr, 66)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -103,11 +103,12 @@ contract LibOrder is
|
||||
bytes32 takerAssetDataHash = keccak256(order.takerAssetData);
|
||||
|
||||
// Assembly for more efficiently computing:
|
||||
// keccak256(abi.encode(
|
||||
// order.makerAddress,
|
||||
// order.takerAddress,
|
||||
// order.feeRecipientAddress,
|
||||
// order.senderAddress,
|
||||
// keccak256(abi.encodePacked(
|
||||
// EIP712_ORDER_SCHEMA_HASH,
|
||||
// bytes32(order.makerAddress),
|
||||
// bytes32(order.takerAddress),
|
||||
// bytes32(order.feeRecipientAddress),
|
||||
// bytes32(order.senderAddress),
|
||||
// order.makerAssetAmount,
|
||||
// order.takerAssetAmount,
|
||||
// order.makerFee,
|
||||
@ -119,24 +120,26 @@ contract LibOrder is
|
||||
// ));
|
||||
|
||||
assembly {
|
||||
// Calculate memory addresses that will be swapped out before hashing
|
||||
let pos1 := sub(order, 32)
|
||||
let pos2 := add(order, 320)
|
||||
let pos3 := add(order, 352)
|
||||
|
||||
// Backup
|
||||
// solhint-disable-next-line space-after-comma
|
||||
let temp1 := mload(sub(order, 32))
|
||||
let temp2 := mload(add(order, 320))
|
||||
let temp3 := mload(add(order, 352))
|
||||
let temp1 := mload(pos1)
|
||||
let temp2 := mload(pos2)
|
||||
let temp3 := mload(pos3)
|
||||
|
||||
// Hash in place
|
||||
// solhint-disable-next-line space-after-comma
|
||||
mstore(sub(order, 32), schemaHash)
|
||||
mstore(add(order, 320), makerAssetDataHash)
|
||||
mstore(add(order, 352), takerAssetDataHash)
|
||||
result := keccak256(sub(order, 32), 416)
|
||||
mstore(pos1, schemaHash)
|
||||
mstore(pos2, makerAssetDataHash)
|
||||
mstore(pos3, takerAssetDataHash)
|
||||
result := keccak256(pos1, 416)
|
||||
|
||||
// Restore
|
||||
// solhint-disable-next-line space-after-comma
|
||||
mstore(sub(order, 32), temp1)
|
||||
mstore(add(order, 320), temp2)
|
||||
mstore(add(order, 352), temp3)
|
||||
mstore(pos1, temp1)
|
||||
mstore(pos2, temp2)
|
||||
mstore(pos3, temp3)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
|
||||
import "../../protocol/Exchange/Exchange.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract TestExchangeInternals is
|
||||
Exchange
|
||||
{
|
||||
|
@ -22,13 +22,33 @@ pragma experimental ABIEncoderV2;
|
||||
import "../../protocol/Exchange/libs/LibMath.sol";
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../protocol/Exchange/libs/LibFillResults.sol";
|
||||
import "../../protocol/Exchange/libs/LibAbiEncoder.sol";
|
||||
|
||||
|
||||
contract TestLibs is
|
||||
LibMath,
|
||||
LibOrder,
|
||||
LibFillResults
|
||||
LibFillResults,
|
||||
LibAbiEncoder
|
||||
{
|
||||
|
||||
function publicAbiEncodeFillOrder(
|
||||
Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory fillOrderCalldata)
|
||||
{
|
||||
fillOrderCalldata = abiEncodeFillOrder(
|
||||
order,
|
||||
takerAssetFillAmount,
|
||||
signature
|
||||
);
|
||||
return fillOrderCalldata;
|
||||
}
|
||||
|
||||
function publicGetPartialAmount(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
|
@ -69,13 +69,22 @@ describe('matchOrders', () => {
|
||||
before(async () => {
|
||||
// Create accounts
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
// Hack(albrow): Both Prettier and TSLint insert a trailing comma below
|
||||
// but that is invalid syntax as of TypeScript version >= 2.8. We don't
|
||||
// have the right fine-grained configuration options in TSLint,
|
||||
// Prettier, or TypeScript, to reconcile this, so we will just have to
|
||||
// wait for them to sort it out. We disable TSLint and Prettier for
|
||||
// this part of the code for now. This occurs several times in this
|
||||
// file. See https://github.com/prettier/prettier/issues/4624.
|
||||
// prettier-ignore
|
||||
const usedAddresses = ([
|
||||
owner,
|
||||
makerAddressLeft,
|
||||
makerAddressRight,
|
||||
takerAddress,
|
||||
feeRecipientAddressLeft,
|
||||
feeRecipientAddressRight,
|
||||
// tslint:disable-next-line:trailing-comma
|
||||
feeRecipientAddressRight
|
||||
] = _.slice(accounts, 0, 6));
|
||||
// Create wrappers
|
||||
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
|
||||
@ -201,9 +210,11 @@ describe('matchOrders', () => {
|
||||
// Match signedOrderLeft with signedOrderRight
|
||||
let newERC20BalancesByOwner: ERC20BalancesByOwner;
|
||||
let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner;
|
||||
// prettier-ignore
|
||||
[
|
||||
newERC20BalancesByOwner,
|
||||
newERC721TokenIdsByOwner,
|
||||
// tslint:disable-next-line:trailing-comma
|
||||
newERC721TokenIdsByOwner
|
||||
] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync(
|
||||
signedOrderLeft,
|
||||
signedOrderRight,
|
||||
@ -306,9 +317,11 @@ describe('matchOrders', () => {
|
||||
// Match orders
|
||||
let newERC20BalancesByOwner: ERC20BalancesByOwner;
|
||||
let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner;
|
||||
// prettier-ignore
|
||||
[
|
||||
newERC20BalancesByOwner,
|
||||
newERC721TokenIdsByOwner,
|
||||
// tslint:disable-next-line:trailing-comma
|
||||
newERC721TokenIdsByOwner
|
||||
] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync(
|
||||
signedOrderLeft,
|
||||
signedOrderRight,
|
||||
@ -374,9 +387,11 @@ describe('matchOrders', () => {
|
||||
// Match orders
|
||||
let newERC20BalancesByOwner: ERC20BalancesByOwner;
|
||||
let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner;
|
||||
// prettier-ignore
|
||||
[
|
||||
newERC20BalancesByOwner,
|
||||
newERC721TokenIdsByOwner,
|
||||
// tslint:disable-next-line:trailing-comma
|
||||
newERC721TokenIdsByOwner
|
||||
] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync(
|
||||
signedOrderLeft,
|
||||
signedOrderRight,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import { signatureUtils, assetDataUtils, MessagePrefixType, orderHashUtils } from '@0xproject/order-utils';
|
||||
import { RevertReason, SignatureType, SignedOrder } from '@0xproject/types';
|
||||
import { signatureUtils, assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
|
||||
import { RevertReason, SignatureType, SignedOrder, SignerType } from '@0xproject/types';
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
import ethUtil = require('ethereumjs-util');
|
||||
@ -113,7 +113,7 @@ describe('MixinSignatureValidator', () => {
|
||||
|
||||
it('should revert when signature type is unsupported', async () => {
|
||||
const unsupportedSignatureType = SignatureType.NSignatureTypes;
|
||||
const unsupportedSignatureHex = `0x${unsupportedSignatureType}`;
|
||||
const unsupportedSignatureHex = '0x' + Buffer.from([unsupportedSignatureType]).toString('hex');
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
return expectContractCallFailed(
|
||||
signatureValidator.publicIsValidSignature.callAsync(
|
||||
@ -126,7 +126,7 @@ describe('MixinSignatureValidator', () => {
|
||||
});
|
||||
|
||||
it('should revert when SignatureType=Illegal', async () => {
|
||||
const unsupportedSignatureHex = `0x${SignatureType.Illegal}`;
|
||||
const unsupportedSignatureHex = '0x' + Buffer.from([SignatureType.Illegal]).toString('hex');
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
return expectContractCallFailed(
|
||||
signatureValidator.publicIsValidSignature.callAsync(
|
||||
@ -139,7 +139,7 @@ describe('MixinSignatureValidator', () => {
|
||||
});
|
||||
|
||||
it('should return false when SignatureType=Invalid and signature has a length of zero', async () => {
|
||||
const signatureHex = `0x${SignatureType.Invalid}`;
|
||||
const signatureHex = '0x' + Buffer.from([SignatureType.Invalid]).toString('hex');
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync(
|
||||
orderHashHex,
|
||||
@ -215,7 +215,7 @@ describe('MixinSignatureValidator', () => {
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix(
|
||||
orderHashHex,
|
||||
MessagePrefixType.EthSign,
|
||||
SignerType.Default,
|
||||
);
|
||||
const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
|
||||
@ -241,7 +241,7 @@ describe('MixinSignatureValidator', () => {
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix(
|
||||
orderHashHex,
|
||||
MessagePrefixType.EthSign,
|
||||
SignerType.Default,
|
||||
);
|
||||
const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
|
||||
@ -391,10 +391,7 @@ describe('MixinSignatureValidator', () => {
|
||||
it('should return true when SignatureType=Trezor and signature is valid', async () => {
|
||||
// Create Trezor signature
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix(
|
||||
orderHashHex,
|
||||
MessagePrefixType.Trezor,
|
||||
);
|
||||
const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix(orderHashHex, SignerType.Trezor);
|
||||
const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
|
||||
// Create 0x signature from Trezor signature
|
||||
@ -417,10 +414,7 @@ describe('MixinSignatureValidator', () => {
|
||||
it('should return false when SignatureType=Trezor and signature is invalid', async () => {
|
||||
// Create Trezor signature
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix(
|
||||
orderHashHex,
|
||||
MessagePrefixType.Trezor,
|
||||
);
|
||||
const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix(orderHashHex, SignerType.Trezor);
|
||||
const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
|
||||
// Create 0x signature from Trezor signature
|
||||
|
@ -36,6 +36,7 @@ describe(ContractName.Forwarder, () => {
|
||||
let feeRecipientAddress: string;
|
||||
let otherAddress: string;
|
||||
let defaultMakerAssetAddress: string;
|
||||
let zrxAssetData: string;
|
||||
|
||||
let weth: DummyERC20TokenContract;
|
||||
let zrxToken: DummyERC20TokenContract;
|
||||
@ -90,7 +91,7 @@ describe(ContractName.Forwarder, () => {
|
||||
erc20Wrapper.addDummyTokenContract(weth);
|
||||
|
||||
const wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address);
|
||||
const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
|
||||
zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
|
||||
const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
artifacts.Exchange,
|
||||
provider,
|
||||
@ -722,25 +723,18 @@ describe(ContractName.Forwarder, () => {
|
||||
);
|
||||
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should not change balances if the amount of ETH sent is too low to fill the makerAssetAmount', async () => {
|
||||
it('should revert if the amount of ETH sent is too low to fill the makerAssetAmount', async () => {
|
||||
const ordersWithoutFee = [orderWithoutFee];
|
||||
const feeOrders: SignedOrder[] = [];
|
||||
const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
|
||||
const ethValue = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(4);
|
||||
|
||||
tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
|
||||
value: ethValue,
|
||||
from: takerAddress,
|
||||
});
|
||||
const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||
const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||
|
||||
const totalEthSpent = gasPrice.times(tx.gasUsed);
|
||||
|
||||
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
||||
expect(newBalances).to.deep.equal(erc20Balances);
|
||||
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
return expectTransactionFailedAsync(
|
||||
forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
|
||||
value: ethValue,
|
||||
from: takerAddress,
|
||||
}),
|
||||
RevertReason.CompleteFillFailed,
|
||||
);
|
||||
});
|
||||
it('should buy an ERC721 asset from a single order', async () => {
|
||||
const makerAssetId = erc721MakerAssetIds[0];
|
||||
@ -775,7 +769,7 @@ describe(ContractName.Forwarder, () => {
|
||||
);
|
||||
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should buy an ERC721 asset and ignore later orders with different makerAssetData', async () => {
|
||||
it('should revert if buying an ERC721 asset when later orders contain different makerAssetData', async () => {
|
||||
const makerAssetId = erc721MakerAssetIds[0];
|
||||
orderWithoutFee = await orderFactory.newSignedOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
@ -786,33 +780,12 @@ describe(ContractName.Forwarder, () => {
|
||||
const feeOrders: SignedOrder[] = [];
|
||||
const makerAssetFillAmount = new BigNumber(1).plus(differentMakerAssetDataOrder.makerAssetAmount);
|
||||
const ethValue = orderWithFee.takerAssetAmount;
|
||||
|
||||
tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
|
||||
from: takerAddress,
|
||||
value: ethValue,
|
||||
});
|
||||
const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||
const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
||||
const newOwner = await erc721Token.ownerOf.callAsync(makerAssetId);
|
||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||
|
||||
const primaryTakerAssetFillAmount = ethValue;
|
||||
const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
|
||||
expect(newOwner).to.be.bignumber.equal(takerAddress);
|
||||
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
||||
expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
|
||||
erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
|
||||
);
|
||||
expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
|
||||
erc20Balances[makerAddress][defaultMakerAssetAddress],
|
||||
);
|
||||
expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
|
||||
erc20Balances[takerAddress][defaultMakerAssetAddress],
|
||||
return expectTransactionFailedAsync(
|
||||
forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
|
||||
value: ethValue,
|
||||
from: takerAddress,
|
||||
}),
|
||||
RevertReason.CompleteFillFailed,
|
||||
);
|
||||
});
|
||||
it('should buy an ERC721 asset and pay ZRX fees from a single fee order', async () => {
|
||||
@ -998,6 +971,26 @@ describe(ContractName.Forwarder, () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('withdrawAsset', () => {
|
||||
it('should allow owner to withdraw ERC20 tokens', async () => {
|
||||
const zrxWithdrawAmount = erc20Balances[forwarderContract.address][zrxToken.address];
|
||||
await forwarderWrapper.withdrawAssetAsync(zrxAssetData, zrxWithdrawAmount, { from: owner });
|
||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||
expect(newBalances[owner][zrxToken.address]).to.be.bignumber.equal(
|
||||
erc20Balances[owner][zrxToken.address].plus(zrxWithdrawAmount),
|
||||
);
|
||||
expect(newBalances[forwarderContract.address][zrxToken.address]).to.be.bignumber.equal(
|
||||
erc20Balances[forwarderContract.address][zrxToken.address].minus(zrxWithdrawAmount),
|
||||
);
|
||||
});
|
||||
it('should revert if not called by owner', async () => {
|
||||
const zrxWithdrawAmount = erc20Balances[forwarderContract.address][zrxToken.address];
|
||||
await expectTransactionFailedAsync(
|
||||
forwarderWrapper.withdrawAssetAsync(zrxAssetData, zrxWithdrawAmount, { from: makerAddress }),
|
||||
RevertReason.OnlyContractOwner,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
||||
// tslint:enable:no-unnecessary-type-assertion
|
||||
|
@ -8,7 +8,7 @@ import { ExchangeContract } from '../../generated_contract_wrappers/exchange';
|
||||
import { formatters } from './formatters';
|
||||
import { LogDecoder } from './log_decoder';
|
||||
import { orderUtils } from './order_utils';
|
||||
import { OrderInfo, SignedTransaction } from './types';
|
||||
import { FillResults, OrderInfo, SignedTransaction } from './types';
|
||||
|
||||
export class ExchangeWrapper {
|
||||
private readonly _exchange: ExchangeContract;
|
||||
@ -243,4 +243,27 @@ export class ExchangeWrapper {
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
public async getFillOrderResultsAsync(
|
||||
signedOrder: SignedOrder,
|
||||
from: string,
|
||||
opts: { takerAssetFillAmount?: BigNumber } = {},
|
||||
): Promise<FillResults> {
|
||||
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
||||
const fillResults = await this._exchange.fillOrder.callAsync(
|
||||
params.order,
|
||||
params.takerAssetFillAmount,
|
||||
params.signature,
|
||||
{ from },
|
||||
);
|
||||
return fillResults;
|
||||
}
|
||||
public abiEncodeFillOrder(signedOrder: SignedOrder, opts: { takerAssetFillAmount?: BigNumber } = {}): string {
|
||||
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
||||
const data = this._exchange.fillOrder.getABIEncodedTransactionData(
|
||||
params.order,
|
||||
params.takerAssetFillAmount,
|
||||
params.signature,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import * as _ from 'lodash';
|
||||
import 'make-promises-safe';
|
||||
|
||||
import { ExchangeContract, ExchangeFillEventArgs } from '../../generated_contract_wrappers/exchange';
|
||||
import { TestLibsContract } from '../../generated_contract_wrappers/test_libs';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
import { expectTransactionFailedAsync } from './assertions';
|
||||
@ -123,6 +124,8 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
exchangeContract.address,
|
||||
);
|
||||
|
||||
const testLibsContract = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults);
|
||||
|
||||
const fillOrderCombinatorialUtils = new FillOrderCombinatorialUtils(
|
||||
orderFactory,
|
||||
ownerAddress,
|
||||
@ -132,6 +135,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
zrxAssetData,
|
||||
exchangeWrapper,
|
||||
assetWrapper,
|
||||
testLibsContract,
|
||||
);
|
||||
return fillOrderCombinatorialUtils;
|
||||
}
|
||||
@ -145,6 +149,7 @@ export class FillOrderCombinatorialUtils {
|
||||
public zrxAssetData: string;
|
||||
public exchangeWrapper: ExchangeWrapper;
|
||||
public assetWrapper: AssetWrapper;
|
||||
public testLibsContract: TestLibsContract;
|
||||
public static generateFillOrderCombinations(): FillScenario[] {
|
||||
const takerScenarios = [
|
||||
TakerScenario.Unspecified,
|
||||
@ -329,6 +334,7 @@ export class FillOrderCombinatorialUtils {
|
||||
zrxAssetData: string,
|
||||
exchangeWrapper: ExchangeWrapper,
|
||||
assetWrapper: AssetWrapper,
|
||||
testLibsContract: TestLibsContract,
|
||||
) {
|
||||
this.orderFactory = orderFactory;
|
||||
this.ownerAddress = ownerAddress;
|
||||
@ -338,6 +344,7 @@ export class FillOrderCombinatorialUtils {
|
||||
this.zrxAssetData = zrxAssetData;
|
||||
this.exchangeWrapper = exchangeWrapper;
|
||||
this.assetWrapper = assetWrapper;
|
||||
this.testLibsContract = testLibsContract;
|
||||
}
|
||||
public async testFillOrderScenarioAsync(
|
||||
provider: Provider,
|
||||
@ -410,6 +417,8 @@ export class FillOrderCombinatorialUtils {
|
||||
lazyStore,
|
||||
fillRevertReasonIfExists,
|
||||
);
|
||||
|
||||
await this._abiEncodeFillOrderAndAssertOutcomeAsync(signedOrder, takerAssetFillAmount);
|
||||
}
|
||||
private async _fillOrderAndAssertOutcomeAsync(
|
||||
signedOrder: SignedOrder,
|
||||
@ -456,6 +465,29 @@ export class FillOrderCombinatorialUtils {
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.makerAssetAmount,
|
||||
);
|
||||
const expMakerFeePaid = orderUtils.getPartialAmount(
|
||||
expFilledTakerAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.makerFee,
|
||||
);
|
||||
const expTakerFeePaid = orderUtils.getPartialAmount(
|
||||
expFilledTakerAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.takerFee,
|
||||
);
|
||||
const fillResults = await this.exchangeWrapper.getFillOrderResultsAsync(signedOrder, this.takerAddress, {
|
||||
takerAssetFillAmount,
|
||||
});
|
||||
expect(fillResults.takerAssetFilledAmount).to.be.bignumber.equal(
|
||||
expFilledTakerAmount,
|
||||
'takerAssetFilledAmount',
|
||||
);
|
||||
expect(fillResults.makerAssetFilledAmount).to.be.bignumber.equal(
|
||||
expFilledMakerAmount,
|
||||
'makerAssetFilledAmount',
|
||||
);
|
||||
expect(fillResults.takerFeePaid).to.be.bignumber.equal(expTakerFeePaid, 'takerFeePaid');
|
||||
expect(fillResults.makerFeePaid).to.be.bignumber.equal(expMakerFeePaid, 'makerFeePaid');
|
||||
|
||||
// - Let's fill the order!
|
||||
const txReceipt = await this.exchangeWrapper.fillOrderAsync(signedOrder, this.takerAddress, {
|
||||
@ -479,17 +511,7 @@ export class FillOrderCombinatorialUtils {
|
||||
expFilledTakerAmount,
|
||||
'log.args.takerAssetFilledAmount',
|
||||
);
|
||||
const expMakerFeePaid = orderUtils.getPartialAmount(
|
||||
expFilledTakerAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.makerFee,
|
||||
);
|
||||
expect(log.args.makerFeePaid).to.be.bignumber.equal(expMakerFeePaid, 'log.args.makerFeePaid');
|
||||
const expTakerFeePaid = orderUtils.getPartialAmount(
|
||||
expFilledTakerAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.takerFee,
|
||||
);
|
||||
expect(log.args.takerFeePaid).to.be.bignumber.equal(expTakerFeePaid, 'logs.args.takerFeePaid');
|
||||
expect(log.args.orderHash).to.be.equal(orderHash, 'log.args.orderHash');
|
||||
expect(log.args.makerAssetData).to.be.equal(makerAssetData, 'log.args.makerAssetData');
|
||||
@ -571,6 +593,19 @@ export class FillOrderCombinatorialUtils {
|
||||
'ZRXAssetBalanceOfFeeRecipient',
|
||||
);
|
||||
}
|
||||
private async _abiEncodeFillOrderAndAssertOutcomeAsync(
|
||||
signedOrder: SignedOrder,
|
||||
takerAssetFillAmount: BigNumber,
|
||||
): Promise<void> {
|
||||
const params = orderUtils.createFill(signedOrder, takerAssetFillAmount);
|
||||
const expectedAbiEncodedData = this.exchangeWrapper.abiEncodeFillOrder(signedOrder, { takerAssetFillAmount });
|
||||
const libsAbiEncodedData = await this.testLibsContract.publicAbiEncodeFillOrder.callAsync(
|
||||
params.order,
|
||||
params.takerAssetFillAmount,
|
||||
params.signature,
|
||||
);
|
||||
expect(libsAbiEncodedData).to.be.equal(expectedAbiEncodedData, 'ABIEncodedFillOrderData');
|
||||
}
|
||||
private async _getTakerAssetFillAmountAsync(
|
||||
signedOrder: SignedOrder,
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario,
|
||||
|
@ -106,12 +106,12 @@ export class ForwarderWrapper {
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
public async withdrawERC20Async(
|
||||
tokenAddress: string,
|
||||
public async withdrawAssetAsync(
|
||||
assetData: string,
|
||||
amount: BigNumber,
|
||||
txData: TxDataPayable,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txHash = await this._forwarderContract.withdrawERC20.sendTransactionAsync(tokenAddress, amount, txData);
|
||||
const txHash = await this._forwarderContract.withdrawAsset.sendTransactionAsync(assetData, amount, txData);
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1534210131,
|
||||
"version": "1.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.3",
|
||||
"changes": [
|
||||
|
@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.4 - _August 13, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.3 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -17,7 +21,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0 - _July 20, 2018_
|
||||
## v1.0.0 - _July 19, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@ -43,7 +47,7 @@ CHANGELOG
|
||||
* Pass SolCompilerArtifactAdapter to CoverageSubprovider (#589)
|
||||
* Move callbackErrorReporter over from 0x.js (#579)
|
||||
|
||||
## v0.4.1 - _May 5, 2018_
|
||||
## v0.4.1 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/dev-utils",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -29,27 +29,27 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/dev-utils/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/subproviders": "^1.0.4",
|
||||
"@0xproject/types": "^1.0.1-rc.3",
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/web3-wrapper": "^1.1.2",
|
||||
"ethereum-types": "^1.0.3",
|
||||
"lodash": "^4.17.4"
|
||||
"@0xproject/subproviders": "^1.0.5",
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"@0xproject/web3-wrapper": "^1.2.0",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1534210131,
|
||||
"version": "1.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1532614997,
|
||||
"version": "1.0.3",
|
||||
|
@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.4 - _August 13, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.3 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -17,11 +21,11 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0 - _July 20, 2018_
|
||||
## v1.0.0 - _July 19, 2018_
|
||||
|
||||
* Add `TraceParams` interface for `debug_traceTransaction` parameters (#675)
|
||||
* Add `TransactionReceiptStatus` type (#812)
|
||||
|
||||
## v0.0.2 - _June 1, 2018_
|
||||
## v0.0.2 - _May 31, 2018_
|
||||
|
||||
* Initial publish (#642)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ethereum-types",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -30,12 +30,12 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/ethereum-types/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"copyfiles": "^1.2.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^8.0.53",
|
||||
|
@ -1,4 +1,18 @@
|
||||
[
|
||||
{
|
||||
"version": "1.0.1-rc.3",
|
||||
"changes": [
|
||||
{
|
||||
"note":
|
||||
"Updated to use latest orderFactory interface, fixed `feeRecipient` spelling error in public interface",
|
||||
"pr": 936
|
||||
},
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1534210131
|
||||
},
|
||||
{
|
||||
"version": "1.0.1-rc.2",
|
||||
"changes": [
|
||||
|
@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.1-rc.3 - _August 13, 2018_
|
||||
|
||||
* Updated to use latest orderFactory interface, fixed `feeRecipient` spelling error in public interface (#936)
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.1-rc.2 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -17,7 +22,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0-rc.1 - _July 20, 2018_
|
||||
## v1.0.0-rc.1 - _July 19, 2018_
|
||||
|
||||
* Make fill-scenarios compatible with V2 of 0x protocol (#656)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/fill-scenarios",
|
||||
"version": "1.0.1-rc.2",
|
||||
"version": "1.0.1-rc.3",
|
||||
"description": "0x order fill scenario generator",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@ -27,27 +27,27 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/fill-scenarios/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/abi-gen": "^1.0.4",
|
||||
"@0xproject/sol-compiler": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/abi-gen": "^1.0.5",
|
||||
"@0xproject/sol-compiler": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"copyfiles": "^1.2.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/base-contract": "^1.0.4",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.2",
|
||||
"@0xproject/types": "^1.0.1-rc.3",
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/web3-wrapper": "^1.1.2",
|
||||
"ethereum-types": "^1.0.3",
|
||||
"@0xproject/base-contract": "^2.0.0-rc.1",
|
||||
"@0xproject/order-utils": "^1.0.1-rc.3",
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"@0xproject/web3-wrapper": "^1.2.0",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"ethers": "3.0.22",
|
||||
"lodash": "^4.17.4"
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -62,7 +62,7 @@ export class FillScenarios {
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
feeRecepientAddress: string,
|
||||
feeRecipientAddress: string,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
@ -74,7 +74,7 @@ export class FillScenarios {
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
feeRecepientAddress,
|
||||
feeRecipientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
@ -89,7 +89,7 @@ export class FillScenarios {
|
||||
): Promise<SignedOrder> {
|
||||
const makerFee = new BigNumber(0);
|
||||
const takerFee = new BigNumber(0);
|
||||
const feeRecepientAddress = constants.NULL_ADDRESS;
|
||||
const feeRecipientAddress = constants.NULL_ADDRESS;
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
@ -99,7 +99,7 @@ export class FillScenarios {
|
||||
takerAddress,
|
||||
makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
feeRecepientAddress,
|
||||
feeRecipientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
@ -149,7 +149,7 @@ export class FillScenarios {
|
||||
takerAddress: string,
|
||||
makerFillableAmount: BigNumber,
|
||||
takerFillableAmount: BigNumber,
|
||||
feeRecepientAddress: string,
|
||||
feeRecipientAddress: string,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(makerAssetData);
|
||||
@ -195,17 +195,19 @@ export class FillScenarios {
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(
|
||||
this._web3Wrapper.getProvider(),
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
senderAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerFillableAmount,
|
||||
makerAssetData,
|
||||
takerFillableAmount,
|
||||
takerAssetData,
|
||||
this._exchangeAddress,
|
||||
feeRecepientAddress,
|
||||
expirationTimeSeconds,
|
||||
{
|
||||
takerAddress,
|
||||
senderAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
feeRecipientAddress,
|
||||
expirationTimeSeconds,
|
||||
},
|
||||
);
|
||||
return signedOrder;
|
||||
}
|
||||
|
@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"version": "1.0.1-rc.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Allow for additional properties in txData schema",
|
||||
"pr": 938
|
||||
},
|
||||
{
|
||||
"note": "Change hexSchema to match `0x`",
|
||||
"pr": 937
|
||||
},
|
||||
{
|
||||
"note": "Upgrade Relayer API schemas for relayer API V2",
|
||||
"pr": 916
|
||||
}
|
||||
],
|
||||
"timestamp": 1534210131
|
||||
},
|
||||
{
|
||||
"version": "1.0.1-rc.3",
|
||||
"changes": [
|
||||
|
@ -5,6 +5,12 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.1-rc.4 - _August 13, 2018_
|
||||
|
||||
* Allow for additional properties in txData schema (#938)
|
||||
* Change hexSchema to match `0x` (#937)
|
||||
* Upgrade Relayer API schemas for relayer API V2 (#916)
|
||||
|
||||
## v1.0.1-rc.3 - _July 26, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
@ -21,7 +27,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0-rc.1 - _July 20, 2018_
|
||||
## v1.0.0-rc.1 - _July 19, 2018_
|
||||
|
||||
* Update schemas for V2 or 0x Protocol (#615)
|
||||
* Added CallData schema (#821)
|
||||
@ -47,7 +53,7 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.7.23 - _May 5, 2018_
|
||||
## v0.7.23 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/json-schemas",
|
||||
"version": "1.0.1-rc.3",
|
||||
"version": "1.0.1-rc.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -38,14 +38,14 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/json-schemas/README.md",
|
||||
"dependencies": {
|
||||
"@0xproject/typescript-typings": "^1.0.3",
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
"@types/node": "^8.0.53",
|
||||
"jsonschema": "^1.2.0",
|
||||
"lodash.values": "^4.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.4",
|
||||
"@0xproject/utils": "^1.0.4",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@0xproject/utils": "^1.0.5",
|
||||
"@types/lodash.foreach": "^4.5.3",
|
||||
"@types/lodash.values": "^4.3.3",
|
||||
"@types/mocha": "^2.2.42",
|
||||
@ -54,13 +54,13 @@
|
||||
"dirty-chai": "^2.0.1",
|
||||
"lodash.foreach": "^4.5.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.7.1"
|
||||
"typescript": "2.9.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,17 +1,17 @@
|
||||
export const addressSchema = {
|
||||
id: '/Address',
|
||||
id: '/addressSchema',
|
||||
type: 'string',
|
||||
pattern: '^0x[0-9a-f]{40}$',
|
||||
};
|
||||
|
||||
export const hexSchema = {
|
||||
id: '/Hex',
|
||||
id: '/hexSchema',
|
||||
type: 'string',
|
||||
pattern: '^0x([0-9a-f][0-9a-f])+$',
|
||||
pattern: '^0x(([0-9a-f][0-9a-f])+)?$',
|
||||
};
|
||||
|
||||
export const numberSchema = {
|
||||
id: '/Number',
|
||||
id: '/numberSchema',
|
||||
type: 'string',
|
||||
pattern: '^\\d+(\\.\\d+)?$',
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
export const blockParamSchema = {
|
||||
id: '/BlockParam',
|
||||
id: '/blockParamSchema',
|
||||
oneOf: [
|
||||
{
|
||||
type: 'number',
|
||||
@ -11,10 +11,10 @@ export const blockParamSchema = {
|
||||
};
|
||||
|
||||
export const blockRangeSchema = {
|
||||
id: '/BlockRange',
|
||||
id: '/blockRangeSchema',
|
||||
properties: {
|
||||
fromBlock: { $ref: '/BlockParam' },
|
||||
toBlock: { $ref: '/BlockParam' },
|
||||
fromBlock: { $ref: '/blockParamSchema' },
|
||||
toBlock: { $ref: '/blockParamSchema' },
|
||||
},
|
||||
type: 'object',
|
||||
};
|
||||
|
@ -1,16 +1,16 @@
|
||||
export const callDataSchema = {
|
||||
id: '/CallData',
|
||||
id: '/callDataSchema',
|
||||
properties: {
|
||||
from: { $ref: '/Address' },
|
||||
to: { $ref: '/Address' },
|
||||
from: { $ref: '/addressSchema' },
|
||||
to: { $ref: '/addressSchema' },
|
||||
value: {
|
||||
oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }],
|
||||
oneOf: [{ $ref: '/numberSchema' }, { $ref: '/jsNumber' }],
|
||||
},
|
||||
gas: {
|
||||
oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }],
|
||||
oneOf: [{ $ref: '/numberSchema' }, { $ref: '/jsNumber' }],
|
||||
},
|
||||
gasPrice: {
|
||||
oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }],
|
||||
oneOf: [{ $ref: '/numberSchema' }, { $ref: '/jsNumber' }],
|
||||
},
|
||||
data: {
|
||||
type: 'string',
|
||||
|
@ -1,5 +1,5 @@
|
||||
export const ecSignatureParameterSchema = {
|
||||
id: '/ECSignatureParameter',
|
||||
id: '/ecSignatureParameterSchema',
|
||||
type: 'string',
|
||||
pattern: '^0[xX][0-9A-Fa-f]{64}$',
|
||||
};
|
||||
@ -12,8 +12,8 @@ export const ecSignatureSchema = {
|
||||
minimum: 27,
|
||||
maximum: 28,
|
||||
},
|
||||
r: { $ref: '/ECSignatureParameter' },
|
||||
s: { $ref: '/ECSignatureParameter' },
|
||||
r: { $ref: '/ecSignatureParameterSchema' },
|
||||
s: { $ref: '/ecSignatureParameterSchema' },
|
||||
},
|
||||
required: ['v', 'r', 's'],
|
||||
type: 'object',
|
||||
|
@ -1,7 +1,7 @@
|
||||
export const indexFilterValuesSchema = {
|
||||
id: '/IndexFilterValues',
|
||||
id: '/indexFilterValuesSchema',
|
||||
additionalProperties: {
|
||||
oneOf: [{ $ref: '/Number' }, { $ref: '/Address' }, { $ref: '/OrderHashSchema' }],
|
||||
oneOf: [{ $ref: '/numberSchema' }, { $ref: '/addressSchema' }, { $ref: '/orderHashSchema' }],
|
||||
},
|
||||
type: 'object',
|
||||
};
|
||||
|
@ -1,10 +1,10 @@
|
||||
export const orderCancellationRequestsSchema = {
|
||||
id: '/OrderCancellationRequests',
|
||||
id: '/orderCancellationRequestsSchema',
|
||||
type: 'array',
|
||||
items: {
|
||||
properties: {
|
||||
order: { $ref: '/Order' },
|
||||
takerTokenCancelAmount: { $ref: '/Number' },
|
||||
order: { $ref: '/orderSchema' },
|
||||
takerTokenCancelAmount: { $ref: '/numberSchema' },
|
||||
},
|
||||
required: ['order', 'takerTokenCancelAmount'],
|
||||
type: 'object',
|
||||
|
@ -1,10 +1,10 @@
|
||||
export const orderFillOrKillRequestsSchema = {
|
||||
id: '/OrderFillOrKillRequests',
|
||||
id: '/orderFillOrKillRequestsSchema',
|
||||
type: 'array',
|
||||
items: {
|
||||
properties: {
|
||||
signedOrder: { $ref: '/SignedOrder' },
|
||||
fillTakerAmount: { $ref: '/Number' },
|
||||
signedOrder: { $ref: '/signedOrderSchema' },
|
||||
fillTakerAmount: { $ref: '/numberSchema' },
|
||||
},
|
||||
required: ['signedOrder', 'fillTakerAmount'],
|
||||
type: 'object',
|
||||
|
@ -1,10 +1,10 @@
|
||||
export const orderFillRequestsSchema = {
|
||||
id: '/OrderFillRequests',
|
||||
id: '/orderFillRequestsSchema',
|
||||
type: 'array',
|
||||
items: {
|
||||
properties: {
|
||||
signedOrder: { $ref: '/SignedOrder' },
|
||||
takerTokenFillAmount: { $ref: '/Number' },
|
||||
signedOrder: { $ref: '/signedOrderSchema' },
|
||||
takerTokenFillAmount: { $ref: '/numberSchema' },
|
||||
},
|
||||
required: ['signedOrder', 'takerTokenFillAmount'],
|
||||
type: 'object',
|
||||
|
@ -1,5 +1,5 @@
|
||||
export const orderHashSchema = {
|
||||
id: '/OrderHashSchema',
|
||||
id: '/orderHashSchema',
|
||||
type: 'string',
|
||||
pattern: '^0x[0-9a-fA-F]{64}$',
|
||||
};
|
||||
|
@ -1,19 +1,19 @@
|
||||
export const orderSchema = {
|
||||
id: '/Order',
|
||||
id: '/orderSchema',
|
||||
properties: {
|
||||
makerAddress: { $ref: '/Address' },
|
||||
takerAddress: { $ref: '/Address' },
|
||||
makerFee: { $ref: '/Number' },
|
||||
takerFee: { $ref: '/Number' },
|
||||
senderAddress: { $ref: '/Address' },
|
||||
makerAssetAmount: { $ref: '/Number' },
|
||||
takerAssetAmount: { $ref: '/Number' },
|
||||
makerAssetData: { $ref: '/Hex' },
|
||||
takerAssetData: { $ref: '/Hex' },
|
||||
salt: { $ref: '/Number' },
|
||||
exchangeAddress: { $ref: '/Address' },
|
||||
feeRecipientAddress: { $ref: '/Address' },
|
||||
expirationTimeSeconds: { $ref: '/Number' },
|
||||
makerAddress: { $ref: '/addressSchema' },
|
||||
takerAddress: { $ref: '/addressSchema' },
|
||||
makerFee: { $ref: '/numberSchema' },
|
||||
takerFee: { $ref: '/numberSchema' },
|
||||
senderAddress: { $ref: '/addressSchema' },
|
||||
makerAssetAmount: { $ref: '/numberSchema' },
|
||||
takerAssetAmount: { $ref: '/numberSchema' },
|
||||
makerAssetData: { $ref: '/hexSchema' },
|
||||
takerAssetData: { $ref: '/hexSchema' },
|
||||
salt: { $ref: '/numberSchema' },
|
||||
exchangeAddress: { $ref: '/addressSchema' },
|
||||
feeRecipientAddress: { $ref: '/addressSchema' },
|
||||
expirationTimeSeconds: { $ref: '/numberSchema' },
|
||||
},
|
||||
required: [
|
||||
'makerAddress',
|
||||
@ -34,12 +34,12 @@ export const orderSchema = {
|
||||
};
|
||||
|
||||
export const signedOrderSchema = {
|
||||
id: '/SignedOrder',
|
||||
id: '/signedOrderSchema',
|
||||
allOf: [
|
||||
{ $ref: '/Order' },
|
||||
{ $ref: '/orderSchema' },
|
||||
{
|
||||
properties: {
|
||||
signature: { $ref: '/Hex' },
|
||||
signature: { $ref: '/hexSchema' },
|
||||
},
|
||||
required: ['signature'],
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
export const ordersSchema = {
|
||||
id: '/ordersSchema',
|
||||
type: 'array',
|
||||
items: { $ref: '/Order' },
|
||||
items: { $ref: '/orderSchema' },
|
||||
};
|
||||
|
10
packages/json-schemas/schemas/paginated_collection_schema.ts
Normal file
10
packages/json-schemas/schemas/paginated_collection_schema.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export const paginatedCollectionSchema = {
|
||||
id: '/paginatedCollectionSchema',
|
||||
type: 'object',
|
||||
properties: {
|
||||
total: { type: 'number' },
|
||||
perPage: { type: 'number' },
|
||||
page: { type: 'number' },
|
||||
},
|
||||
required: ['total', 'perPage', 'page'],
|
||||
};
|
@ -0,0 +1,38 @@
|
||||
export const relayerApiAssetDataPairsResponseSchema = {
|
||||
id: '/relayerApiAssetDataPairsResponseSchema',
|
||||
type: 'object',
|
||||
allOf: [
|
||||
{ $ref: '/paginatedCollectionSchema' },
|
||||
{
|
||||
properties: {
|
||||
records: { $ref: '/relayerApiAssetDataPairsSchema' },
|
||||
},
|
||||
required: ['records'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const relayerApiAssetDataPairsSchema = {
|
||||
id: '/relayerApiAssetDataPairsSchema',
|
||||
type: 'array',
|
||||
items: {
|
||||
properties: {
|
||||
assetDataA: { $ref: '/relayerApiAssetDataTradeInfoSchema' },
|
||||
assetDataB: { $ref: '/relayerApiAssetDataTradeInfoSchema' },
|
||||
},
|
||||
required: ['assetDataA', 'assetDataB'],
|
||||
type: 'object',
|
||||
},
|
||||
};
|
||||
|
||||
export const relayerApiAssetDataTradeInfoSchema = {
|
||||
id: '/relayerApiAssetDataTradeInfoSchema',
|
||||
type: 'object',
|
||||
properties: {
|
||||
assetData: { $ref: '/hexSchema' },
|
||||
minAmount: { $ref: '/numberSchema' },
|
||||
maxAmount: { $ref: '/numberSchema' },
|
||||
precision: { type: 'number' },
|
||||
},
|
||||
required: ['assetData'],
|
||||
};
|
@ -1,8 +1,8 @@
|
||||
export const relayerApiErrorResponseSchema = {
|
||||
id: '/RelayerApiErrorResponse',
|
||||
id: '/relayerApiErrorResponseSchema',
|
||||
type: 'object',
|
||||
properties: {
|
||||
code: { type: 'number' },
|
||||
code: { type: 'integer', minimum: 100, maximum: 103 },
|
||||
reason: { type: 'string' },
|
||||
validationErrors: {
|
||||
type: 'array',
|
||||
@ -10,7 +10,7 @@ export const relayerApiErrorResponseSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
field: { type: 'string' },
|
||||
code: { type: 'number' },
|
||||
code: { type: 'integer', minimum: 1000, maximum: 1006 },
|
||||
reason: { type: 'string' },
|
||||
},
|
||||
required: ['field', 'code', 'reason'],
|
||||
|
@ -0,0 +1,13 @@
|
||||
export const relayerApiFeeRecipientsResponseSchema = {
|
||||
id: '/relayerApiFeeRecipientsResponseSchema',
|
||||
type: 'object',
|
||||
allOf: [
|
||||
{ $ref: '/paginatedCollectionSchema' },
|
||||
{
|
||||
properties: {
|
||||
records: { $ref: '/addressSchema' },
|
||||
},
|
||||
required: ['records'],
|
||||
},
|
||||
],
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
export const relayerApiFeesPayloadSchema = {
|
||||
id: '/RelayerApiFeesPayload',
|
||||
type: 'object',
|
||||
properties: {
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
maker: { $ref: '/Address' },
|
||||
taker: { $ref: '/Address' },
|
||||
makerTokenAddress: { $ref: '/Address' },
|
||||
takerTokenAddress: { $ref: '/Address' },
|
||||
makerTokenAmount: { $ref: '/Number' },
|
||||
takerTokenAmount: { $ref: '/Number' },
|
||||
expirationUnixTimestampSec: { $ref: '/Number' },
|
||||
salt: { $ref: '/Number' },
|
||||
},
|
||||
required: [
|
||||
'exchangeContractAddress',
|
||||
'maker',
|
||||
'taker',
|
||||
'makerTokenAddress',
|
||||
'takerTokenAddress',
|
||||
'expirationUnixTimestampSec',
|
||||
'salt',
|
||||
],
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
export const relayerApiFeesResponseSchema = {
|
||||
id: '/RelayerApiFeesResponse',
|
||||
type: 'object',
|
||||
properties: {
|
||||
makerFee: { $ref: '/Number' },
|
||||
takerFee: { $ref: '/Number' },
|
||||
feeRecipient: { $ref: '/Address' },
|
||||
},
|
||||
required: ['makerFee', 'takerFee', 'feeRecipient'],
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
export const relayerApiOrderbookChannelSubscribeSchema = {
|
||||
id: '/RelayerApiOrderbookChannelSubscribe',
|
||||
type: 'object',
|
||||
properties: {
|
||||
type: { enum: ['subscribe'] },
|
||||
channel: { enum: ['orderbook'] },
|
||||
requestId: { type: 'number' },
|
||||
payload: { $ref: '/RelayerApiOrderbookChannelSubscribePayload' },
|
||||
},
|
||||
required: ['type', 'channel', 'requestId', 'payload'],
|
||||
};
|
||||
|
||||
export const relayerApiOrderbookChannelSubscribePayload = {
|
||||
id: '/RelayerApiOrderbookChannelSubscribePayload',
|
||||
type: 'object',
|
||||
properties: {
|
||||
baseTokenAddress: { $ref: '/Address' },
|
||||
quoteTokenAddress: { $ref: '/Address' },
|
||||
snapshot: { type: 'boolean' },
|
||||
limit: { type: 'number' },
|
||||
},
|
||||
required: ['baseTokenAddress', 'quoteTokenAddress'],
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
export const relayerApiOrderConfigPayloadSchema = {
|
||||
id: '/relayerApiOrderConfigPayloadSchema',
|
||||
type: 'object',
|
||||
properties: {
|
||||
makerAddress: { $ref: '/addressSchema' },
|
||||
takerAddress: { $ref: '/addressSchema' },
|
||||
makerAssetAmount: { $ref: '/numberSchema' },
|
||||
takerAssetAmount: { $ref: '/numberSchema' },
|
||||
makerAssetData: { $ref: '/hexSchema' },
|
||||
takerAssetData: { $ref: '/hexSchema' },
|
||||
exchangeAddress: { $ref: '/addressSchema' },
|
||||
expirationTimeSeconds: { $ref: '/numberSchema' },
|
||||
},
|
||||
required: [
|
||||
'makerAddress',
|
||||
'takerAddress',
|
||||
'makerAssetAmount',
|
||||
'takerAssetAmount',
|
||||
'makerAssetData',
|
||||
'takerAssetData',
|
||||
'exchangeAddress',
|
||||
'expirationTimeSeconds',
|
||||
],
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
export const relayerApiOrderConfigResponseSchema = {
|
||||
id: '/relayerApiOrderConfigResponseSchema',
|
||||
type: 'object',
|
||||
properties: {
|
||||
makerFee: { $ref: '/numberSchema' },
|
||||
takerFee: { $ref: '/numberSchema' },
|
||||
feeRecipientAddress: { $ref: '/addressSchema' },
|
||||
senderAddress: { $ref: '/addressSchema' },
|
||||
},
|
||||
required: ['makerFee', 'takerFee', 'feeRecipientAddress', 'senderAddress'],
|
||||
};
|
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