From 32ab4dcac723e189ce8a1be796f0539975a48eae Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 15:52:30 -0400 Subject: Implement rate utils --- packages/order-utils/src/index.ts | 1 + packages/order-utils/src/rate_utils.ts | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 packages/order-utils/src/rate_utils.ts diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index 858f500c6..a52f936b6 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -33,3 +33,4 @@ export { EIP712Utils } from './eip712_utils'; export { OrderValidationUtils } from './order_validation_utils'; export { ExchangeTransferSimulator } from './exchange_transfer_simulator'; export { marketUtils } from './market_utils'; +export { rateUtils } from './rate_utils'; diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts new file mode 100644 index 000000000..212431e0c --- /dev/null +++ b/packages/order-utils/src/rate_utils.ts @@ -0,0 +1,44 @@ +import { schemas } from '@0xproject/json-schemas'; +import { SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; + +import { assert } from './assert'; +import { constants } from './constants'; + +export const rateUtils = { + /** + * Takes a signed order and calculates the fee adjusted rate (takerAsset/makerAsset) by calculating how much takerAsset + * is required to cover the fees (feeRate * takerFee), adding the takerAssetAmount and dividing by makerAssetAmount + * @param signedOrder An object that conforms to the signedOrder interface + * @param feeRate The market rate of ZRX denominated in takerAssetAmount + * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) + * @return The rate (takerAsset/makerAsset) of the order adjusted for fees + */ + getFeeAdjustedRateOfOrder(signedOrder: SignedOrder, feeRate: BigNumber): BigNumber { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isBigNumber('feeRate', feeRate); + assert.assert(feeRate.greaterThan(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than 0`); + const takerAssetAmountNeededToPayForFees = signedOrder.takerFee.mul(feeRate); + const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(signedOrder.takerAssetAmount); + const rate = totalTakerAssetAmount.div(signedOrder.makerAssetAmount); + return rate; + }, + /** + * Takes a signed fee order (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) and calculates + * the fee adjusted rate (WETH/ZRX) by dividing the takerAssetAmount by the makerAmount minus the takerFee + * @param signedFeeOrder An object that conforms to the signedOrder interface + * @return The rate (WETH/ZRX) of the fee order adjusted for fees + */ + getFeeAdjustedRateOfFeeOrder(signedFeeOrder: SignedOrder): BigNumber { + assert.doesConformToSchema('signedFeeOrder', signedFeeOrder, schemas.signedOrderSchema); + const zrxAmountAfterFees = signedFeeOrder.makerAssetAmount.sub(signedFeeOrder.takerFee); + assert.assert( + zrxAmountAfterFees.greaterThan(constants.ZERO_AMOUNT), + `Expected takerFee: ${JSON.stringify( + signedFeeOrder.takerFee, + )} to be less than makerAssetAmount: ${JSON.stringify(signedFeeOrder.makerAssetAmount)}`, + ); + const rate = signedFeeOrder.takerAssetAmount.div(zrxAmountAfterFees); + return rate; + }, +}; -- cgit From a1860b076d9d3408e64d8ff5e6bc0657e9ff7e7b Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 17:24:08 -0400 Subject: Add tests for rateUtils --- packages/order-utils/test/rate_utils_test.ts | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 packages/order-utils/test/rate_utils_test.ts diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts new file mode 100644 index 000000000..2f321a7db --- /dev/null +++ b/packages/order-utils/test/rate_utils_test.ts @@ -0,0 +1,55 @@ +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import 'mocha'; + +import { constants, rateUtils } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { testOrderFactory } from './utils/test_order_factory'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('rateUtils', () => { + const testOrder = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerAssetAmount: new BigNumber(100), + takerFee: new BigNumber(20), + }); + describe('#getFeeAdjustedRateOfOrder', () => { + it('throws when feeRate is zero', async () => { + const feeRate = constants.ZERO_AMOUNT; + expect(() => rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate)).to.throw( + 'Expected feeRate: 0 to be greater than 0', + ); + }); + it('throws when feeRate is less than zero', async () => { + const feeRate = new BigNumber(-1); + expect(() => rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate)).to.throw( + 'Expected feeRate: -1 to be greater than 0', + ); + }); + it('correctly calculates fee adjusted rate', async () => { + const feeRate = new BigNumber(2); // ZRX costs 2 units of takerAsset per 1 unit of ZRX + const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate); + // the order actually takes 100 + (2 * 20) takerAsset units to fill 100 units of makerAsset + expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.4)); + }); + }); + describe('#getFeeAdjustedRateOfFeeOrder', () => { + it('throws when takerFee exceeds makerAssetAmount', async () => { + const badOrder = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerFee: new BigNumber(101), + }); + expect(() => rateUtils.getFeeAdjustedRateOfFeeOrder(badOrder)).to.throw( + 'Expected takerFee: "101" to be less than makerAssetAmount: "100"', + ); + }); + it('correctly calculates fee adjusted rate', async () => { + const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfFeeOrder(testOrder); + // the order actually takes 100 takerAsset units to fill (100 - 20) units of makerAsset + expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.25)); + }); + }); +}); -- cgit From c0924d8067079f246c5cad32f7acb3d1f6cfd9b9 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 17:49:22 -0400 Subject: Implement sorting utils --- packages/order-utils/src/index.ts | 1 + packages/order-utils/src/sorting_utils.ts | 69 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 packages/order-utils/src/sorting_utils.ts diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index a52f936b6..359954641 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -34,3 +34,4 @@ export { OrderValidationUtils } from './order_validation_utils'; export { ExchangeTransferSimulator } from './exchange_transfer_simulator'; export { marketUtils } from './market_utils'; export { rateUtils } from './rate_utils'; +export { sortingUtils } from './sorting_utils'; diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts new file mode 100644 index 000000000..7474a302f --- /dev/null +++ b/packages/order-utils/src/sorting_utils.ts @@ -0,0 +1,69 @@ +import { schemas } from '@0xproject/json-schemas'; +import { SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; + +import { assert } from './assert'; +import { constants } from './constants'; +import { rateUtils } from './rate_utils'; + +export const sortingUtils = { + /** + * Takes an array of signed orders and sorts them by takerAsset/makerAsset rate in ascending order (best rate first). + * Adjusts the rate of each order according to the feeRate and takerFee for that order. + * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. + * @param feeRate The market rate of ZRX denominated in takerAssetAmount + * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) + * @return The input orders sorted by rate in ascending order + */ + sortOrdersByFeeAdjustedRate(signedOrders: SignedOrder[], feeRate: BigNumber): SignedOrder[] { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('feeRate', feeRate); + assert.assert(feeRate.greaterThan(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than 0`); + const rateCalculator = (signedOrder: SignedOrder) => rateUtils.getFeeAdjustedRateOfOrder(signedOrder, feeRate); + const sortedOrders = sortOrders(signedOrders, rateCalculator); + return sortedOrders; + }, + /** + * Takes an array of signed fee orders (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) + * and sorts them by rate in ascending order (best rate first). Adjusts the rate according to the takerFee. + * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. + * @return The input orders sorted by rate in ascending order + */ + sortFeeOrdersByFeeAdjustedRate(signedFeeOrders: SignedOrder[]): SignedOrder[] { + assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder; + const sortedOrders = sortOrders(signedFeeOrders, rateCalculator); + return sortedOrders; + }, +}; + +type RateCalculator = (signedOrder: SignedOrder) => BigNumber; + +// takes an array of orders, copies them, and sorts the copy based on the rate definition provided by rateCalculator +const sortOrders = (signedOrders: SignedOrder[], rateCalculator: RateCalculator): SignedOrder[] => { + const copiedOrders = _.cloneDeep(signedOrders); + const feeOrderComparator = getOrderComparator(rateCalculator); + copiedOrders.sort(feeOrderComparator); + return copiedOrders; +}; + +type Comparator = (first: T, second: T) => number; + +// takes a function that calculates rate for a signed order and returns a comparator that sorts based on rate +const getOrderComparator = (rateCalculator: RateCalculator): Comparator => ( + firstSignedOrder, + secondSignedOrder, +) => { + const firstOrderRate = rateCalculator(firstSignedOrder); + const secondOrderRate = rateCalculator(secondSignedOrder); + if (firstOrderRate.lt(secondOrderRate)) { + return -1; + } else if (firstOrderRate.gt(secondOrderRate)) { + return 1; + } else { + return 0; + } +}; -- cgit From fcd57d2743e4b6a1363b8071696147a91d2afb00 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 18:43:31 -0400 Subject: Add tests for sortingUtils --- packages/order-utils/src/sorting_utils.ts | 1 - packages/order-utils/test/sorting_utils_test.ts | 66 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 packages/order-utils/test/sorting_utils_test.ts diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts index 7474a302f..2acd8180f 100644 --- a/packages/order-utils/src/sorting_utils.ts +++ b/packages/order-utils/src/sorting_utils.ts @@ -20,7 +20,6 @@ export const sortingUtils = { sortOrdersByFeeAdjustedRate(signedOrders: SignedOrder[], feeRate: BigNumber): SignedOrder[] { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('feeRate', feeRate); - assert.assert(feeRate.greaterThan(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than 0`); const rateCalculator = (signedOrder: SignedOrder) => rateUtils.getFeeAdjustedRateOfOrder(signedOrder, feeRate); const sortedOrders = sortOrders(signedOrders, rateCalculator); return sortedOrders; diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts new file mode 100644 index 000000000..efce13d3f --- /dev/null +++ b/packages/order-utils/test/sorting_utils_test.ts @@ -0,0 +1,66 @@ +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'mocha'; + +import { constants, rateUtils, sortingUtils } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { testOrderFactory } from './utils/test_order_factory'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('sortingUtils', () => { + describe('#sortOrdersByFeeAdjustedRate', () => { + // rate: 2 takerAsset / makerAsset + const testOrder1 = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerAssetAmount: new BigNumber(200), + }); + // rate: 1 takerAsset / makerAsset + const testOrder2 = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerAssetAmount: new BigNumber(100), + }); + // rate: 2.5 takerAsset / makerAsset + const testOrder3 = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerAssetAmount: new BigNumber(200), + takerFee: new BigNumber(50), + }); + it('correctly sorts by fee adjusted rate', async () => { + const feeRate = new BigNumber(1); // ZRX costs 1 unit of takerAsset per 1 unit of ZRX + const orders = [testOrder1, testOrder2, testOrder3]; + const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate( + [testOrder1, testOrder2, testOrder3], + feeRate, + ); + expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]); + }); + }); + describe('#sortFeeOrdersByFeeAdjustedRate', () => { + // rate: 200 takerAsset / makerAsset + const testOrder1 = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerAssetAmount: new BigNumber(200), + takerFee: new BigNumber(99), + }); + // rate: 1 takerAsset / makerAsset + const testOrder2 = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerAssetAmount: new BigNumber(100), + }); + // rate: 4 takerAsset / makerAsset + const testOrder3 = testOrderFactory.generateTestSignedOrder({ + makerAssetAmount: new BigNumber(100), + takerAssetAmount: new BigNumber(200), + takerFee: new BigNumber(50), + }); + it('correctly sorts by fee adjusted# # KNOBS -- A list of popular knobs and their descriptions # # $FreeBSD$ # # Rules for adding knobs: # # - Knob name must be 12 characters or less # - Knob description must be 45 characters or less # # - Naming knobs: # When a port has a lib-prefix (e.g.: libquicktime, libxine) # the lib-prefix should be stripped from the knob name # (e.g.: QUICKTIME, XINE). # # Keep this list sorted in alphabetical order. # # Knob name: Knob description: # Length | | Length | A52 ATSC A/52 audio decoding (used in most DVDs) AALIB Adds aalib support ADS Adds Asyncronous DNS Support ALSA Adds ALSA support APACHE Include support for APACHE_PORT ARTS aRts support via the KDE sound daemon ASPELL Use Aspell (textproc/aspell) for spell checking ATLAS Use ATLAS instead of BLAS/LAPACK AUDIOFILE Adds audiofile support AVAHI Adds Avahi support AVIFILE Adds support for AVI multimedia BDB Adds Berkeley DB Support BLAS Use BLAS instead of ATLAS CACA Libcaca colored ASCII graphics CAIRO Adds CAIRO support CDDB CDDB support CDPARANOIA Support for cdparanoia CD extraction CGI Adds CGI support CJK Chinese, Japanese, and Korean language support CLAMAV Adds clamav support CLIENT Client component of a client/server package CLIENT_ONLY Client component of a client/server package COMPILE Do not use the pre-compiled .jar files CUPS CUPS (Common Unix Printing System) support CURL cURL generic file transfer library support DBUS Adds support for D-Bus (Desktop Bus) DEBUG Enables debugging support DEDICATED Enables dedicated server DOCS Install documentation DOXYGEN Build Doxygen documentation DTS DTS coherent acoustics decoding (some DVDs) DV Digital Video used by many digital camcorders DVD Enables general DVD support DVDNAV Enables DVD Menu support DVDREAD Enables DVD support EJABBERD Adds support for the ejabberd jabber server EMACS Adds support for Emacs ESOUND Adds support for EsounD EXAMPLES Installs optional example code, graphics, etc. EXIF Support EXIF headers in JPEG and TIFF files FAAC FAAC AAC and MP4 audio encoder support FAAD FAAD AAC and MP4 audio decoder support FAM Adds File Alteration Monitor support FASTCGI Adds FastCGI support FFMPEG Enables FFMPEG support FIREBIRD Firebird (Interbase) database support FPING Adds fping support FREETYPE Adds Freetype support FRIBIDI Adds fribidi support FLAC Flac audio support FORTRAN Adds FORTRAN support GCONF Use GConf/GConf2 GD Adds support for gd GDBM Use gdbm db instead of system bdb GEOIP Adds GeoIP support GETTEXT Adds GetText support GHC Prefer/use Glasgow Haskell Compiler GHOSTSCRIPT Adds ghostscript support GIF Adds GIF support GL Adds OpenGL support GLX Adds OpenGL support GMP Adds GMP support GNOME Adds GNOME support GNUTLS Adds GnuTLS support GPGME Use security/gpgme for PGP support GRAPHVIZ Adds graphviz support GSASL Adds GSASL support GSM GSM audio codec support GSSAPI GSSAPI (Kerberos) support GSTREAMER GStreamer multimedia support GTK Adds Gtk support GTK1 Adds Gtk+1 support GTK2 Adds Gtk+2 support GTKSPELL Enable Spell checking through GTKSpell GUI Enable Graphical User Interface H323 Adds support for the H323 protocol HAL Adds support for HAL HEIMDAL_KRB5 Adds Heimdal kerberos support ICU Use ICU for unicode collation IDN Adds support for International Domain Names IMAGEMAGICK ImageMagick graphics support IMAP Adds support for IMAP mail protocol IMLIB Adds imlib support IODBC Use iODBC as the ODBC driver IPV6 IPv6 internet protocol support IRC Adds IRC support ISPELL Use textproc/ispell for spell checking JABBER Adds support for the Jabber protocol JACK Adds suppor for the JACK Audio Connection Kit JAVA Adds support for Java JOYSTICK Adds joystick support JPEG Adds JPEG support KDE Adds KDE support KDE4 Adds KDE4 support KERBEROS Adds Kerberos support LAME LAME MP3 audio encoder support LADSPA Adds LADSPA support LDAP Adds LDAP support LIGHTTPD Adds lighttpd support LINUX Adds support for Linux LINUXTHREADS Use the linuxthreads pthread library LIRC Adds LIRC support LIVEMEDIA LiveMedia rstp/rtp/sdp support LUA Lua scripting support LZO LZO data compression support MAD Mad MP3 audio decoder support MANPAGES Build and install man pages MIT_KRB5 Adds MIT kerberos support MATROSKA Matroska multimedia container support MIKMOD Adds mikmod support MILTER Adds milter support MMAP Enables MMAP support MMX Adds support for x86 MMX optimizations MODPERL2 Use www/mod_perl2 port MODPYTHON3 Use www/mod_python3 port MOTIF Adds MOTIF support MOZILLA Adds Mozilla support MP3 Adds MP3 support MP4 Adds MP4 support MPEG4IP MPEG4 multimedia support MPG123 Adds mpg123 support MPI Use MPI MPLAYER Adds Mplayer support MSN Adds support for the MSN protocol MSSQL Adds MSSQL Support MUSEPACK Musepack (MPC, musicpd, libmpcdec) support MYSQL MySQL database support NAS Adds support for NAS (Network Audio Sound) NCURSES Adds ncurses console graphics support NETCDF Adds NetCDF support NHC98 Prefer/use nhc98 Haskell compiler NIS Support for NIS/YP NLS Native Language Support via gettext utilities NOTIFY Adds support for libnotify NOUVEAU Use MesaLib 7.4.4/libdrm 2.4.12 with xf86-video-nouveau NTLM Adds NTLM support NVIDIA Adds support for the nvidia driver NVIDIA_GL Use libGL provided by NVidia binary drivers ODBC Adds ODBC support OGG OGG multimedia container format OPENAL Adds OpenAL support OPENGL Adds OpenGL support OPENLDAP Adds OpenLDAP support OPENMPI Adds OpenMPI support OPENSSL Adds OpenSSL support OPTIMIZATION Build with optimizations OPTIMIZED_CFLAGS Enables optimized CFLAGS OPTIMIZED_FLAGS Enables optimized compiler flags ORACLE Adds Oracle database support OSS Adds support for the Open Sound System PAM Adds PAM support PCRE Adds PCRE support PDF Adds PDF support PERL Adds Perl language/module support PGO Enables Profile-Guided Optimization PGSQL PostgreSQL database support PHP Adds PHP support PLUGIN Enables building of plugin PLUGINS Enables building of plugins PNG Adds PNG support POP3 Adds support for POP3 mail protocol PORTAUDIO Adds Portaudio support POSTFIX Adds support for the Postfix mta PSYCO Adds Python Psyco optimization support PTHREADS Enable pthreads support PULSEAUDIO Adds support for the PulseAudio sound server PYTHON Adds Python language/module support QT Adds Qt support QT4 Adds Qt4 support QUOTA Adds support for quotas QUICKTIME QuickTime audio/video support RADIUS Adds RADIUS support READLINE Adds Readline support REPLACE_BASE Replace base software with this version RUBY Adds Ruby language/module support SAMBA Adds SAMBA support SAMPLERATE Adds support for libsamplerate SASL Adds SASL support SASL2 Adds SASL2 support SASLKRB5 Adds SASL Kerberos5 support SDL Adds support for SDL media library SERVER Server component of a client/server package SIEVE Adds Sieve support SIGCHASE Adds DNSSEC validation support SIMD Enable x86 SIMD (3DNow!/MMX) SLANG Adds display/screen management via S-Lang SLP Adds SLP (Service Locator Protocol) support SMP Adds Symetric MultiProcessor support SNDFILE Adds support for libsndfile SNMP Adds SNMP support SOCKS Adds SOCKS support SOUND Adds sound support SOX SoX audio support SPAMASSASSIN Adds Spamassassin support SPEEX Speex audio codec support SQLITE SQLite embedded SQL database support SSE Adds support for x86 SSE optimizations SSE2 Adds support for x86 SSE2 optimizations SSH Adds support for SSH SSL Adds support for SSL (Secure Socket Layer) STATIC Build statically linked executables SUBVERSION Adds Subversion support SUID Install with setuid bit set SVGALIB Adds SVGALib support SVG Adds SVG support SYSLOG Adds Syslog support TAGLIB Adds Taglib support TCL Adds TCL support TCP_WRAPPERS Adds TCP-Wrappers support TEST Enable tests THEORA Theora video codec support THREADS Enable threads support TIFF Adds TIFF support TLS Adds TLS support TOOLS Install additional tools TRACING Enable tracing TREMOR Tremor (integer-only Vorbis) audio support UNICODE Adds unicode support UNIXODBC Use UnixODBC as the ODBC driver USB Adds devel/libusb support for USB devices V4L Adds Video 4 Linux support VIDEO Enable video support VORBIS OGG/Vorbis audio support WAVPACK Adds WAVPACK support WX wxWidgets (formerly wxWindows) support X11 Support for X11 X264 H.264/AVC (MPEG4 part 10) multimedia codec X86_ASM Enables assembly code (i386 only) XAW3D Adds XAW3D support XFT Adds XFT support XIM Adds XIM support XINE XINE multimedia support XINERAMA Adds Xinerama support XML Adds XML support through libxml XMMS Adds XMMS support XPM Adds XPM support XVID XVID multimedia MPEG4 codec support YAHOO Adds Yahoo! Messenger Protocol support ZIP Adds ZIP support ZLIB Adds Zlib support ZVBI Adds support to access raw VBI capture devices ls/test_order_factory'; diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts index 5a33cb2ca..016432505 100644 --- a/packages/order-utils/test/sorting_utils_test.ts +++ b/packages/order-utils/test/sorting_utils_test.ts @@ -1,9 +1,8 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; -import * as _ from 'lodash'; import 'mocha'; -import { constants, rateUtils, sortingUtils } from '../src'; +import { sortingUtils } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { testOrderFactory } from './utils/test_order_factory'; @@ -32,15 +31,12 @@ describe('sortingUtils', () => { }); it('correctly sorts by fee adjusted rate when feeRate is Provided', async () => { const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate( - [testOrder1, testOrder2, testOrder3], - feeRate, - ); + const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders, feeRate); expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]); }); it('correctly sorts by fee adjusted rate when no feeRate is Provided', async () => { const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate([testOrder1, testOrder2, testOrder3]); + const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders); expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]); }); }); @@ -64,7 +60,7 @@ describe('sortingUtils', () => { }); it('correctly sorts by fee adjusted rate', async () => { const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate([testOrder1, testOrder2, testOrder3]); + const sortedOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate(orders); expect(sortedOrders).to.deep.equal([testOrder2, testOrder3, testOrder1]); }); }); -- cgit From ab64ea7377b4cd0a0a7e3ec219f958037c5fabbe Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 19:20:07 -0400 Subject: Updated CHANGELOG --- packages/order-utils/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index fa82976ad..ee0030b6b 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -13,6 +13,10 @@ }, { "note": "Dependencies updated" + }, + { + "note": "Added rateUtils and sortingUtils", + "pr": 953 } ] }, -- cgit From d8593998414aa3234533b8fa868b05495ac54457 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 13 Aug 2018 17:45:50 -0700 Subject: Change rateUtils to use Order --- packages/order-utils/src/rate_utils.ts | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts index e82c03873..c9ca72c59 100644 --- a/packages/order-utils/src/rate_utils.ts +++ b/packages/order-utils/src/rate_utils.ts @@ -1,5 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; -import { SignedOrder } from '@0xproject/types'; +import { Order } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { assert } from './assert'; @@ -7,42 +7,42 @@ import { constants } from './constants'; export const rateUtils = { /** - * Takes a signed order and calculates the fee adjusted rate (takerAsset/makerAsset) by calculating how much takerAsset + * Takes an order and calculates the fee adjusted rate (takerAsset/makerAsset) by calculating how much takerAsset * is required to cover the fees (feeRate * takerFee), adding the takerAssetAmount and dividing by makerAssetAmount - * @param signedOrder An object that conforms to the signedOrder interface - * @param feeRate The market rate of ZRX denominated in takerAssetAmount - * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) - * Defaults to 0 + * @param order An object that conforms to the order interface + * @param feeRate The market rate of ZRX denominated in takerAssetAmount + * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) + * Defaults to 0 * @return The rate (takerAsset/makerAsset) of the order adjusted for fees */ - getFeeAdjustedRateOfOrder(signedOrder: SignedOrder, feeRate: BigNumber = constants.ZERO_AMOUNT): BigNumber { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + getFeeAdjustedRateOfOrder(order: Order, feeRate: BigNumber = constants.ZERO_AMOUNT): BigNumber { + assert.doesConformToSchema('order', order, schemas.orderSchema); assert.isBigNumber('feeRate', feeRate); assert.assert( feeRate.gte(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than or equal to 0`, ); - const takerAssetAmountNeededToPayForFees = signedOrder.takerFee.mul(feeRate); - const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(signedOrder.takerAssetAmount); - const rate = totalTakerAssetAmount.div(signedOrder.makerAssetAmount); + const takerAssetAmountNeededToPayForFees = order.takerFee.mul(feeRate); + const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(order.takerAssetAmount); + const rate = totalTakerAssetAmount.div(order.makerAssetAmount); return rate; }, /** - * Takes a signed fee order (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) and calculates + * Takes a fee order (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) and calculates * the fee adjusted rate (WETH/ZRX) by dividing the takerAssetAmount by the makerAmount minus the takerFee - * @param signedFeeOrder An object that conforms to the signedOrder interface + * @param feeOrder An object that conforms to the order interface * @return The rate (WETH/ZRX) of the fee order adjusted for fees */ - getFeeAdjustedRateOfFeeOrder(signedFeeOrder: SignedOrder): BigNumber { - assert.doesConformToSchema('signedFeeOrder', signedFeeOrder, schemas.signedOrderSchema); - const zrxAmountAfterFees = signedFeeOrder.makerAssetAmount.sub(signedFeeOrder.takerFee); + getFeeAdjustedRateOfFeeOrder(feeOrder: Order): BigNumber { + assert.doesConformToSchema('feeOrder', feeOrder, schemas.orderSchema); + const zrxAmountAfterFees = feeOrder.makerAssetAmount.sub(feeOrder.takerFee); assert.assert( zrxAmountAfterFees.greaterThan(constants.ZERO_AMOUNT), - `Expected takerFee: ${JSON.stringify( - signedFeeOrder.takerFee, - )} to be less than makerAssetAmount: ${JSON.stringify(signedFeeOrder.makerAssetAmount)}`, + `Expected takerFee: ${JSON.stringify(feeOrder.takerFee)} to be less than makerAssetAmount: ${JSON.stringify( + feeOrder.makerAssetAmount, + )}`, ); - const rate = signedFeeOrder.takerAssetAmount.div(zrxAmountAfterFees); + const rate = feeOrder.takerAssetAmount.div(zrxAmountAfterFees); return rate; }, }; -- cgit From 99b744ba52f538752bb0966e6d8b50d9f5a2f032 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 13 Aug 2018 18:31:41 -0700 Subject: Update sortingUtils to support Order and SignedOrder --- packages/order-utils/src/sorting_utils.ts | 70 ++++++++++++------------------- 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts index f019aa4a8..8811bcaf8 100644 --- a/packages/order-utils/src/sorting_utils.ts +++ b/packages/order-utils/src/sorting_utils.ts @@ -1,5 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; -import { SignedOrder } from '@0xproject/types'; +import { Order } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -9,64 +9,46 @@ import { rateUtils } from './rate_utils'; export const sortingUtils = { /** - * Takes an array of signed orders and sorts them by takerAsset/makerAsset rate in ascending order (best rate first). + * Takes an array of orders and sorts them by takerAsset/makerAsset rate in ascending order (best rate first). * Adjusts the rate of each order according to the feeRate and takerFee for that order. - * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param feeRate The market rate of ZRX denominated in takerAssetAmount - * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) - * Defaults to 0 + * @param orders An array of objects that extend the Order interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. + * @param feeRate The market rate of ZRX denominated in takerAssetAmount + * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) + * Defaults to 0 * @return The input orders sorted by rate in ascending order */ - sortOrdersByFeeAdjustedRate( - signedOrders: SignedOrder[], - feeRate: BigNumber = constants.ZERO_AMOUNT, - ): SignedOrder[] { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + sortOrdersByFeeAdjustedRate(orders: T[], feeRate: BigNumber = constants.ZERO_AMOUNT): T[] { + assert.doesConformToSchema('orders', orders, schemas.ordersSchema); assert.isBigNumber('feeRate', feeRate); - const rateCalculator = (signedOrder: SignedOrder) => rateUtils.getFeeAdjustedRateOfOrder(signedOrder, feeRate); - const sortedOrders = sortOrders(signedOrders, rateCalculator); + const rateCalculator = (order: Order) => rateUtils.getFeeAdjustedRateOfOrder(order, feeRate); + const sortedOrders = sortOrders(orders, rateCalculator); return sortedOrders; }, /** - * Takes an array of signed fee orders (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) + * Takes an array of fee orders (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) * and sorts them by rate in ascending order (best rate first). Adjusts the rate according to the takerFee. - * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. + * @param feeOrders An array of objects that extend the Order interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. * @return The input orders sorted by rate in ascending order */ - sortFeeOrdersByFeeAdjustedRate(signedFeeOrders: SignedOrder[]): SignedOrder[] { - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + sortFeeOrdersByFeeAdjustedRate(feeOrders: Order[]): Order[] { + assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema); const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder.bind(rateUtils); - const sortedOrders = sortOrders(signedFeeOrders, rateCalculator); + const sortedOrders = sortOrders(feeOrders, rateCalculator); return sortedOrders; }, }; -type RateCalculator = (signedOrder: SignedOrder) => BigNumber; +type RateCalculator = (order: Order) => BigNumber; // takes an array of orders, copies them, and sorts the copy based on the rate definition provided by rateCalculator -const sortOrders = (signedOrders: SignedOrder[], rateCalculator: RateCalculator): SignedOrder[] => { - const copiedOrders = _.cloneDeep(signedOrders); - const feeOrderComparator = getOrderComparator(rateCalculator); - copiedOrders.sort(feeOrderComparator); +function sortOrders(orders: T[], rateCalculator: RateCalculator): T[] { + const copiedOrders = _.cloneDeep(orders); + copiedOrders.sort((firstOrder, secondOrder) => { + const firstOrderRate = rateCalculator(firstOrder); + const secondOrderRate = rateCalculator(secondOrder); + return firstOrderRate.comparedTo(secondOrderRate); + }); return copiedOrders; -}; - -type Comparator = (first: T, second: T) => number; - -// takes a function that calculates rate for a signed order and returns a comparator that sorts based on rate -const getOrderComparator = (rateCalculator: RateCalculator): Comparator => ( - firstSignedOrder, - secondSignedOrder, -) => { - const firstOrderRate = rateCalculator(firstSignedOrder); - const secondOrderRate = rateCalculator(secondSignedOrder); - if (firstOrderRate.lt(secondOrderRate)) { - return -1; - } else if (firstOrderRate.gt(secondOrderRate)) { - return 1; - } else { - return 0; - } -}; +} -- cgit From dd7e03c7d7434e5fd5aa96812e773a69247b8546 Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 13 Aug 2018 18:46:54 -0700 Subject: Add defaults for networkId and pagination --- packages/sra-api/package.json | 2 +- packages/sra-api/public/api.json | 2 +- packages/sra-api/src/parameters.ts | 5 ++++- yarn.lock | 8 ++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/sra-api/package.json b/packages/sra-api/package.json index 4a8526a28..70e645c5b 100644 --- a/packages/sra-api/package.json +++ b/packages/sra-api/package.json @@ -33,7 +33,7 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/sra-api/README.md", "dependencies": { - "@0xproject/json-schemas": "1.0.1-rc.3" + "@0xproject/json-schemas": "^1.0.1-rc.3" }, "devDependencies": { "@0xproject/tslint-config": "^1.0.4", diff --git a/packages/sra-api/public/api.json b/packages/sra-api/public/api.json index 36b08ad1a..9c727cfbd 100644 --- a/packages/sra-api/public/api.json +++ b/packages/sra-api/public/api.json @@ -1 +1 @@ -{"openapi":"3.0.0","info":{"version":"2.0.0","title":"Standard Relayer REST API","description":"# Testing\n\nUse the [sra-report](https://github.com/0xProject/0x-monorepo/tree/development/packages/sra-report) command line tool to test your API for SRA compliance.\n\n# Schemas\n\nThe [JSON schemas](http://json-schema.org/) for the API payloads and responses can be found in [@0xproject/json-schemas](https://github.com/0xProject/0x.js/tree/development/packages/json-schemas). Examples of each payload and response can be found in the library's [test suite](https://github.com/0xProject/0x.js/blob/development/packages/json-schemas/test/schema_test.ts#L1).\n\n```bash\nnpm install @0xproject/json-schemas --save\n```\n\nYou can easily validate your API's payloads and responses using the [@0xproject/json-schemas](https://github.com/0xProject/0x.js/tree/development/packages/json-schemas) package:\n\n```js\nimport {SchemaValidator, ValidatorResult, schemas} from '@0xproject/json-schemas';\n\nconst {relayerApiTokenPairsResponseSchema} = schemas;\nconst validator = new SchemaValidator();\n\nconst tokenPairsResponse = {\n ...\n};\nconst validatorResult: ValidatorResult = validator.validate(tokenPairsResponse, relayerApiTokenPairsResponseSchema);\n```\n\n# Pagination\n\nRequests that return potentially large collections should respond to the **?page** and **?perPage** parameters. For example:\n\n```bash\n$ curl https://api.example-relayer.com/v2/asset_pairs?page=3&perPage=20\n```\n\nPage numbering should be 1-indexed, not 0-indexed. If a query provides an unreasonable (ie. too high) `perPage` value, the response can return a validation error as specified in the [errors section](#section/Errors). If the query specifies a `page` that does not exist (ie. there are not enough `records`), the response should just return an empty `records` array.\n\nAll endpoints that are paginated should return a `total`, `page`, `perPage` and a `records` value in the top level of the collection. The value of `total` should be the total number of records for a given query, whereas `records` should be an array representing the response to the query for that page. `page` and `perPage`, are the same values that were specified in the request. See the note in [miscellaneous](#section/Misc.) about formatting `snake_case` vs. `lowerCamelCase`.\n\nThese requests include the [`/v2/asset_pairs`](#operation/getAssetPairs), [`/v2/orders`](#operation/getOrders), [`/v2/fee_recipients`](#operation/getFeeRecipients) and [`/v2/orderbook`](#operation/getOrderbook) endpoints.\n\n# Network Id\n\nAll requests should be able to specify a **?networkId** query param for all supported networks. For example:\n\n```bash\n$ curl https://api.example-relayer.com/v2/asset_pairs?networkId=1\n```\n\nIf the query param is not provided, it should default to **1** (mainnet).\n\nNetworks and their Ids:\n\n| Network Id | Network Name |\n| ---------- | ------------ |\n| 1 | Mainnet |\n| 42 | Kovan |\n| 3 | Ropsten |\n| 4 | Rinkeby |\n\nIf a certain network is not supported, the response should **400** as specified in the [error response](#section/Errors) section. For example:\n\n```json\n{\n \"code\": 100,\n \"reason\": \"Validation failed\",\n \"validationErrors\": [\n {\n \"field\": \"networkId\",\n \"code\": 1006,\n \"reason\": \"Network id 42 is not supported\"\n }\n ]\n}\n```\n\n# Link Header\n\nA [Link Header](https://tools.ietf.org/html/rfc5988) can be included in a response to provide clients with more context about paging\nFor example:\n\n```bash\nLink: ; rel=\"next\",\n; rel=\"last\"\n```\n\nThis `Link` response header contains one or more Hypermedia link relations.\n\nThe possible `rel` values are:\n\n| Name | Description |\n| ----- | ------------------------------------------------------------- |\n| next | The link relation for the immediate next page of results. |\n| last | The link relation for the last page of results. |\n| first | The link relation for the first page of results. |\n| prev | The link relation for the immediate previous page of results. |\n\n# Rate Limits\n\nRate limit guidance for clients can be optionally returned in the response headers:\n\n| Header Name | Description |\n| --------------------- | ---------------------------------------------------------------------------- |\n| X-RateLimit-Limit | The maximum number of requests you're permitted to make per hour. |\n| X-RateLimit-Remaining | The number of requests remaining in the current rate limit window. |\n| X-RateLimit-Reset | The time at which the current rate limit window resets in UTC epoch seconds. |\n\nFor example:\n\n```bash\n$ curl -i https://api.example-relayer.com/v2/asset_pairs\nHTTP/1.1 200 OK\nDate: Mon, 20 Oct 2017 12:30:06 GMT\nStatus: 200 OK\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 56\nX-RateLimit-Reset: 1372700873\n```\n\nWhen a rate limit is exceeded, a status of **429 Too Many Requests** should be returned.\n\n# Errors\n\nUnless the spec defines otherwise, errors to bad requests should respond with HTTP 4xx or status codes.\n\n## Common error codes\n\n| Code | Reason |\n| ---- | --------------------------------------- |\n| 400 | Bad Request – Invalid request format |\n| 404 | Not found |\n| 429 | Too many requests - Rate limit exceeded |\n| 500 | Internal Server Error |\n| 501 | Not Implemented |\n\n## Error reporting format\n\nFor all **400** responses, see the [error response schema](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_error_response_schema.ts#L1).\n\n```json\n{\n \"code\": 101,\n \"reason\": \"Validation failed\",\n \"validationErrors\": [\n {\n \"field\": \"maker\",\n \"code\": 1002,\n \"reason\": \"Invalid address\"\n }\n ]\n}\n```\n\nGeneral error codes:\n\n```bash\n100 - Validation Failed\n101 - Malformed JSON\n102 - Order submission disabled\n103 - Throttled\n```\n\nValidation error codes:\n\n```bash\n1000 - Required field\n1001 - Incorrect format\n1002 - Invalid address\n1003 - Address not supported\n1004 - Value out of range\n1005 - Invalid signature or hash\n1006 - Unsupported option\n```\n\n# Asset Data Encoding\n\nAs we now support multiple [token transfer proxies](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxy), the identifier of which proxy to use for the token transfer must be encoded, along with the token information. Each proxy in 0x v2 has a unique identifier. If you're using 0x.js there will be helper methods for this [encoding](https://0xproject.com/docs/0x.js#zeroEx-encodeERC20AssetData) and [decoding](https://0xproject.com/docs/0x.js#zeroEx-decodeAssetProxyId).\n\nThe identifier for the Proxy uses a similar scheme to [ABI function selectors](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#function-selector).\n\n```js\n// ERC20 Proxy ID 0xf47261b0\nbytes4(keccak256('ERC20Token(address)'));\n// ERC721 Proxy ID 0x08e937fa\nbytes4(keccak256('ERC721Token(address,uint256)'));\n```\n\nAsset data is encoded using [ABI encoding](https://solidity.readthedocs.io/en/develop/abi-spec.html).\n\nFor example, encoding the ERC20 token contract (address: 0x1dc4c1cefef38a777b15aa20260a54e584b16c48) using the ERC20 Transfer Proxy (id: 0xf47261b0) would be:\n\n```bash\n0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48\n```\n\nEncoding the ERC721 token contract (address: `0x371b13d97f4bf77d724e78c16b7dc74099f40e84`), token id (id: `99`, which hex encoded is `0x63`) and the ERC721 Transfer Proxy (id: 0x08e937fa) would be:\n\n```bash\n0x08e937fa000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063\n```\n\nFor more information see [the Asset Proxy](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#erc20proxy) section of the v2 spec and the [Ethereum ABI Spec](https://solidity.readthedocs.io/en/develop/abi-spec.html).\n\n# Meta Data in Order Responses\n\nIn v2 of the standard relayer API we added the `metaData` field. It is meant to provide a standard place for relayers to put optional, custom or non-standard fields that may of interest to the consumer of the API.\n\nA good example of such a field is `remainingTakerAssetAmount`, which is a convenience field that communicates how much of a 0x order is potentially left to be filled. Unlike the other fields in a 0x order, it is not guaranteed to be correct as it is derived from whatever mechanism the implementer (ie. the relayer) is using. While convenient for prototyping and low stakes situations, we recommend validating the value of the field by checking the state of the blockchain yourself, such as by using [Order Watcher](https://0xproject.com/wiki#0x-OrderWatcher).\n\n# Misc.\n\n* All requests and responses should be of **application/json** content type\n* All token amounts are sent in amounts of the smallest level of precision (base units). (e.g if a token has 18 decimal places, selling 1 token would show up as selling `'1000000000000000000'` units by this API).\n* All addresses are sent as lower-case (non-checksummed) Ethereum addresses with the `0x` prefix.\n* All parameters are to be written in `lowerCamelCase`.\n","license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0.html"}},"paths":{"/v2/asset_pairs":{"get":{"description":"Retrieves a list of available asset pairs and the information required to trade them (in any order). Setting only `assetDataA` or `assetDataB` returns pairs filtered by that asset only.","operationId":"getAssetPairs","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number"}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number"}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number"}},{"name":"assetDataA","in":"query","description":"The assetData value for the first asset in the pair.","example":"0xf47261b04c32345ced77393b3530b1eed0f346429d","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"assetDataB","in":"query","description":"The assetData value for the second asset in the pair.","example":"0x0257179264389b814a946f3e92105513705ca6b990","schema":{"$ref":"#/components/schemas/hexSchema"}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"Returns a collection of available asset pairs with some meta info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiAssetDataPairsResponseSchema"},"example":{"total":43,"page":1,"perPage":100,"records":[{"assetDataA":{"minAmount":"0","maxAmount":"10000000000000000000","precision":5,"assetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d"},"assetDataB":{"minAmount":"0","maxAmount":"50000000000000000000","precision":5,"assetData":"0x0257179264389b814a946f3e92105513705ca6b990"}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/orders":{"get":{"description":"Retrieves a list of orders given query parameters. This endpoint should be [paginated](#section/Pagination). For querying an entire orderbook snapshot, the [orderbook endpoint](#operation/getOrderbook) is recommended. If both makerAssetData and takerAssetData are specified, returned orders will be sorted by price determined by (takerTokenAmount/makerTokenAmount) in ascending order. By default, orders returned by this endpoint are unsorted.","operationId":"getOrders","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number"}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number"}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number"}},{"name":"makerAssetProxyId","in":"query","description":"The maker [asset proxy id](https://0xproject.com/docs/0x.js#types-AssetProxyId) (example: \"0xf47261b0\" for ERC20, \"0x02571792\" for ERC721).","example":"0xf47261b0","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"takerAssetProxyId","in":"query","description":"The taker asset [asset proxy id](https://0xproject.com/docs/0x.js#types-AssetProxyId) (example: \"0xf47261b0\" for ERC20, \"0x02571792\" for ERC721).","example":"0x02571792","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"makerAssetAddress","in":"query","description":"The contract address for the maker asset.","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"takerAssetAddress","in":"query","description":"The contract address for the taker asset.","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"exchangeAddress","in":"query","description":"Same as exchangeAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"senderAddress","in":"query","description":"Same as senderAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"makerAssetData","in":"query","description":"Same as makerAssetData in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"takerAssetData","in":"query","description":"Same as takerAssetData in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"traderAssetData","in":"query","description":"Same as traderAssetData in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"makerAddress","in":"query","description":"Same as makerAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"traderAddress","in":"query","description":"Same as traderAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"feeRecipientAddress","in":"query","description":"Same as feeRecipientAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"A collection of 0x orders with meta-data as specified by query params","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrdersResponseSchema"},"example":{"total":984,"page":1,"perPage":100,"records":[{"order":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"},"metaData":{}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/order/{orderHash}":{"get":{"description":"Retrieves the 0x order with meta info that is associated with the hash.","operationId":"getOrder","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number"}},{"name":"orderHash","in":"path","description":"The hash of the desired 0x order.","example":"0xd4b103c42d2512eef3fee775e097f044291615d25f5d71e0ac70dbd49d223591","schema":{"$ref":"#/components/schemas/orderHashSchema"}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"The order and meta info associated with the orderHash","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderSchema"},"example":{"order":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"},"metaData":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/orderbook":{"get":{"description":"Retrieves the orderbook for a given asset pair. This endpoint should be [paginated](#section/Pagination). Bids will be sorted in descending order by price, and asks will be sorted in ascending order by price. Within the price sorted orders, the orders are further sorted by _taker fee price_ which is defined as the **takerFee** divided by **takerTokenAmount**. After _taker fee price_, orders are to be sorted by expiration in ascending order. The way pagination works for this endpoint is that the **page** and **perPage** query params apply to both `bids` and `asks` collections, and if `page` * `perPage` > `total` for a certain collection, the `records` for that collection should just be empty. ","operationId":"getOrderbook","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number"}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number"}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number"}},{"name":"baseAssetData","in":"query","description":"assetData (makerAssetData or takerAssetData) designated as the base currency in the [currency pair calculation](https://en.wikipedia.org/wiki/Currency_pair) of price.","required":true,"example":"0xf47261b04c32345ced77393b3530b1eed0f346429d","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"quoteAssetData","in":"query","description":"assetData (makerAssetData or takerAssetData) designated as the quote currency in the currency pair calculation of price (required).","required":true,"example":"0xf47261b04c32345ced77393b3530b1eed0f346429d","schema":{"$ref":"#/components/schemas/hexSchema"}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"The sorted order book for the specified asset pair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderbookResponseSchema"},"example":{"bids":{"total":325,"page":2,"perPage":100,"records":[{"order":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"},"metaData":{}}]},"asks":{"total":500,"page":2,"perPage":100,"records":[{"order":{"makerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","takerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"20000000000000000","takerAssetAmount":"10000000000000000","makerFee":"200000000000000","takerFee":"100000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","takerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x013842a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b3518891"},"metaData":{}}]}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/order_config":{"get":{"description":"Relayers have full discretion over the orders that they are willing to host on their orderbooks (e.g what fees they charge, etc...). In order for traders to discover their requirements programmatically, they can send an incomplete order to this endpoint and receive the missing fields, specifc to that order. This gives relayers a large amount of flexibility to tailor fees to unique traders, trading pairs and volume amounts. Submit a partial order and receive information required to complete the order: `senderAddress`, `feeRecipientAddress`, `makerFee`, `takerFee`. ","operationId":"getOrderConfig","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number"}}],"requestBody":{"description":"The fields of a 0x order the relayer may want to decide what configuration to send back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderConfigPayloadSchema"},"example":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","expirationTimeSeconds":"1532560590"}}}},"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"The additional fields necessary in order to submit an order to the relayer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderConfigResponseSchema"},"example":{"senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","makerFee":"100000000000000","takerFee":"200000000000000"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/fee_recipients":{"get":{"description":"Retrieves a collection of all fee recipient addresses for a relayer. This endpoint should be [paginated](#section/Pagination).","operationId":"getFeeRecipients","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number"}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number"}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number"}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"A collection of all used fee recipient addresses.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiFeeRecipientsResponseSchema"},"example":{"total":3,"page":1,"perPage":10,"records":["0x6eC92694ea172ebC430C30fa31De87620967A082","0x9e56625509c2f60af937f23b7b532600390e8c8b","0xa2b31dacf30a9c50ca473337c01d8a201ae33e32"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/order":{"post":{"description":"Submit a signed order to the relayer.","operationId":"postOrder","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number"}}],"requestBody":{"description":"A valid signed 0x order based on the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/signedOrderSchema"},"example":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"}}}},"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"OK","content":{}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}}},"components":{"schemas":{"numberSchema":{"type":"string","pattern":"^\\d+(\\.\\d+)?$"},"addressSchema":{"type":"string","pattern":"^0x[0-9a-f]{40}$"},"hexSchema":{"type":"string","pattern":"^0x(([0-9a-f][0-9a-f])+)?$"},"orderHashSchema":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$"},"orderSchema":{"properties":{"makerAddress":{"$ref":"#/components/schemas/addressSchema"},"takerAddress":{"$ref":"#/components/schemas/addressSchema"},"makerFee":{"$ref":"#/components/schemas/numberSchema"},"takerFee":{"$ref":"#/components/schemas/numberSchema"},"senderAddress":{"$ref":"#/components/schemas/addressSchema"},"makerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"takerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"makerAssetData":{"$ref":"#/components/schemas/hexSchema"},"takerAssetData":{"$ref":"#/components/schemas/hexSchema"},"salt":{"$ref":"#/components/schemas/numberSchema"},"exchangeAddress":{"$ref":"#/components/schemas/addressSchema"},"feeRecipientAddress":{"$ref":"#/components/schemas/addressSchema"},"expirationTimeSeconds":{"$ref":"#/components/schemas/numberSchema"}},"required":["makerAddress","takerAddress","makerFee","takerFee","senderAddress","makerAssetAmount","takerAssetAmount","makerAssetData","takerAssetData","salt","exchangeAddress","feeRecipientAddress","expirationTimeSeconds"],"type":"object"},"signedOrderSchema":{"allOf":[{"$ref":"#/components/schemas/orderSchema"},{"properties":{"signature":{"$ref":"#/components/schemas/hexSchema"}},"required":["signature"]}]},"signedOrdersSchema":{"type":"array","items":{"$ref":"#/components/schemas/signedOrderSchema"}},"ordersSchema":{"type":"array","items":{"$ref":"#/components/schemas/orderSchema"}},"paginatedCollectionSchema":{"type":"object","properties":{"total":{"type":"number"},"perPage":{"type":"number"},"page":{"type":"number"}},"required":["total","perPage","page"]},"relayerApiErrorResponseSchema":{"type":"object","properties":{"code":{"type":"integer","minimum":100,"maximum":103},"reason":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"code":{"type":"integer","minimum":1000,"maximum":1006},"reason":{"type":"string"}},"required":["field","code","reason"]}}},"required":["code","reason"]},"relayerApiFeeRecipientsResponseSchema":{"type":"object","allOf":[{"$ref":"#/components/schemas/paginatedCollectionSchema"},{"properties":{"records":{"$ref":"#/components/schemas/addressSchema"}},"required":["records"]}]},"relayerApiOrderSchema":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/orderSchema"},"metaData":{"type":"object"}},"required":["order","metaData"]},"relayerApiOrdersSchema":{"type":"array","items":{"$ref":"#/components/schemas/relayerApiOrderSchema"}},"relayerApiOrderConfigPayloadSchema":{"type":"object","properties":{"makerAddress":{"$ref":"#/components/schemas/addressSchema"},"takerAddress":{"$ref":"#/components/schemas/addressSchema"},"makerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"takerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"makerAssetData":{"$ref":"#/components/schemas/hexSchema"},"takerAssetData":{"$ref":"#/components/schemas/hexSchema"},"exchangeAddress":{"$ref":"#/components/schemas/addressSchema"},"expirationTimeSeconds":{"$ref":"#/components/schemas/numberSchema"}},"required":["makerAddress","takerAddress","makerAssetAmount","takerAssetAmount","makerAssetData","takerAssetData","exchangeAddress","expirationTimeSeconds"]},"relayerApiOrderConfigResponseSchema":{"type":"object","properties":{"makerFee":{"$ref":"#/components/schemas/numberSchema"},"takerFee":{"$ref":"#/components/schemas/numberSchema"},"feeRecipientAddress":{"$ref":"#/components/schemas/addressSchema"},"senderAddress":{"$ref":"#/components/schemas/addressSchema"}},"required":["makerFee","takerFee","feeRecipientAddress","senderAddress"]},"relayerApiOrderbookResponseSchema":{"type":"object","properties":{"bids":{"$ref":"#/components/schemas/relayerApiOrdersResponseSchema"},"asks":{"$ref":"#/components/schemas/relayerApiOrdersResponseSchema"}},"required":["bids","asks"]},"relayerApiAssetDataPairsResponseSchema":{"type":"object","allOf":[{"$ref":"#/components/schemas/paginatedCollectionSchema"},{"properties":{"records":{"$ref":"#/components/schemas/relayerApiAssetDataPairsSchema"}},"required":["records"]}]},"relayerApiAssetDataTradeInfoSchema":{"type":"object","properties":{"assetData":{"$ref":"#/components/schemas/hexSchema"},"minAmount":{"$ref":"#/components/schemas/numberSchema"},"maxAmount":{"$ref":"#/components/schemas/numberSchema"},"precision":{"type":"number"}},"required":["assetData"]},"relayerApiOrdersChannelSubscribeSchema":{"type":"object","properties":{"type":{"enum":["subscribe"]},"channel":{"enum":["orders"]},"requestId":{"type":"string"},"payload":{"$ref":"#/components/schemas/relayerApiOrdersChannelSubscribePayload"}},"required":["type","channel","requestId"]},"relayerApiOrdersChannelSubscribePayload":{"type":"object","properties":{"makerAssetProxyId":{"$ref":"#/components/schemas/hexSchema"},"takerAssetProxyId":{"$ref":"#/components/schemas/hexSchema"},"networkId":{"type":"number"},"makerAssetAddress":{"$ref":"#/components/schemas/addressSchema"},"takerAssetAddress":{"$ref":"#/components/schemas/addressSchema"},"makerAssetData":{"$ref":"#/components/schemas/hexSchema"},"takerAssetData":{"$ref":"#/components/schemas/hexSchema"},"traderAssetData":{"$ref":"#/components/schemas/hexSchema"}}},"relayerApiOrdersChannelUpdateSchema":{"type":"object","properties":{"type":{"enum":["update"]},"channel":{"enum":["orders"]},"requestId":{"type":"string"},"payload":{"$ref":"#/components/schemas/relayerApiOrdersSchema"}},"required":["type","channel","requestId"]},"relayerApiOrdersResponseSchema":{"type":"object","allOf":[{"$ref":"#/components/schemas/paginatedCollectionSchema"},{"properties":{"records":{"$ref":"#/components/schemas/relayerApiOrdersSchema"}},"required":["records"]}]},"relayerApiAssetDataPairsSchema":{"type":"array","items":{"properties":{"assetDataA":{"$ref":"#/components/schemas/relayerApiAssetDataTradeInfoSchema"},"assetDataB":{"$ref":"#/components/schemas/relayerApiAssetDataTradeInfoSchema"}},"required":["assetDataA","assetDataB"],"type":"object"}}}}} \ No newline at end of file +{"openapi":"3.0.0","info":{"version":"2.0.0","title":"Standard Relayer REST API","description":"# Testing\n\nUse the [sra-report](https://github.com/0xProject/0x-monorepo/tree/development/packages/sra-report) command line tool to test your API for SRA compliance.\n\n# Schemas\n\nThe [JSON schemas](http://json-schema.org/) for the API payloads and responses can be found in [@0xproject/json-schemas](https://github.com/0xProject/0x.js/tree/development/packages/json-schemas). Examples of each payload and response can be found in the library's [test suite](https://github.com/0xProject/0x.js/blob/development/packages/json-schemas/test/schema_test.ts#L1).\n\n```bash\nnpm install @0xproject/json-schemas --save\n```\n\nYou can easily validate your API's payloads and responses using the [@0xproject/json-schemas](https://github.com/0xProject/0x.js/tree/development/packages/json-schemas) package:\n\n```js\nimport {SchemaValidator, ValidatorResult, schemas} from '@0xproject/json-schemas';\n\nconst {relayerApiTokenPairsResponseSchema} = schemas;\nconst validator = new SchemaValidator();\n\nconst tokenPairsResponse = {\n ...\n};\nconst validatorResult: ValidatorResult = validator.validate(tokenPairsResponse, relayerApiTokenPairsResponseSchema);\n```\n\n# Pagination\n\nRequests that return potentially large collections should respond to the **?page** and **?perPage** parameters. For example:\n\n```bash\n$ curl https://api.example-relayer.com/v2/asset_pairs?page=3&perPage=20\n```\n\nPage numbering should be 1-indexed, not 0-indexed. If a query provides an unreasonable (ie. too high) `perPage` value, the response can return a validation error as specified in the [errors section](#section/Errors). If the query specifies a `page` that does not exist (ie. there are not enough `records`), the response should just return an empty `records` array.\n\nAll endpoints that are paginated should return a `total`, `page`, `perPage` and a `records` value in the top level of the collection. The value of `total` should be the total number of records for a given query, whereas `records` should be an array representing the response to the query for that page. `page` and `perPage`, are the same values that were specified in the request. See the note in [miscellaneous](#section/Misc.) about formatting `snake_case` vs. `lowerCamelCase`.\n\nThese requests include the [`/v2/asset_pairs`](#operation/getAssetPairs), [`/v2/orders`](#operation/getOrders), [`/v2/fee_recipients`](#operation/getFeeRecipients) and [`/v2/orderbook`](#operation/getOrderbook) endpoints.\n\n# Network Id\n\nAll requests should be able to specify a **?networkId** query param for all supported networks. For example:\n\n```bash\n$ curl https://api.example-relayer.com/v2/asset_pairs?networkId=1\n```\n\nIf the query param is not provided, it should default to **1** (mainnet).\n\nNetworks and their Ids:\n\n| Network Id | Network Name |\n| ---------- | ------------ |\n| 1 | Mainnet |\n| 42 | Kovan |\n| 3 | Ropsten |\n| 4 | Rinkeby |\n\nIf a certain network is not supported, the response should **400** as specified in the [error response](#section/Errors) section. For example:\n\n```json\n{\n \"code\": 100,\n \"reason\": \"Validation failed\",\n \"validationErrors\": [\n {\n \"field\": \"networkId\",\n \"code\": 1006,\n \"reason\": \"Network id 42 is not supported\"\n }\n ]\n}\n```\n\n# Link Header\n\nA [Link Header](https://tools.ietf.org/html/rfc5988) can be included in a response to provide clients with more context about paging\nFor example:\n\n```bash\nLink: ; rel=\"next\",\n; rel=\"last\"\n```\n\nThis `Link` response header contains one or more Hypermedia link relations.\n\nThe possible `rel` values are:\n\n| Name | Description |\n| ----- | ------------------------------------------------------------- |\n| next | The link relation for the immediate next page of results. |\n| last | The link relation for the last page of results. |\n| first | The link relation for the first page of results. |\n| prev | The link relation for the immediate previous page of results. |\n\n# Rate Limits\n\nRate limit guidance for clients can be optionally returned in the response headers:\n\n| Header Name | Description |\n| --------------------- | ---------------------------------------------------------------------------- |\n| X-RateLimit-Limit | The maximum number of requests you're permitted to make per hour. |\n| X-RateLimit-Remaining | The number of requests remaining in the current rate limit window. |\n| X-RateLimit-Reset | The time at which the current rate limit window resets in UTC epoch seconds. |\n\nFor example:\n\n```bash\n$ curl -i https://api.example-relayer.com/v2/asset_pairs\nHTTP/1.1 200 OK\nDate: Mon, 20 Oct 2017 12:30:06 GMT\nStatus: 200 OK\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 56\nX-RateLimit-Reset: 1372700873\n```\n\nWhen a rate limit is exceeded, a status of **429 Too Many Requests** should be returned.\n\n# Errors\n\nUnless the spec defines otherwise, errors to bad requests should respond with HTTP 4xx or status codes.\n\n## Common error codes\n\n| Code | Reason |\n| ---- | --------------------------------------- |\n| 400 | Bad Request – Invalid request format |\n| 404 | Not found |\n| 429 | Too many requests - Rate limit exceeded |\n| 500 | Internal Server Error |\n| 501 | Not Implemented |\n\n## Error reporting format\n\nFor all **400** responses, see the [error response schema](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_error_response_schema.ts#L1).\n\n```json\n{\n \"code\": 101,\n \"reason\": \"Validation failed\",\n \"validationErrors\": [\n {\n \"field\": \"maker\",\n \"code\": 1002,\n \"reason\": \"Invalid address\"\n }\n ]\n}\n```\n\nGeneral error codes:\n\n```bash\n100 - Validation Failed\n101 - Malformed JSON\n102 - Order submission disabled\n103 - Throttled\n```\n\nValidation error codes:\n\n```bash\n1000 - Required field\n1001 - Incorrect format\n1002 - Invalid address\n1003 - Address not supported\n1004 - Value out of range\n1005 - Invalid signature or hash\n1006 - Unsupported option\n```\n\n# Asset Data Encoding\n\nAs we now support multiple [token transfer proxies](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxy), the identifier of which proxy to use for the token transfer must be encoded, along with the token information. Each proxy in 0x v2 has a unique identifier. If you're using 0x.js there will be helper methods for this [encoding](https://0xproject.com/docs/0x.js#zeroEx-encodeERC20AssetData) and [decoding](https://0xproject.com/docs/0x.js#zeroEx-decodeAssetProxyId).\n\nThe identifier for the Proxy uses a similar scheme to [ABI function selectors](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#function-selector).\n\n```js\n// ERC20 Proxy ID 0xf47261b0\nbytes4(keccak256('ERC20Token(address)'));\n// ERC721 Proxy ID 0x08e937fa\nbytes4(keccak256('ERC721Token(address,uint256)'));\n```\n\nAsset data is encoded using [ABI encoding](https://solidity.readthedocs.io/en/develop/abi-spec.html).\n\nFor example, encoding the ERC20 token contract (address: 0x1dc4c1cefef38a777b15aa20260a54e584b16c48) using the ERC20 Transfer Proxy (id: 0xf47261b0) would be:\n\n```bash\n0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48\n```\n\nEncoding the ERC721 token contract (address: `0x371b13d97f4bf77d724e78c16b7dc74099f40e84`), token id (id: `99`, which hex encoded is `0x63`) and the ERC721 Transfer Proxy (id: 0x08e937fa) would be:\n\n```bash\n0x08e937fa000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063\n```\n\nFor more information see [the Asset Proxy](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#erc20proxy) section of the v2 spec and the [Ethereum ABI Spec](https://solidity.readthedocs.io/en/develop/abi-spec.html).\n\n# Meta Data in Order Responses\n\nIn v2 of the standard relayer API we added the `metaData` field. It is meant to provide a standard place for relayers to put optional, custom or non-standard fields that may of interest to the consumer of the API.\n\nA good example of such a field is `remainingTakerAssetAmount`, which is a convenience field that communicates how much of a 0x order is potentially left to be filled. Unlike the other fields in a 0x order, it is not guaranteed to be correct as it is derived from whatever mechanism the implementer (ie. the relayer) is using. While convenient for prototyping and low stakes situations, we recommend validating the value of the field by checking the state of the blockchain yourself, such as by using [Order Watcher](https://0xproject.com/wiki#0x-OrderWatcher).\n\n# Misc.\n\n* All requests and responses should be of **application/json** content type\n* All token amounts are sent in amounts of the smallest level of precision (base units). (e.g if a token has 18 decimal places, selling 1 token would show up as selling `'1000000000000000000'` units by this API).\n* All addresses are sent as lower-case (non-checksummed) Ethereum addresses with the `0x` prefix.\n* All parameters are to be written in `lowerCamelCase`.\n","license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0.html"}},"paths":{"/v2/asset_pairs":{"get":{"description":"Retrieves a list of available asset pairs and the information required to trade them (in any order). Setting only `assetDataA` or `assetDataB` returns pairs filtered by that asset only.","operationId":"getAssetPairs","parameters":[{"name":"assetDataA","in":"query","description":"The assetData value for the first asset in the pair.","example":"0xf47261b04c32345ced77393b3530b1eed0f346429d","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"assetDataB","in":"query","description":"The assetData value for the second asset in the pair.","example":"0x0257179264389b814a946f3e92105513705ca6b990","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number","default":1}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number","default":1}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number","default":100}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"Returns a collection of available asset pairs with some meta info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiAssetDataPairsResponseSchema"},"example":{"total":43,"page":1,"perPage":100,"records":[{"assetDataA":{"minAmount":"0","maxAmount":"10000000000000000000","precision":5,"assetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d"},"assetDataB":{"minAmount":"0","maxAmount":"50000000000000000000","precision":5,"assetData":"0x0257179264389b814a946f3e92105513705ca6b990"}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/orders":{"get":{"description":"Retrieves a list of orders given query parameters. This endpoint should be [paginated](#section/Pagination). For querying an entire orderbook snapshot, the [orderbook endpoint](#operation/getOrderbook) is recommended. If both makerAssetData and takerAssetData are specified, returned orders will be sorted by price determined by (takerTokenAmount/makerTokenAmount) in ascending order. By default, orders returned by this endpoint are unsorted.","operationId":"getOrders","parameters":[{"name":"makerAssetProxyId","in":"query","description":"The maker [asset proxy id](https://0xproject.com/docs/0x.js#types-AssetProxyId) (example: \"0xf47261b0\" for ERC20, \"0x02571792\" for ERC721).","example":"0xf47261b0","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"takerAssetProxyId","in":"query","description":"The taker asset [asset proxy id](https://0xproject.com/docs/0x.js#types-AssetProxyId) (example: \"0xf47261b0\" for ERC20, \"0x02571792\" for ERC721).","example":"0x02571792","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"makerAssetAddress","in":"query","description":"The contract address for the maker asset.","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"takerAssetAddress","in":"query","description":"The contract address for the taker asset.","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"exchangeAddress","in":"query","description":"Same as exchangeAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"senderAddress","in":"query","description":"Same as senderAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"makerAssetData","in":"query","description":"Same as makerAssetData in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"takerAssetData","in":"query","description":"Same as takerAssetData in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"traderAssetData","in":"query","description":"Same as traderAssetData in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"makerAddress","in":"query","description":"Same as makerAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"traderAddress","in":"query","description":"Same as traderAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"feeRecipientAddress","in":"query","description":"Same as feeRecipientAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)","example":"0xe41d2489571d322189246dafa5ebde1f4699f498","schema":{"$ref":"#/components/schemas/addressSchema"}},{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number","default":1}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number","default":1}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number","default":100}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"A collection of 0x orders with meta-data as specified by query params","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrdersResponseSchema"},"example":{"total":984,"page":1,"perPage":100,"records":[{"order":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"},"metaData":{}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/order/{orderHash}":{"get":{"description":"Retrieves the 0x order with meta info that is associated with the hash.","operationId":"getOrder","parameters":[{"name":"orderHash","in":"path","description":"The hash of the desired 0x order.","example":"0xd4b103c42d2512eef3fee775e097f044291615d25f5d71e0ac70dbd49d223591","schema":{"$ref":"#/components/schemas/orderHashSchema"}},{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number","default":1}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"The order and meta info associated with the orderHash","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderSchema"},"example":{"order":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"},"metaData":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/orderbook":{"get":{"description":"Retrieves the orderbook for a given asset pair. This endpoint should be [paginated](#section/Pagination). Bids will be sorted in descending order by price, and asks will be sorted in ascending order by price. Within the price sorted orders, the orders are further sorted by _taker fee price_ which is defined as the **takerFee** divided by **takerTokenAmount**. After _taker fee price_, orders are to be sorted by expiration in ascending order. The way pagination works for this endpoint is that the **page** and **perPage** query params apply to both `bids` and `asks` collections, and if `page` * `perPage` > `total` for a certain collection, the `records` for that collection should just be empty. ","operationId":"getOrderbook","parameters":[{"name":"baseAssetData","in":"query","description":"assetData (makerAssetData or takerAssetData) designated as the base currency in the [currency pair calculation](https://en.wikipedia.org/wiki/Currency_pair) of price.","required":true,"example":"0xf47261b04c32345ced77393b3530b1eed0f346429d","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"quoteAssetData","in":"query","description":"assetData (makerAssetData or takerAssetData) designated as the quote currency in the currency pair calculation of price (required).","required":true,"example":"0xf47261b04c32345ced77393b3530b1eed0f346429d","schema":{"$ref":"#/components/schemas/hexSchema"}},{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number","default":1}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number","default":1}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number","default":100}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"The sorted order book for the specified asset pair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderbookResponseSchema"},"example":{"bids":{"total":325,"page":2,"perPage":100,"records":[{"order":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"},"metaData":{}}]},"asks":{"total":500,"page":2,"perPage":100,"records":[{"order":{"makerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","takerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"20000000000000000","takerAssetAmount":"10000000000000000","makerFee":"200000000000000","takerFee":"100000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","takerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x013842a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b3518891"},"metaData":{}}]}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/order_config":{"get":{"description":"Relayers have full discretion over the orders that they are willing to host on their orderbooks (e.g what fees they charge, etc...). In order for traders to discover their requirements programmatically, they can send an incomplete order to this endpoint and receive the missing fields, specifc to that order. This gives relayers a large amount of flexibility to tailor fees to unique traders, trading pairs and volume amounts. Submit a partial order and receive information required to complete the order: `senderAddress`, `feeRecipientAddress`, `makerFee`, `takerFee`. ","operationId":"getOrderConfig","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number","default":1}}],"requestBody":{"description":"The fields of a 0x order the relayer may want to decide what configuration to send back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderConfigPayloadSchema"},"example":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","expirationTimeSeconds":"1532560590"}}}},"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"The additional fields necessary in order to submit an order to the relayer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiOrderConfigResponseSchema"},"example":{"senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","makerFee":"100000000000000","takerFee":"200000000000000"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/fee_recipients":{"get":{"description":"Retrieves a collection of all fee recipient addresses for a relayer. This endpoint should be [paginated](#section/Pagination).","operationId":"getFeeRecipients","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number","default":1}},{"name":"page","in":"query","description":"The number of the page to request in the collection.","example":3,"schema":{"type":"number","default":1}},{"name":"perPage","in":"query","description":"The number of records to return per page.","example":10,"schema":{"type":"number","default":100}}],"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"A collection of all used fee recipient addresses.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiFeeRecipientsResponseSchema"},"example":{"total":3,"page":1,"perPage":10,"records":["0x6eC92694ea172ebC430C30fa31De87620967A082","0x9e56625509c2f60af937f23b7b532600390e8c8b","0xa2b31dacf30a9c50ca473337c01d8a201ae33e32"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}},"/v2/order":{"post":{"description":"Submit a signed order to the relayer.","operationId":"postOrder","parameters":[{"name":"networkId","in":"query","description":"The id of the Ethereum network","example":42,"schema":{"type":"number","default":1}}],"requestBody":{"description":"A valid signed 0x order based on the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/signedOrderSchema"},"example":{"makerAddress":"0x9e56625509c2f60af937f23b7b532600390e8c8b","takerAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","feeRecipientAddress":"0xb046140686d052fff581f63f8136cce132e857da","senderAddress":"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32","makerAssetAmount":"10000000000000000","takerAssetAmount":"20000000000000000","makerFee":"100000000000000","takerFee":"200000000000000","expirationTimeSeconds":"1532560590","salt":"1532559225","makerAssetData":"0xf47261b04c32345ced77393b3530b1eed0f346429d","takerAssetData":"0x0257179264389b814a946f3e92105513705ca6b990","exchangeAddress":"0x12459c951127e0c374ff9105dda097662a027093","signature":"0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"}}}},"responses":{"200":{"headers":{"X-Rate-Limit-Limit":{"description":"The maximum number of requests you're permitted to make per hour.","schema":{"type":"integer"}},"X-Rate-Limit-Remaining":{"description":"The number of requests remaining in the current rate limit window.","schema":{"type":"integer"}},"X-Rate-Limit-Reset":{"description":"The time at which the current rate limit window resets in UTC epoch seconds.","schema":{"type":"integer"}}},"description":"OK","content":{}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/relayerApiErrorResponseSchema"},"example":{"code":100,"reason":"Validation failed","validationErrors":[{"field":"networkId","code":1006,"reason":"Network id 42 is not supported"}]}}}},"404":{"description":"Not found"},"429":{"description":"Too many requests - Rate limit exceeded"},"500":{"description":"Internal Server Error"},"501":{"description":"Not implemented."}}}}},"components":{"schemas":{"numberSchema":{"type":"string","pattern":"^\\d+(\\.\\d+)?$"},"addressSchema":{"type":"string","pattern":"^0x[0-9a-f]{40}$"},"hexSchema":{"type":"string","pattern":"^0x(([0-9a-f][0-9a-f])+)?$"},"orderHashSchema":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$"},"orderSchema":{"properties":{"makerAddress":{"$ref":"#/components/schemas/addressSchema"},"takerAddress":{"$ref":"#/components/schemas/addressSchema"},"makerFee":{"$ref":"#/components/schemas/numberSchema"},"takerFee":{"$ref":"#/components/schemas/numberSchema"},"senderAddress":{"$ref":"#/components/schemas/addressSchema"},"makerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"takerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"makerAssetData":{"$ref":"#/components/schemas/hexSchema"},"takerAssetData":{"$ref":"#/components/schemas/hexSchema"},"salt":{"$ref":"#/components/schemas/numberSchema"},"exchangeAddress":{"$ref":"#/components/schemas/addressSchema"},"feeRecipientAddress":{"$ref":"#/components/schemas/addressSchema"},"expirationTimeSeconds":{"$ref":"#/components/schemas/numberSchema"}},"required":["makerAddress","takerAddress","makerFee","takerFee","senderAddress","makerAssetAmount","takerAssetAmount","makerAssetData","takerAssetData","salt","exchangeAddress","feeRecipientAddress","expirationTimeSeconds"],"type":"object"},"signedOrderSchema":{"allOf":[{"$ref":"#/components/schemas/orderSchema"},{"properties":{"signature":{"$ref":"#/components/schemas/hexSchema"}},"required":["signature"]}]},"signedOrdersSchema":{"type":"array","items":{"$ref":"#/components/schemas/signedOrderSchema"}},"ordersSchema":{"type":"array","items":{"$ref":"#/components/schemas/orderSchema"}},"paginatedCollectionSchema":{"type":"object","properties":{"total":{"type":"number"},"perPage":{"type":"number"},"page":{"type":"number"}},"required":["total","perPage","page"]},"relayerApiErrorResponseSchema":{"type":"object","properties":{"code":{"type":"integer","minimum":100,"maximum":103},"reason":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"code":{"type":"integer","minimum":1000,"maximum":1006},"reason":{"type":"string"}},"required":["field","code","reason"]}}},"required":["code","reason"]},"relayerApiFeeRecipientsResponseSchema":{"type":"object","allOf":[{"$ref":"#/components/schemas/paginatedCollectionSchema"},{"properties":{"records":{"$ref":"#/components/schemas/addressSchema"}},"required":["records"]}]},"relayerApiOrderSchema":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/orderSchema"},"metaData":{"type":"object"}},"required":["order","metaData"]},"relayerApiOrdersSchema":{"type":"array","items":{"$ref":"#/components/schemas/relayerApiOrderSchema"}},"relayerApiOrderConfigPayloadSchema":{"type":"object","properties":{"makerAddress":{"$ref":"#/components/schemas/addressSchema"},"takerAddress":{"$ref":"#/components/schemas/addressSchema"},"makerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"takerAssetAmount":{"$ref":"#/components/schemas/numberSchema"},"makerAssetData":{"$ref":"#/components/schemas/hexSchema"},"takerAssetData":{"$ref":"#/components/schemas/hexSchema"},"exchangeAddress":{"$ref":"#/components/schemas/addressSchema"},"expirationTimeSeconds":{"$ref":"#/components/schemas/numberSchema"}},"required":["makerAddress","takerAddress","makerAssetAmount","takerAssetAmount","makerAssetData","takerAssetData","exchangeAddress","expirationTimeSeconds"]},"relayerApiOrderConfigResponseSchema":{"type":"object","properties":{"makerFee":{"$ref":"#/components/schemas/numberSchema"},"takerFee":{"$ref":"#/components/schemas/numberSchema"},"feeRecipientAddress":{"$ref":"#/components/schemas/addressSchema"},"senderAddress":{"$ref":"#/components/schemas/addressSchema"}},"required":["makerFee","takerFee","feeRecipientAddress","senderAddress"]},"relayerApiOrderbookResponseSchema":{"type":"object","properties":{"bids":{"$ref":"#/components/schemas/relayerApiOrdersResponseSchema"},"asks":{"$ref":"#/components/schemas/relayerApiOrdersResponseSchema"}},"required":["bids","asks"]},"relayerApiAssetDataPairsResponseSchema":{"type":"object","allOf":[{"$ref":"#/components/schemas/paginatedCollectionSchema"},{"properties":{"records":{"$ref":"#/components/schemas/relayerApiAssetDataPairsSchema"}},"required":["records"]}]},"relayerApiAssetDataTradeInfoSchema":{"type":"object","properties":{"assetData":{"$ref":"#/components/schemas/hexSchema"},"minAmount":{"$ref":"#/components/schemas/numberSchema"},"maxAmount":{"$ref":"#/components/schemas/numberSchema"},"precision":{"type":"number"}},"required":["assetData"]},"relayerApiOrdersChannelSubscribeSchema":{"type":"object","properties":{"type":{"enum":["subscribe"]},"channel":{"enum":["orders"]},"requestId":{"type":"string"},"payload":{"$ref":"#/components/schemas/relayerApiOrdersChannelSubscribePayload"}},"required":["type","channel","requestId"]},"relayerApiOrdersChannelSubscribePayload":{"type":"object","properties":{"makerAssetProxyId":{"$ref":"#/components/schemas/hexSchema"},"takerAssetProxyId":{"$ref":"#/components/schemas/hexSchema"},"networkId":{"type":"number"},"makerAssetAddress":{"$ref":"#/components/schemas/addressSchema"},"takerAssetAddress":{"$ref":"#/components/schemas/addressSchema"},"makerAssetData":{"$ref":"#/components/schemas/hexSchema"},"takerAssetData":{"$ref":"#/components/schemas/hexSchema"},"traderAssetData":{"$ref":"#/components/schemas/hexSchema"}}},"relayerApiOrdersChannelUpdateSchema":{"type":"object","properties":{"type":{"enum":["update"]},"channel":{"enum":["orders"]},"requestId":{"type":"string"},"payload":{"$ref":"#/components/schemas/relayerApiOrdersSchema"}},"required":["type","channel","requestId"]},"relayerApiOrdersResponseSchema":{"type":"object","allOf":[{"$ref":"#/components/schemas/paginatedCollectionSchema"},{"properties":{"records":{"$ref":"#/components/schemas/relayerApiOrdersSchema"}},"required":["records"]}]},"relayerApiAssetDataPairsSchema":{"type":"array","items":{"properties":{"assetDataA":{"$ref":"#/components/schemas/relayerApiAssetDataTradeInfoSchema"},"assetDataB":{"$ref":"#/components/schemas/relayerApiAssetDataTradeInfoSchema"}},"required":["assetDataA","assetDataB"],"type":"object"}}}}} \ No newline at end of file diff --git a/packages/sra-api/src/parameters.ts b/packages/sra-api/src/parameters.ts index 10382894c..48ffb036d 100644 --- a/packages/sra-api/src/parameters.ts +++ b/packages/sra-api/src/parameters.ts @@ -7,6 +7,7 @@ export const paginationParameters: ParameterObject[] = [ example: 3, schema: { type: 'number', + default: 1, }, }, { @@ -16,6 +17,7 @@ export const paginationParameters: ParameterObject[] = [ example: 10, schema: { type: 'number', + default: 100, }, }, ]; @@ -27,10 +29,11 @@ export const networkdIdParameter: ParameterObject = { example: 42, schema: { type: 'number', + default: 1, }, }; export const generateParameters = (parameters: ParameterObject[], isPaginated: boolean = false): ParameterObject[] => { const optionalParameters = isPaginated ? paginationParameters : []; - return [networkdIdParameter, ...optionalParameters, ...parameters]; + return [...parameters, networkdIdParameter, ...optionalParameters]; }; diff --git a/yarn.lock b/yarn.lock index 598af599b..a6d6dd1bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5275,9 +5275,9 @@ ethereumjs-wallet@0.6.0: utf8 "^2.1.1" uuid "^2.0.1" -ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22: - version "3.0.18" - resolved "https://codeload.github.com/0xproject/ethers.js/tar.gz/b91342bd200d142af0165d6befddf783c8ae8447" +ethers@3.0.22: + version "3.0.22" + resolved "https://registry.npmjs.org/ethers/-/ethers-3.0.22.tgz#7fab1ea16521705837aa43c15831877b2716b436" dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -6028,7 +6028,7 @@ ganache-core@0xProject/ganache-core#monorepo-dep: ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default" ethereumjs-util "^5.2.0" ethereumjs-vm "2.3.5" - ethereumjs-wallet "0.6.0" + ethereumjs-wallet "~0.6.0" fake-merkle-patricia-tree "~1.0.1" heap "~0.2.6" js-scrypt "^0.2.0" -- cgit From c10c4cec1db2c5bc0b71177aea7590ee6fda8735 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 21:14:46 -0400 Subject: Update marketUtils api --- packages/order-utils/src/market_utils.ts | 93 +++++++++++++++----------- packages/order-utils/src/types.ts | 28 ++++++++ packages/order-utils/test/market_utils_test.ts | 67 ++++++++++++------- 3 files changed, 125 insertions(+), 63 deletions(-) diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index 681059ddf..58e9ab7ba 100644 --- a/packages/order-utils/src/market_utils.ts +++ b/packages/order-utils/src/market_utils.ts @@ -5,37 +5,42 @@ import * as _ from 'lodash'; import { assert } from './assert'; import { constants } from './constants'; +import { FindFeeOrdersThatCoverFeesForTargetOrdersOpts, FindOrdersThatCoverMakerAssetFillAmountOpts } from './types'; export const marketUtils = { /** - * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount (taking into account on-chain balances, - * allowances, and partial fills) in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last. + * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount + * in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last order. * Sort the input by ascending rate in order to get the subset of orders that will cost the least ETH. - * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify the same makerAsset. - * All orders should specify WETH as the takerAsset. - * @param remainingFillableMakerAssetAmounts An array of BigNumbers corresponding to the signedOrders parameter. - * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups - * for these values. - * @param makerAssetFillAmount The amount of makerAsset desired to be filled. - * @param slippageBufferAmount An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills. + * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify the same makerAsset. + * All orders should specify WETH as the takerAsset. + * @param makerAssetFillAmount The amount of makerAsset desired to be filled. + * @param opts Optional arguments this function accepts. * @return Resulting orders and remaining fill amount that could not be covered by the input. */ findOrdersThatCoverMakerAssetFillAmount( signedOrders: SignedOrder[], - remainingFillableMakerAssetAmounts: BigNumber[], makerAssetFillAmount: BigNumber, - slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, + opts?: FindOrdersThatCoverMakerAssetFillAmountOpts, ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); + // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders + const remainingFillableMakerAssetAmounts = _.get( + opts, + 'remainingFillableMakerAssetAmounts', + _.map(signedOrders, order => order.makerAssetAmount), + ) as BigNumber[]; _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); - assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); - assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount); assert.assert( signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length', + 'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', ); + // try to get slippageBufferAmount from opts, if it's not there, default to 0 + const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; + assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); // calculate total amount of makerAsset needed to be filled const totalFillAmount = makerAssetFillAmount.plus(slippageBufferAmount); // iterate through the signedOrders input from left to right until we have enough makerAsset to fill totalFillAmount @@ -64,47 +69,53 @@ export const marketUtils = { return result; }, /** - * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX (taking into account - * on-chain balances, allowances, and partial fills) in order to fill the takerFees required by signedOrders plus a - * slippageBufferAmount. Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of + * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX + * in order to fill the takerFees required by signedOrders plus a slippageBufferAmount. + * Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of * feeOrders that will cost the least ETH. - * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param remainingFillableMakerAssetAmounts An array of BigNumbers corresponding to the signedOrders parameter. - * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups - * for these values. - * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param remainingFillableFeeAmounts An array of BigNumbers corresponding to the signedFeeOrders parameter. - * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups - * for these values. - * @param slippageBufferAmount An additional amount of fee to be covered by the result in case of trade collisions or partial fills. + * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. + * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. + * @param opts Optional arguments this function accepts. * @return Resulting orders and remaining fee amount that could not be covered by the input. */ findFeeOrdersThatCoverFeesForTargetOrders( signedOrders: SignedOrder[], - remainingFillableMakerAssetAmounts: BigNumber[], signedFeeOrders: SignedOrder[], - remainingFillableFeeAmounts: BigNumber[], - slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, + opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts, ): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders + const remainingFillableMakerAssetAmounts = _.get( + opts, + 'remainingFillableMakerAssetAmounts', + _.map(signedOrders, order => order.makerAssetAmount), + ) as BigNumber[]; _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - _.forEach(remainingFillableFeeAmounts, (amount, index) => - assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), - ); - assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount); assert.assert( signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length', + 'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', + ); + // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from signedFeeOrders + const remainingFillableFeeAmounts = _.get( + opts, + 'remainingFillableFeeAmounts', + _.map(signedFeeOrders, order => order.makerAssetAmount), + ) as BigNumber[]; + _.forEach(remainingFillableFeeAmounts, (amount, index) => + assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), ); assert.assert( signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedFeeOrders.length to equal remainingFillableFeeAmounts.length', + 'Expected signedFeeOrders.length to equal opts.remainingFillableFeeAmounts.length', ); + // try to get slippageBufferAmount from opts, if it's not there, default to 0 + const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; + assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); // calculate total amount of ZRX needed to fill signedOrders const totalFeeAmount = _.reduce( signedOrders, @@ -119,9 +130,11 @@ export const marketUtils = { ); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( signedFeeOrders, - remainingFillableFeeAmounts, totalFeeAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts, + slippageBufferAmount, + }, ); return { resultOrders, diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts index 1fbd8cf7b..8a9a4cafe 100644 --- a/packages/order-utils/src/types.ts +++ b/packages/order-utils/src/types.ts @@ -41,3 +41,31 @@ export interface CreateOrderOpts { salt?: BigNumber; expirationTimeSeconds?: BigNumber; } + +/** + * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. + * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. + * Defaults to `makerAssetAmount` values from the signedOrders param. + * slippageBufferAmount: An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills. + * Defaults to 0 + */ +export interface FindOrdersThatCoverMakerAssetFillAmountOpts { + remainingFillableMakerAssetAmounts?: BigNumber[]; + slippageBufferAmount?: BigNumber; +} + +/** + * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. + * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. + * Defaults to `makerAssetAmount` values from the signedOrders param. + * remainingFillableFeeAmounts: An array of BigNumbers corresponding to the signedFeeOrders parameter. + * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups for these values. + * Defaults to `makerAssetAmount` values from the signedFeeOrders param. + * slippageBufferAmount: An additional amount of fee to be covered by the result in case of trade collisions or partial fills. + * Defaults to 0 + */ +export interface FindFeeOrdersThatCoverFeesForTargetOrdersOpts { + remainingFillableMakerAssetAmounts?: BigNumber[]; + remainingFillableFeeAmounts?: BigNumber[]; + slippageBufferAmount?: BigNumber; +} diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts index 21c0a4802..2f6bb7bd1 100644 --- a/packages/order-utils/test/market_utils_test.ts +++ b/packages/order-utils/test/market_utils_test.ts @@ -11,13 +11,12 @@ chaiSetup.configure(); const expect = chai.expect; // tslint:disable: no-unused-expression -describe('marketUtils', () => { +describe.only('marketUtils', () => { describe('#findOrdersThatCoverMakerAssetFillAmount', () => { describe('no orders', () => { it('returns empty and unchanged remainingFillAmount', async () => { const fillAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - [], [], fillAmount, ); @@ -43,9 +42,11 @@ describe('marketUtils', () => { const slippageBufferAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts, + slippageBufferAmount, + }, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -57,9 +58,11 @@ describe('marketUtils', () => { const slippageBufferAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts, + slippageBufferAmount, + }, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -71,9 +74,11 @@ describe('marketUtils', () => { const slippageBufferAmount = new BigNumber(5); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts, + slippageBufferAmount, + }, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5)); @@ -83,8 +88,10 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, + { + remainingFillableMakerAssetAmounts, + }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -94,8 +101,10 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(15); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, + { + remainingFillableMakerAssetAmounts, + }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -120,8 +129,10 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(30); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, + { + remainingFillableMakerAssetAmounts, + }, ); expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]); expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(15)); @@ -142,10 +153,11 @@ describe('marketUtils', () => { describe('no target orders', () => { it('returns empty and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - [], [], inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -168,9 +180,10 @@ describe('marketUtils', () => { it('returns empty and non-zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, - [], [], + { + remainingFillableMakerAssetAmounts, + }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); @@ -190,9 +203,11 @@ describe('marketUtils', () => { it('returns empty and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -215,9 +230,11 @@ describe('marketUtils', () => { it('returns input fee orders and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -243,9 +260,11 @@ describe('marketUtils', () => { it('returns first two input fee orders and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]); expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -268,9 +287,11 @@ describe('marketUtils', () => { it('returns input fee orders and non-zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); -- cgit From 66745c5260d2e2802211697980ce91a0cf084e83 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 21:18:13 -0400 Subject: Remove remaining amounts that are now defaults in tests --- packages/order-utils/test/market_utils_test.ts | 37 +------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts index 2f6bb7bd1..109420a02 100644 --- a/packages/order-utils/test/market_utils_test.ts +++ b/packages/order-utils/test/market_utils_test.ts @@ -11,7 +11,7 @@ chaiSetup.configure(); const expect = chai.expect; // tslint:disable: no-unused-expression -describe.only('marketUtils', () => { +describe('marketUtils', () => { describe('#findOrdersThatCoverMakerAssetFillAmount', () => { describe('no orders', () => { it('returns empty and unchanged remainingFillAmount', async () => { @@ -33,8 +33,6 @@ describe.only('marketUtils', () => { }, 3, ); - // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount - const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => { // try to fill 20 units of makerAsset // include 10 units of slippageBufferAmount @@ -44,7 +42,6 @@ describe.only('marketUtils', () => { inputOrders, fillAmount, { - remainingFillableMakerAssetAmounts, slippageBufferAmount, }, ); @@ -60,7 +57,6 @@ describe.only('marketUtils', () => { inputOrders, fillAmount, { - remainingFillableMakerAssetAmounts, slippageBufferAmount, }, ); @@ -76,7 +72,6 @@ describe.only('marketUtils', () => { inputOrders, fillAmount, { - remainingFillableMakerAssetAmounts, slippageBufferAmount, }, ); @@ -89,9 +84,6 @@ describe.only('marketUtils', () => { const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, fillAmount, - { - remainingFillableMakerAssetAmounts, - }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -102,9 +94,6 @@ describe.only('marketUtils', () => { const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, fillAmount, - { - remainingFillableMakerAssetAmounts, - }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -148,16 +137,11 @@ describe.only('marketUtils', () => { }, 3, ); - // generate remainingFillableFeeAmounts that equal the zrxAmount - const remainingFillableFeeAmounts = [zrxAmount, zrxAmount, zrxAmount]; describe('no target orders', () => { it('returns empty and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( [], inputFeeOrders, - { - remainingFillableFeeAmounts, - }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -198,16 +182,10 @@ describe.only('marketUtils', () => { }, 3, ); - // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount - const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; it('returns empty and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, inputFeeOrders, - { - remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, - }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -225,16 +203,10 @@ describe.only('marketUtils', () => { }, 3, ); - // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount - const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; it('returns input fee orders and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, inputFeeOrders, - { - remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, - }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -263,7 +235,6 @@ describe.only('marketUtils', () => { inputFeeOrders, { remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, }, ); expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]); @@ -282,16 +253,10 @@ describe.only('marketUtils', () => { }, 3, ); - // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount - const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; it('returns input fee orders and non-zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, inputFeeOrders, - { - remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, - }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); -- cgit From a2192e62df56efd95a0e3540296cd17a23cb2033 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 21:26:45 -0400 Subject: Update CHANGELOG --- packages/order-utils/CHANGELOG.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index a81eb077d..7cefc1670 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -18,6 +18,11 @@ }, { "note": "Dependencies updated" + }, + { + "note": + "Update marketUtils api such that all optional parameters are bundled into one optional param and more defaults are provided", + "pr": 954 } ], "timestamp": 1534210131 -- cgit From 6a2634d362e50e5a611f388c0785df3209cee308 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 13 Aug 2018 21:29:35 -0700 Subject: Make marketUtils interface compatible with Order and SignedOrder --- packages/order-utils/src/market_utils.ts | 72 ++++++++++++++++---------------- packages/order-utils/src/types.ts | 12 +++--- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index 58e9ab7ba..a0a827546 100644 --- a/packages/order-utils/src/market_utils.ts +++ b/packages/order-utils/src/market_utils.ts @@ -1,5 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; -import { SignedOrder } from '@0xproject/types'; +import { Order } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -12,40 +12,40 @@ export const marketUtils = { * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount * in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last order. * Sort the input by ascending rate in order to get the subset of orders that will cost the least ETH. - * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify the same makerAsset. + * @param orders An array of objects that extend the Order interface. All orders should specify the same makerAsset. * All orders should specify WETH as the takerAsset. * @param makerAssetFillAmount The amount of makerAsset desired to be filled. * @param opts Optional arguments this function accepts. * @return Resulting orders and remaining fill amount that could not be covered by the input. */ - findOrdersThatCoverMakerAssetFillAmount( - signedOrders: SignedOrder[], + findOrdersThatCoverMakerAssetFillAmount( + orders: T[], makerAssetFillAmount: BigNumber, opts?: FindOrdersThatCoverMakerAssetFillAmountOpts, - ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + ): { resultOrders: T[]; remainingFillAmount: BigNumber } { + assert.doesConformToSchema('orders', orders, schemas.ordersSchema); assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); - // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders + // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders const remainingFillableMakerAssetAmounts = _.get( opts, 'remainingFillableMakerAssetAmounts', - _.map(signedOrders, order => order.makerAssetAmount), + _.map(orders, order => order.makerAssetAmount), ) as BigNumber[]; _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); assert.assert( - signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', + orders.length === remainingFillableMakerAssetAmounts.length, + 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length', ); // try to get slippageBufferAmount from opts, if it's not there, default to 0 const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); // calculate total amount of makerAsset needed to be filled const totalFillAmount = makerAssetFillAmount.plus(slippageBufferAmount); - // iterate through the signedOrders input from left to right until we have enough makerAsset to fill totalFillAmount + // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount const result = _.reduce( - signedOrders, + orders, ({ resultOrders, remainingFillAmount }, order, index) => { if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) { return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT }; @@ -64,61 +64,61 @@ export const marketUtils = { }; } }, - { resultOrders: [] as SignedOrder[], remainingFillAmount: totalFillAmount }, + { resultOrders: [] as T[], remainingFillAmount: totalFillAmount }, ); return result; }, /** * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX - * in order to fill the takerFees required by signedOrders plus a slippageBufferAmount. + * in order to fill the takerFees required by orders plus a slippageBufferAmount. * Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of * feeOrders that will cost the least ETH. - * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param opts Optional arguments this function accepts. + * @param orders An array of objects that extend the Order interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. + * @param feeOrders An array of objects that extend the Order interface. All orders should specify ZRX as + * the makerAsset and WETH as the takerAsset. + * @param opts Optional arguments this function accepts. * @return Resulting orders and remaining fee amount that could not be covered by the input. */ - findFeeOrdersThatCoverFeesForTargetOrders( - signedOrders: SignedOrder[], - signedFeeOrders: SignedOrder[], + findFeeOrdersThatCoverFeesForTargetOrders( + orders: T[], + feeOrders: T[], opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts, - ): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders + ): { resultOrders: T[]; remainingFeeAmount: BigNumber } { + assert.doesConformToSchema('orders', orders, schemas.ordersSchema); + assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema); + // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders const remainingFillableMakerAssetAmounts = _.get( opts, 'remainingFillableMakerAssetAmounts', - _.map(signedOrders, order => order.makerAssetAmount), + _.map(orders, order => order.makerAssetAmount), ) as BigNumber[]; _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); assert.assert( - signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', + orders.length === remainingFillableMakerAssetAmounts.length, + 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length', ); - // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from signedFeeOrders + // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from feeOrders const remainingFillableFeeAmounts = _.get( opts, 'remainingFillableFeeAmounts', - _.map(signedFeeOrders, order => order.makerAssetAmount), + _.map(feeOrders, order => order.makerAssetAmount), ) as BigNumber[]; _.forEach(remainingFillableFeeAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), ); assert.assert( - signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedFeeOrders.length to equal opts.remainingFillableFeeAmounts.length', + feeOrders.length === remainingFillableFeeAmounts.length, + 'Expected feeOrders.length to equal opts.remainingFillableFeeAmounts.length', ); // try to get slippageBufferAmount from opts, if it's not there, default to 0 const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); - // calculate total amount of ZRX needed to fill signedOrders + // calculate total amount of ZRX needed to fill orders const totalFeeAmount = _.reduce( - signedOrders, + orders, (accFees, order, index) => { const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index]; const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable @@ -129,7 +129,7 @@ export const marketUtils = { constants.ZERO_AMOUNT, ); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - signedFeeOrders, + feeOrders, totalFeeAmount, { remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts, diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts index 8a9a4cafe..2e9c79d80 100644 --- a/packages/order-utils/src/types.ts +++ b/packages/order-utils/src/types.ts @@ -43,9 +43,9 @@ export interface CreateOrderOpts { } /** - * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. + * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter. * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. - * Defaults to `makerAssetAmount` values from the signedOrders param. + * Defaults to `makerAssetAmount` values from the orders param. * slippageBufferAmount: An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills. * Defaults to 0 */ @@ -55,12 +55,12 @@ export interface FindOrdersThatCoverMakerAssetFillAmountOpts { } /** - * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. + * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter. * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. - * Defaults to `makerAssetAmount` values from the signedOrders param. - * remainingFillableFeeAmounts: An array of BigNumbers corresponding to the signedFeeOrders parameter. + * Defaults to `makerAssetAmount` values from the orders param. + * remainingFillableFeeAmounts: An array of BigNumbers corresponding to the feeOrders parameter. * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups for these values. - * Defaults to `makerAssetAmount` values from the signedFeeOrders param. + * Defaults to `makerAssetAmount` values from the feeOrders param. * slippageBufferAmount: An additional amount of fee to be covered by the result in case of trade collisions or partial fills. * Defaults to 0 */ -- cgit From db20ad1c5db5677b7d5ad54bf76a928b5857fe8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 14 Aug 2018 06:21:07 +0000 Subject: Bump @types/fetch-mock from 5.12.2 to 6.0.3 Bumps [@types/fetch-mock](https://github.com/DefinitelyTyped/DefinitelyTyped) from 5.12.2 to 6.0.3. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits) Signed-off-by: dependabot[bot] --- packages/connect/package.json | 2 +- yarn.lock | 79 ++++++++++++++++++++++++------------------- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/packages/connect/package.json b/packages/connect/package.json index 1cc5e1bab..0fad3e14c 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@0xproject/monorepo-scripts": "^1.0.5", "@0xproject/tslint-config": "^1.0.5", - "@types/fetch-mock": "^5.12.2", + "@types/fetch-mock": "^6.0.3", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/query-string": "^5.0.1", diff --git a/yarn.lock b/yarn.lock index a6d6dd1bf..f0214178e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -944,9 +944,9 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" -"@types/fetch-mock@^5.12.2": - version "5.12.2" - resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-5.12.2.tgz#8c96517ff74303031c65c5da2d99858e34c844d2" +"@types/fetch-mock@6.0.3": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-6.0.3.tgz#54ba90776293e728089bf53ba53e3c69f1c80655" "@types/find-versions@^2.0.0": version "2.0.0" @@ -1369,9 +1369,9 @@ aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" -aes-js@^0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d" +aes-js@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072" ajv-keywords@^2.1.0: version "2.1.1" @@ -2429,10 +2429,6 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" -base-x@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-1.1.0.tgz#42d3d717474f9ea02207f6d1aa1f426913eeb7ac" - base-x@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" @@ -2836,7 +2832,7 @@ browserslist@^2.1.2: caniuse-lite "^1.0.30000792" electron-to-chromium "^1.3.30" -bs58@=4.0.1: +bs58@=4.0.1, bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" dependencies: @@ -2846,18 +2842,13 @@ bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" -bs58@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e" - dependencies: - base-x "^1.1.0" - -bs58check@^1.0.8: - version "1.3.4" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-1.3.4.tgz#c52540073749117714fa042c3047eb8f9151cbf8" +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" dependencies: - bs58 "^3.1.0" + bs58 "^4.0.0" create-hash "^1.1.0" + safe-buffer "^5.1.2" btoa@1.1.2: version "1.1.2" @@ -5209,7 +5200,7 @@ ethereumjs-util@5.1.5, ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumj safe-buffer "^5.1.1" secp256k1 "^3.0.1" -ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0: +ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" dependencies: @@ -5263,21 +5254,23 @@ ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4: rustbn.js "~0.1.1" safe-buffer "^5.1.1" -ethereumjs-wallet@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb" +ethereumjs-wallet@~0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda" dependencies: - aes-js "^0.2.3" - bs58check "^1.0.8" - ethereumjs-util "^4.4.0" - hdkey "^0.7.0" + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereumjs-util "^5.2.0" + hdkey "^1.0.0" + safe-buffer "^5.1.2" scrypt.js "^0.2.0" - utf8 "^2.1.1" - uuid "^2.0.1" + utf8 "^3.0.0" + uuid "^3.3.2" -ethers@3.0.22: - version "3.0.22" - resolved "https://registry.npmjs.org/ethers/-/ethers-3.0.22.tgz#7fab1ea16521705837aa43c15831877b2716b436" +ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22: + version "3.0.18" + uid b91342bd200d142af0165d6befddf783c8ae8447 + resolved "https://codeload.github.com/0xproject/ethers.js/tar.gz/b91342bd200d142af0165d6befddf783c8ae8447" dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -6693,13 +6686,21 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" -hdkey@^0.7.0, hdkey@^0.7.1: +hdkey@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632" dependencies: coinstring "^2.0.0" secp256k1 "^3.0.1" +hdkey@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.0.0.tgz#1d658dfe966aaa542c1d499586200b325e5c0cf4" + dependencies: + coinstring "^2.0.0" + safe-buffer "^5.1.1" + secp256k1 "^3.0.1" + he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" @@ -14036,6 +14037,10 @@ utf8@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" +utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -14081,6 +14086,10 @@ uuid@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + uvm@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/uvm/-/uvm-1.7.0.tgz#685d3a149ec7118fb73a73dfdc158ab46b0f0634" -- cgit From 6baa5ef311112941ccaec3fb8a877dd57b63627b Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Mon, 13 Aug 2018 12:46:43 -0700 Subject: feat: Upgrade TypeScript to 3.0.1 --- packages/0x.js/package.json | 2 +- packages/abi-gen/package.json | 2 +- packages/assert/package.json | 2 +- packages/base-contract/package.json | 2 +- packages/connect/package.json | 2 +- packages/contract-wrappers/package.json | 2 +- packages/contracts/package.json | 2 +- packages/dev-utils/package.json | 2 +- packages/ethereum-types/package.json | 2 +- packages/fill-scenarios/package.json | 2 +- packages/json-schemas/package.json | 2 +- packages/metacoin/package.json | 2 +- packages/migrations/package.json | 2 +- packages/monorepo-scripts/package.json | 2 +- packages/order-utils/package.json | 2 +- packages/order-watcher/package.json | 2 +- packages/react-docs-example/package.json | 2 +- packages/react-docs/package.json | 2 +- packages/react-shared/package.json | 2 +- packages/sol-compiler/package.json | 2 +- packages/sol-cov/package.json | 2 +- packages/sol-resolver/package.json | 2 +- packages/sra-report/package.json | 2 +- packages/subproviders/package.json | 2 +- packages/testnet-faucets/package.json | 2 +- packages/tslint-config/package.json | 2 +- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- packages/web3-wrapper/package.json | 2 +- packages/website/package.json | 2 +- yarn.lock | 6 +++--- 31 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index cf7b1962f..2daf40b54 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -94,7 +94,7 @@ "source-map-support": "^0.5.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.1.0" }, "dependencies": { diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 8ea055a15..565fe4058 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -63,7 +63,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/assert/package.json b/packages/assert/package.json index 9d2669955..d249b4cd1 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -44,7 +44,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/json-schemas": "^1.0.1-rc.4", diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index e658d9cfa..c5375ecf6 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -40,7 +40,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/typescript-typings": "^1.0.4", diff --git a/packages/connect/package.json b/packages/connect/package.json index 1cc5e1bab..4ab5cec64 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -83,7 +83,7 @@ "shx": "^0.2.2", "tslint": "5.11.0", "typedoc": "~0.8.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index 7667b5b7f..ae2867e6c 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -68,7 +68,7 @@ "sinon": "^4.0.0", "source-map-support": "^0.5.0", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "web3-provider-engine": "14.0.6" }, "dependencies": { diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 799f72d9e..01858894b 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -68,7 +68,7 @@ "solc": "^0.4.24", "solhint": "^1.2.1", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "yargs": "^10.0.3" }, "dependencies": { diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 5aa6edcd8..544ff23fa 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -42,7 +42,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/subproviders": "^1.0.5", diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json index 0e89a8049..c2092a1d3 100644 --- a/packages/ethereum-types/package.json +++ b/packages/ethereum-types/package.json @@ -41,7 +41,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@types/node": "^8.0.53", diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index c3e8afb0e..466e96258 100644 --- a/packages/fill-scenarios/package.json +++ b/packages/fill-scenarios/package.json @@ -38,7 +38,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/base-contract": "^2.0.0-rc.1", diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index 40cb71c18..a5941a971 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -70,7 +70,7 @@ "shx": "^0.2.2", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index 6900da198..322708b50 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -56,6 +56,6 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" } } diff --git a/packages/migrations/package.json b/packages/migrations/package.json index d496393f7..dc481a972 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -49,7 +49,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "yargs": "^10.0.3" }, "dependencies": { diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index 4d92ed495..87135fd93 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -40,7 +40,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@lerna/batch-packages": "^3.0.0-beta.18", diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index fa8f3563e..bedbdc6d2 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -70,7 +70,7 @@ "sinon": "^4.0.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/assert": "^1.0.5", diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index ba4fed358..5ce1805e7 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -67,7 +67,7 @@ "sinon": "^4.0.0", "source-map-support": "^0.5.0", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/assert": "^1.0.5", diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json index 1701e6adb..001b354d7 100644 --- a/packages/react-docs-example/package.json +++ b/packages/react-docs-example/package.json @@ -45,7 +45,7 @@ "source-map-loader": "^0.2.3", "style-loader": "^0.20.2", "tslint": "^5.9.1", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.11.0", "webpack-dev-server": "^2.11.1" }, diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index e24ed8e6f..a530e526d 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -33,7 +33,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "^5.9.1", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/react-shared": "^1.0.6", diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index 9761c246e..6eaac9d07 100644 --- a/packages/react-shared/package.json +++ b/packages/react-shared/package.json @@ -32,7 +32,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "^5.9.1", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@types/is-mobile": "0.3.0", diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index 7cb07e970..29b8f9f3a 100644 --- a/packages/sol-compiler/package.json +++ b/packages/sol-compiler/package.json @@ -71,7 +71,7 @@ "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "types-bn": "^0.0.1", - "typescript": "2.9.2", + "typescript": "3.0.1", "web3-typescript-typings": "^0.10.2", "zeppelin-solidity": "1.8.0" }, diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 4c3000360..1d98faf8b 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -89,7 +89,7 @@ "sinon": "^4.0.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json index 7a3c7509a..46ad8f784 100644 --- a/packages/sol-resolver/package.json +++ b/packages/sol-resolver/package.json @@ -30,7 +30,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/types": "^1.0.1-rc.4", diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json index 42321359c..175a4ca1b 100644 --- a/packages/sra-report/package.json +++ b/packages/sra-report/package.json @@ -66,7 +66,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 405b89db3..ab3ae1a5a 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -84,7 +84,7 @@ "sinon": "^4.0.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.1.0" }, "optionalDependencies": { diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json index ce2a1a52d..769fdf371 100644 --- a/packages/testnet-faucets/package.json +++ b/packages/testnet-faucets/package.json @@ -43,7 +43,7 @@ "shx": "^0.2.2", "source-map-loader": "^0.1.6", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.1.0", "webpack-node-externals": "^1.6.0" } diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index 1cc778caf..6956a9105 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -39,7 +39,7 @@ "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "lodash": "^4.17.5", diff --git a/packages/types/package.json b/packages/types/package.json index c97984e10..6a36b897b 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -30,7 +30,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@types/node": "^8.0.53", diff --git a/packages/utils/package.json b/packages/utils/package.json index 0fd925715..c596f0620 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -40,7 +40,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/types": "^1.0.1-rc.4", diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 3f9ee9019..437a1c6b5 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -61,7 +61,7 @@ "shx": "^0.2.2", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/assert": "^1.0.5", diff --git a/packages/website/package.json b/packages/website/package.json index f4638229d..0fcf9c9b9 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -98,7 +98,7 @@ "style-loader": "0.13.x", "tslint": "5.11.0", "tslint-config-0xproject": "^0.0.2", - "typescript": "2.9.2", + "typescript": "3.0.1", "uglifyjs-webpack-plugin": "^1.2.5", "webpack": "^3.1.0", "webpack-dev-middleware": "^1.10.0", diff --git a/yarn.lock b/yarn.lock index 598af599b..893447f06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13705,9 +13705,9 @@ typescript@2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.1.tgz#bb3682c2c791ac90e7c6210b26478a8da085c359" -typescript@2.9.2: - version "2.9.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" +typescript@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.0.1.tgz#43738f29585d3a87575520a4b93ab6026ef11fdb" typewise-core@^1.2, typewise-core@^1.2.0: version "1.2.0" -- cgit From b6cdc00a3145e6b13102676b2a881d0fe52b3a61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 14 Aug 2018 21:51:13 +0000 Subject: Bump copyfiles from 1.2.0 to 2.0.0 Bumps [copyfiles](https://github.com/calvinmetcalf/copyfiles) from 1.2.0 to 2.0.0. - [Release notes](https://github.com/calvinmetcalf/copyfiles/releases) - [Commits](https://github.com/calvinmetcalf/copyfiles/compare/v1.2.0...v2.0.0) Signed-off-by: dependabot[bot] --- packages/0x.js/package.json | 2 +- packages/abi-gen/package.json | 2 +- packages/assert/package.json | 2 +- packages/base-contract/package.json | 2 +- packages/connect/package.json | 2 +- packages/contract-wrappers/package.json | 2 +- packages/contracts/package.json | 2 +- packages/dev-utils/package.json | 2 +- packages/ethereum-types/package.json | 2 +- packages/fill-scenarios/package.json | 2 +- packages/json-schemas/package.json | 2 +- packages/migrations/package.json | 2 +- packages/order-utils/package.json | 2 +- packages/order-watcher/package.json | 2 +- packages/react-docs-example/package.json | 2 +- packages/react-docs/package.json | 2 +- packages/react-shared/package.json | 2 +- packages/sol-compiler/package.json | 2 +- packages/sol-cov/package.json | 2 +- packages/sol-resolver/package.json | 2 +- packages/sra-report/package.json | 2 +- packages/subproviders/package.json | 2 +- packages/tslint-config/package.json | 2 +- packages/types/package.json | 2 +- packages/typescript-typings/package.json | 2 +- packages/utils/package.json | 2 +- packages/web3-wrapper/package.json | 2 +- packages/website/package.json | 2 +- yarn.lock | 19 ++----------------- 29 files changed, 30 insertions(+), 45 deletions(-) diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index 2daf40b54..bbb902b49 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -81,7 +81,7 @@ "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "json-loader": "^0.5.4", "make-promises-safe": "^1.1.0", diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 565fe4058..3e3494585 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -56,7 +56,7 @@ "@types/tmp": "^0.0.33", "@types/yargs": "^10.0.0", "chai": "^4.1.2", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^5.2.0", diff --git a/packages/assert/package.json b/packages/assert/package.json index d249b4cd1..64e60a1e1 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -36,7 +36,7 @@ "@types/mocha": "^2.2.42", "@types/valid-url": "^1.0.2", "chai": "^4.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index c5375ecf6..d31a02dda 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -34,7 +34,7 @@ "@0xproject/tslint-config": "^1.0.5", "@types/lodash": "4.14.104", "chai": "^4.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", "npm-run-all": "^4.1.2", diff --git a/packages/connect/package.json b/packages/connect/package.json index 3894be6ea..8f2e423b5 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -73,7 +73,7 @@ "async-child-process": "^1.1.1", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "fetch-mock": "^5.13.1", "make-promises-safe": "^1.1.0", diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index ae2867e6c..098c95ef0 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -57,7 +57,7 @@ "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 01858894b..8bd808a27 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -59,7 +59,7 @@ "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 544ff23fa..79e75a06e 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -35,7 +35,7 @@ "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "chai": "^4.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", "npm-run-all": "^4.1.2", diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json index c2092a1d3..4fa273c6a 100644 --- a/packages/ethereum-types/package.json +++ b/packages/ethereum-types/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@0xproject/monorepo-scripts": "^1.0.5", "@0xproject/tslint-config": "^1.0.5", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index 466e96258..ccc04caf8 100644 --- a/packages/fill-scenarios/package.json +++ b/packages/fill-scenarios/package.json @@ -33,7 +33,7 @@ "@0xproject/sol-compiler": "^1.0.5", "@0xproject/tslint-config": "^1.0.5", "@types/lodash": "4.14.104", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index a5941a971..062304585 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -60,7 +60,7 @@ "@types/lodash.values": "^4.3.3", "@types/mocha": "^2.2.42", "chai": "^4.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "lodash.foreach": "^4.5.0", "make-promises-safe": "^1.1.0", diff --git a/packages/migrations/package.json b/packages/migrations/package.json index dc481a972..c1ef61257 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -44,7 +44,7 @@ "@0xproject/tslint-config": "^1.0.5", "@0xproject/types": "^1.0.1-rc.4", "@types/yargs": "^10.0.0", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index bedbdc6d2..07d6fa1b6 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -61,7 +61,7 @@ "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index 5ce1805e7..59d80fd08 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -55,7 +55,7 @@ "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "json-loader": "^0.5.4", "make-promises-safe": "^1.1.0", diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json index 001b354d7..8efe35089 100644 --- a/packages/react-docs-example/package.json +++ b/packages/react-docs-example/package.json @@ -34,7 +34,7 @@ "@types/react-dom": "^16.0.3", "@types/react-tap-event-plugin": "0.0.30", "awesome-typescript-loader": "^3.1.3", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "css-loader": "^0.28.9", "json-loader": "^0.5.4", "less": "^2.7.2", diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index a530e526d..f09bb64a0 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -29,7 +29,7 @@ "@0xproject/monorepo-scripts": "^1.0.5", "@0xproject/tslint-config": "^1.0.5", "@types/compare-versions": "^3.0.0", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "^5.9.1", diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index 6eaac9d07..83b4cc5c9 100644 --- a/packages/react-shared/package.json +++ b/packages/react-shared/package.json @@ -28,7 +28,7 @@ "@0xproject/dev-utils": "^1.0.4", "@0xproject/monorepo-scripts": "^1.0.5", "@0xproject/tslint-config": "^1.0.5", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "^5.9.1", diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index 29b8f9f3a..6543b782b 100644 --- a/packages/sol-compiler/package.json +++ b/packages/sol-compiler/package.json @@ -61,7 +61,7 @@ "@types/semver": "^5.5.0", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 1d98faf8b..bc24fd1dc 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -79,7 +79,7 @@ "@types/rimraf": "^2.0.2", "@types/solidity-parser-antlr": "^0.2.1", "chai": "^4.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json index 46ad8f784..85d11e9e7 100644 --- a/packages/sol-resolver/package.json +++ b/packages/sol-resolver/package.json @@ -26,7 +26,7 @@ "devDependencies": { "@0xproject/monorepo-scripts": "^1.0.5", "@0xproject/tslint-config": "^1.0.5", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json index 175a4ca1b..8c213ee26 100644 --- a/packages/sra-report/package.json +++ b/packages/sra-report/package.json @@ -57,7 +57,7 @@ "@types/yargs": "^10.0.0", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index ab3ae1a5a..57b0a13b3 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -74,7 +74,7 @@ "@types/sinon": "^2.2.2", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index 6956a9105..c0a1977f9 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -36,7 +36,7 @@ "devDependencies": { "@0xproject/monorepo-scripts": "^1.0.5", "@types/lodash": "4.14.104", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "typescript": "3.0.1" diff --git a/packages/types/package.json b/packages/types/package.json index 6a36b897b..a41f78aac 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -26,7 +26,7 @@ "devDependencies": { "@0xproject/monorepo-scripts": "^1.0.5", "@0xproject/tslint-config": "^1.0.5", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", diff --git a/packages/typescript-typings/package.json b/packages/typescript-typings/package.json index 01a1d8adc..5d9768cb0 100644 --- a/packages/typescript-typings/package.json +++ b/packages/typescript-typings/package.json @@ -33,7 +33,7 @@ }, "devDependencies": { "@0xproject/monorepo-scripts": "^1.0.5", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "shx": "^0.2.2" }, "publishConfig": { diff --git a/packages/utils/package.json b/packages/utils/package.json index c596f0620..28a967a35 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -34,7 +34,7 @@ "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "chai": "^4.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", "npm-run-all": "^4.1.2", diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 437a1c6b5..d672db7e4 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -51,7 +51,7 @@ "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "ganache-core": "0xProject/ganache-core#monorepo-dep", "make-promises-safe": "^1.1.0", diff --git a/packages/website/package.json b/packages/website/package.json index 0fcf9c9b9..3b4055856 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -84,7 +84,7 @@ "@types/redux": "^3.6.0", "awesome-typescript-loader": "^3.1.3", "copy-webpack-plugin": "^4.0.1", - "copyfiles": "^1.2.0", + "copyfiles": "^2.0.0", "css-loader": "0.23.x", "exports-loader": "0.6.x", "imports-loader": "0.6.x", diff --git a/yarn.lock b/yarn.lock index c0fa4bccf..f28cfbc90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -944,7 +944,7 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" -"@types/fetch-mock@6.0.3": +"@types/fetch-mock@^6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-6.0.3.tgz#54ba90776293e728089bf53ba53e3c69f1c80655" @@ -3757,18 +3757,7 @@ copy-webpack-plugin@^4.0.1: p-limit "^1.0.0" serialize-javascript "^1.4.0" -copyfiles@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-1.2.0.tgz#a8da3ac41aa2220ae29bd3c58b6984294f2c593c" - dependencies: - glob "^7.0.5" - ltcdr "^2.2.1" - minimatch "^3.0.3" - mkdirp "^0.5.1" - noms "0.0.0" - through2 "^2.0.1" - -copyfiles@^2.0.0: +copyfiles@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.0.0.tgz#bbd78bb78e8fd6db5c67adf54249317b24560f2a" dependencies: @@ -8560,10 +8549,6 @@ lru-cache@~2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" -ltcdr@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltcdr/-/ltcdr-2.2.1.tgz#5ab87ad1d4c1dab8e8c08bbf037ee0c1902287cf" - ltgt@^2.1.2, ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" -- cgit From 622509c508272790e3e69c09cf1a1f9696815147 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 13 Aug 2018 12:23:29 +1000 Subject: [Order-utils] Order is valid when maker amount is very small Previously our min fillable calculation would throw a rounding error when encountering a valid order (with a small maker amount). This was inconsistent with the on-chain logic which allowed this order to be filled. --- packages/contracts/test/exchange/fill_order.ts | 11 ++ .../test/utils/fill_order_combinatorial_utils.ts | 7 ++ .../test/utils/order_factory_from_scenario.ts | 23 ++++ packages/contracts/test/utils/types.ts | 3 +- packages/order-utils/CHANGELOG.json | 4 + packages/order-utils/src/order_state_utils.ts | 36 +++--- .../order-utils/test/order_state_utils_test.ts | 122 +++++++++++++++++++++ packages/order-watcher/test/order_watcher_test.ts | 20 ++-- 8 files changed, 195 insertions(+), 31 deletions(-) create mode 100644 packages/order-utils/test/order_state_utils_test.ts diff --git a/packages/contracts/test/exchange/fill_order.ts b/packages/contracts/test/exchange/fill_order.ts index 1494fe093..e79e2239e 100644 --- a/packages/contracts/test/exchange/fill_order.ts +++ b/packages/contracts/test/exchange/fill_order.ts @@ -104,6 +104,17 @@ describe('FillOrder Tests', () => { }; await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario); }); + it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount with zero decimals', async () => { + const fillScenario = { + ...defaultFillScenario, + orderScenario: { + ...defaultFillScenario.orderScenario, + makerAssetAmountScenario: OrderAssetAmountScenario.Small, + makerAssetDataScenario: AssetDataScenario.ERC20ZeroDecimals, + }, + }; + await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario); + }); it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => { const fillScenario = { ...defaultFillScenario, diff --git a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts index 284c4a2db..f18ad0dd3 100644 --- a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts +++ b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts @@ -81,6 +81,12 @@ export async function fillOrderCombinatorialUtilsFactoryAsync( erc20FiveDecimalTokenCount, fiveDecimals, ); + const zeroDecimals = new BigNumber(0); + const erc20ZeroDecimalTokenCount = 2; + const [erc20ZeroDecimalTokenA, erc20ZeroDecimalTokenB] = await erc20Wrapper.deployDummyTokensAsync( + erc20ZeroDecimalTokenCount, + zeroDecimals, + ); const erc20Proxy = await erc20Wrapper.deployProxyAsync(); await erc20Wrapper.setBalancesAndAllowancesAsync(); @@ -119,6 +125,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync( zrxToken.address, [erc20EighteenDecimalTokenA.address, erc20EighteenDecimalTokenB.address], [erc20FiveDecimalTokenA.address, erc20FiveDecimalTokenB.address], + [erc20ZeroDecimalTokenA.address, erc20ZeroDecimalTokenB.address], erc721Token, erc721Balances, exchangeContract.address, diff --git a/packages/contracts/test/utils/order_factory_from_scenario.ts b/packages/contracts/test/utils/order_factory_from_scenario.ts index a908140b9..8e04db588 100644 --- a/packages/contracts/test/utils/order_factory_from_scenario.ts +++ b/packages/contracts/test/utils/order_factory_from_scenario.ts @@ -21,6 +21,8 @@ const POINT_ONE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(100_000_000_000_000_000) const POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(50_000_000_000_000_000); const TEN_UNITS_FIVE_DECIMALS = new BigNumber(1_000_000); const FIVE_UNITS_FIVE_DECIMALS = new BigNumber(500_000); +const TEN_UNITS_ZERO_DECIMALS = new BigNumber(10); +const ONE_THOUSAND_UNITS_ZERO_DECIMALS = new BigNumber(1000); const ONE_NFT_UNIT = new BigNumber(1); export class OrderFactoryFromScenario { @@ -28,6 +30,7 @@ export class OrderFactoryFromScenario { private readonly _zrxAddress: string; private readonly _nonZrxERC20EighteenDecimalTokenAddresses: string[]; private readonly _erc20FiveDecimalTokenAddresses: string[]; + private readonly _erc20ZeroDecimalTokenAddresses: string[]; private readonly _erc721Token: DummyERC721TokenContract; private readonly _erc721Balances: ERC721TokenIdsByOwner; private readonly _exchangeAddress: string; @@ -36,6 +39,7 @@ export class OrderFactoryFromScenario { zrxAddress: string, nonZrxERC20EighteenDecimalTokenAddresses: string[], erc20FiveDecimalTokenAddresses: string[], + erc20ZeroDecimalTokenAddresses: string[], erc721Token: DummyERC721TokenContract, erc721Balances: ERC721TokenIdsByOwner, exchangeAddress: string, @@ -44,6 +48,7 @@ export class OrderFactoryFromScenario { this._zrxAddress = zrxAddress; this._nonZrxERC20EighteenDecimalTokenAddresses = nonZrxERC20EighteenDecimalTokenAddresses; this._erc20FiveDecimalTokenAddresses = erc20FiveDecimalTokenAddresses; + this._erc20ZeroDecimalTokenAddresses = erc20ZeroDecimalTokenAddresses; this._erc721Token = erc721Token; this._erc721Balances = erc721Balances; this._exchangeAddress = exchangeAddress; @@ -89,6 +94,9 @@ export class OrderFactoryFromScenario { erc721MakerAssetIds[0], ); break; + case AssetDataScenario.ERC20ZeroDecimals: + makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[0]); + break; default: throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario); } @@ -109,6 +117,9 @@ export class OrderFactoryFromScenario { erc721TakerAssetIds[0], ); break; + case AssetDataScenario.ERC20ZeroDecimals: + takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[1]); + break; default: throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario); } @@ -126,6 +137,9 @@ export class OrderFactoryFromScenario { case AssetDataScenario.ERC721: makerAssetAmount = ONE_NFT_UNIT; break; + case AssetDataScenario.ERC20ZeroDecimals: + makerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS; + break; default: throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario); } @@ -142,6 +156,9 @@ export class OrderFactoryFromScenario { case AssetDataScenario.ERC721: makerAssetAmount = ONE_NFT_UNIT; break; + case AssetDataScenario.ERC20ZeroDecimals: + makerAssetAmount = TEN_UNITS_ZERO_DECIMALS; + break; default: throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario); } @@ -166,6 +183,9 @@ export class OrderFactoryFromScenario { case AssetDataScenario.ERC721: takerAssetAmount = ONE_NFT_UNIT; break; + case AssetDataScenario.ERC20ZeroDecimals: + takerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS; + break; default: throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario); } @@ -182,6 +202,9 @@ export class OrderFactoryFromScenario { case AssetDataScenario.ERC721: takerAssetAmount = ONE_NFT_UNIT; break; + case AssetDataScenario.ERC20ZeroDecimals: + takerAssetAmount = TEN_UNITS_ZERO_DECIMALS; + break; default: throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario); } diff --git a/packages/contracts/test/utils/types.ts b/packages/contracts/test/utils/types.ts index 67313b647..481ee87d6 100644 --- a/packages/contracts/test/utils/types.ts +++ b/packages/contracts/test/utils/types.ts @@ -177,10 +177,11 @@ export enum ExpirationTimeSecondsScenario { } export enum AssetDataScenario { - ERC721 = 'ERC721', + ERC20ZeroDecimals = 'ERC20_ZERO_DECIMALS', ZRXFeeToken = 'ZRX_FEE_TOKEN', ERC20FiveDecimals = 'ERC20_FIVE_DECIMALS', ERC20NonZRXEighteenDecimals = 'ERC20_NON_ZRX_EIGHTEEN_DECIMALS', + ERC721 = 'ERC721', } export enum TakerAssetFillAmountScenario { diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 6b49d2ee6..86f0da65a 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -2,6 +2,10 @@ { "version": "1.0.1-rc.4", "changes": [ + { + "note": "Remove rounding error being thrown when maker amount is very small", + "pr": 959 + }, { "note": "Added rateUtils and sortingUtils", "pr": 953 diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index 189bf4180..7974d5d0b 100644 --- a/packages/order-utils/src/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -11,6 +11,7 @@ import { BigNumber } from '@0xproject/utils'; import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher'; import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; import { orderHashUtils } from './order_hash'; +import { OrderValidationUtils } from './order_validation_utils'; import { RemainingFillableCalculator } from './remaining_fillable_calculator'; import { utils } from './utils'; @@ -22,10 +23,9 @@ interface SidedOrderRelevantState { traderFeeProxyAllowance: BigNumber; filledTakerAssetAmount: BigNumber; remainingFillableAssetAmount: BigNumber; + isOrderCancelled: boolean; } -const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001; - export class OrderStateUtils { private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; @@ -34,6 +34,9 @@ export class OrderStateUtils { sidedOrderRelevantState: SidedOrderRelevantState, ): void { const isMakerSide = sidedOrderRelevantState.isMakerSide; + if (sidedOrderRelevantState.isOrderCancelled) { + throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); + } const availableTakerAssetAmount = signedOrder.takerAssetAmount.minus( sidedOrderRelevantState.filledTakerAssetAmount, ); @@ -71,23 +74,15 @@ export class OrderStateUtils { ); } } - - let minFillableTakerAssetAmountWithinNoRoundingErrorRange; - if (isMakerSide) { - minFillableTakerAssetAmountWithinNoRoundingErrorRange = signedOrder.takerAssetAmount - .dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR) - .dividedBy(signedOrder.makerAssetAmount); - } else { - minFillableTakerAssetAmountWithinNoRoundingErrorRange = signedOrder.makerAssetAmount - .dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR) - .dividedBy(signedOrder.takerAssetAmount); - } - - if ( - sidedOrderRelevantState.remainingFillableAssetAmount.lessThan( - minFillableTakerAssetAmountWithinNoRoundingErrorRange, - ) - ) { + const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus( + sidedOrderRelevantState.filledTakerAssetAmount, + ); + const isRoundingError = OrderValidationUtils.isRoundingError( + remainingTakerAssetAmount, + signedOrder.takerAssetAmount, + signedOrder.makerAssetAmount, + ); + if (isRoundingError) { throw new Error(ExchangeContractErrs.OrderFillRoundingError); } } @@ -101,6 +96,7 @@ export class OrderStateUtils { public async getOpenOrderStateAsync(signedOrder: SignedOrder): Promise { const orderRelevantState = await this.getOpenOrderRelevantStateAsync(signedOrder); const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + const isOrderCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(orderHash); const sidedOrderRelevantState = { isMakerSide: true, traderBalance: orderRelevantState.makerBalance, @@ -109,6 +105,7 @@ export class OrderStateUtils { traderFeeProxyAllowance: orderRelevantState.makerFeeProxyAllowance, filledTakerAssetAmount: orderRelevantState.filledTakerAssetAmount, remainingFillableAssetAmount: orderRelevantState.remainingFillableMakerAssetAmount, + isOrderCancelled, }; try { OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState); @@ -278,6 +275,7 @@ export class OrderStateUtils { traderFeeProxyAllowance, filledTakerAssetAmount, remainingFillableAssetAmount, + isOrderCancelled, }; return sidedOrderRelevantState; } diff --git a/packages/order-utils/test/order_state_utils_test.ts b/packages/order-utils/test/order_state_utils_test.ts new file mode 100644 index 000000000..9292c40a4 --- /dev/null +++ b/packages/order-utils/test/order_state_utils_test.ts @@ -0,0 +1,122 @@ +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import 'mocha'; + +import { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher, OrderStateUtils } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { testOrderFactory } from './utils/test_order_factory'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('OrderStateUtils', () => { + describe('#getOpenOrderStateAsync', () => { + const buildMockBalanceFetcher = (takerBalance: BigNumber): AbstractBalanceAndProxyAllowanceFetcher => { + const balanceFetcher = { + async getBalanceAsync(_assetData: string, _userAddress: string): Promise { + return takerBalance; + }, + async getProxyAllowanceAsync(_assetData: string, _userAddress: string): Promise { + return takerBalance; + }, + }; + return balanceFetcher; + }; + const buildMockOrderFilledFetcher = ( + filledAmount: BigNumber = new BigNumber(0), + cancelled: boolean = false, + ): AbstractOrderFilledCancelledFetcher => { + const orderFetcher = { + async getFilledTakerAmountAsync(_orderHash: string): Promise { + return filledAmount; + }, + async isOrderCancelledAsync(_orderHash: string): Promise { + return cancelled; + }, + getZRXAssetData(): string { + return ''; + }, + }; + return orderFetcher; + }; + it('should have valid order state if order can be fully filled with small maker amount', async () => { + const makerAssetAmount = new BigNumber(10); + const takerAssetAmount = new BigNumber(10000000000000000); + const takerBalance = takerAssetAmount; + const orderFilledAmount = new BigNumber(0); + const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); + const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount); + const [signedOrder] = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerAssetAmount, + }, + 1, + ); + + const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); + const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); + expect(orderState.isValid).to.eq(true); + }); + it('should be invalid when an order is partially filled where only a rounding error remains', async () => { + const makerAssetAmount = new BigNumber(1001); + const takerAssetAmount = new BigNumber(3); + const takerBalance = takerAssetAmount; + const orderFilledAmount = new BigNumber(2); + const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); + const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount); + const [signedOrder] = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerAssetAmount, + }, + 1, + ); + + const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); + const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); + expect(orderState.isValid).to.eq(false); + }); + it('should be invalid when an order is cancelled', async () => { + const makerAssetAmount = new BigNumber(1000); + const takerAssetAmount = new BigNumber(2); + const takerBalance = takerAssetAmount; + const orderFilledAmount = new BigNumber(0); + const isCancelled = true; + const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); + const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled); + const [signedOrder] = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerAssetAmount, + }, + 1, + ); + + const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); + const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); + expect(orderState.isValid).to.eq(false); + }); + it('should be invalid when an order is fully filled', async () => { + const makerAssetAmount = new BigNumber(1000); + const takerAssetAmount = new BigNumber(2); + const takerBalance = takerAssetAmount; + const orderFilledAmount = takerAssetAmount; + const isCancelled = false; + const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); + const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled); + const [signedOrder] = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerAssetAmount, + }, + 1, + ); + + const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); + const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); + expect(orderState.isValid).to.eq(false); + }); + }); +}); diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index 00962bed0..0f4caeb63 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -501,25 +501,27 @@ describe('OrderWatcher', () => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; expect(invalidOrderState.orderHash).to.be.equal(orderHash); - expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); }); orderWatcher.subscribe(callback); await contractWrappers.exchange.cancelOrderAsync(signedOrder); })().catch(done); }); - it('should emit orderStateInvalid when within rounding error range', (done: DoneCallback) => { + it('should emit orderStateInvalid when within rounding error range after a partial fill', (done: DoneCallback) => { (async () => { - const remainingFillableAmountInBaseUnits = new BigNumber(100); - signedOrder = await fillScenarios.createFillableSignedOrderAsync( + const fillAmountInBaseUnits = new BigNumber(2); + const makerAssetAmount = new BigNumber(1001); + const takerAssetAmount = new BigNumber(3); + signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync( makerAssetData, takerAssetData, makerAddress, takerAddress, - fillableAmount, + makerAssetAmount, + takerAssetAmount, ); const orderHash = orderHashUtils.getOrderHashHex(signedOrder); await orderWatcher.addOrderAsync(signedOrder); - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; @@ -527,11 +529,7 @@ describe('OrderWatcher', () => { expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError); }); orderWatcher.subscribe(callback); - await contractWrappers.exchange.fillOrderAsync( - signedOrder, - fillableAmount.minus(remainingFillableAmountInBaseUnits), - takerAddress, - ); + await contractWrappers.exchange.fillOrderAsync(signedOrder, fillAmountInBaseUnits, takerAddress); })().catch(done); }); describe('erc721', () => { -- cgit From 88c99396a2d1b880bffb21ef19507d02b474ba9b Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 15 Aug 2018 13:03:31 +1000 Subject: Rename OrderAlreadyCancelledOrFilled -> OrderCancelled. Remove try catch of throwing errors in favour of returning the Errors in a OrderValidationResult --- packages/order-utils/src/order_state_utils.ts | 61 ++++++++++++---------- .../order-utils/test/order_state_utils_test.ts | 4 +- packages/order-watcher/test/order_watcher_test.ts | 2 +- packages/types/src/index.ts | 3 +- packages/website/ts/utils/utils.ts | 7 +-- 5 files changed, 40 insertions(+), 37 deletions(-) diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index 7974d5d0b..18fc18bf6 100644 --- a/packages/order-utils/src/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -25,6 +25,14 @@ interface SidedOrderRelevantState { remainingFillableAssetAmount: BigNumber; isOrderCancelled: boolean; } +interface OrderValidResult { + isValid: true; +} +interface OrderInvalidResult { + isValid: false; + error: ExchangeContractErrs; +} +type OrderValidationResult = OrderValidResult | OrderInvalidResult; export class OrderStateUtils { private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; @@ -32,46 +40,42 @@ export class OrderStateUtils { private static _validateIfOrderIsValid( signedOrder: SignedOrder, sidedOrderRelevantState: SidedOrderRelevantState, - ): void { + ): OrderValidationResult { const isMakerSide = sidedOrderRelevantState.isMakerSide; if (sidedOrderRelevantState.isOrderCancelled) { - throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); + return { isValid: false, error: ExchangeContractErrs.OrderCancelled }; } const availableTakerAssetAmount = signedOrder.takerAssetAmount.minus( sidedOrderRelevantState.filledTakerAssetAmount, ); if (availableTakerAssetAmount.eq(0)) { - throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero); + return { isValid: false, error: ExchangeContractErrs.OrderRemainingFillAmountZero }; } if (sidedOrderRelevantState.traderBalance.eq(0)) { - throw new Error( - isMakerSide - ? ExchangeContractErrs.InsufficientMakerBalance - : ExchangeContractErrs.InsufficientTakerBalance, - ); + const error = isMakerSide + ? ExchangeContractErrs.InsufficientMakerBalance + : ExchangeContractErrs.InsufficientTakerBalance; + return { isValid: false, error }; } if (sidedOrderRelevantState.traderProxyAllowance.eq(0)) { - throw new Error( - isMakerSide - ? ExchangeContractErrs.InsufficientMakerAllowance - : ExchangeContractErrs.InsufficientTakerAllowance, - ); + const error = isMakerSide + ? ExchangeContractErrs.InsufficientMakerAllowance + : ExchangeContractErrs.InsufficientTakerAllowance; + return { isValid: false, error }; } if (!signedOrder.makerFee.eq(0)) { if (sidedOrderRelevantState.traderFeeBalance.eq(0)) { - throw new Error( - isMakerSide - ? ExchangeContractErrs.InsufficientMakerFeeBalance - : ExchangeContractErrs.InsufficientTakerFeeBalance, - ); + const error = isMakerSide + ? ExchangeContractErrs.InsufficientMakerFeeBalance + : ExchangeContractErrs.InsufficientTakerFeeBalance; + return { isValid: false, error }; } if (sidedOrderRelevantState.traderFeeProxyAllowance.eq(0)) { - throw new Error( - isMakerSide - ? ExchangeContractErrs.InsufficientMakerFeeAllowance - : ExchangeContractErrs.InsufficientTakerFeeAllowance, - ); + const error = isMakerSide + ? ExchangeContractErrs.InsufficientMakerFeeAllowance + : ExchangeContractErrs.InsufficientTakerFeeAllowance; + return { isValid: false, error }; } } const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus( @@ -83,8 +87,9 @@ export class OrderStateUtils { signedOrder.makerAssetAmount, ); if (isRoundingError) { - throw new Error(ExchangeContractErrs.OrderFillRoundingError); + return { isValid: false, error: ExchangeContractErrs.OrderFillRoundingError }; } + return { isValid: true }; } constructor( balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher, @@ -107,19 +112,19 @@ export class OrderStateUtils { remainingFillableAssetAmount: orderRelevantState.remainingFillableMakerAssetAmount, isOrderCancelled, }; - try { - OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState); + const orderValidationResult = OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState); + if (orderValidationResult.isValid) { const orderState: OrderStateValid = { isValid: true, orderHash, orderRelevantState, }; return orderState; - } catch (err) { + } else { const orderState: OrderStateInvalid = { isValid: false, orderHash, - error: err.message, + error: orderValidationResult.error, }; return orderState; } diff --git a/packages/order-utils/test/order_state_utils_test.ts b/packages/order-utils/test/order_state_utils_test.ts index 9292c40a4..91ef23b69 100644 --- a/packages/order-utils/test/order_state_utils_test.ts +++ b/packages/order-utils/test/order_state_utils_test.ts @@ -2,7 +2,9 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import 'mocha'; -import { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher, OrderStateUtils } from '../src'; +import { AbstractBalanceAndProxyAllowanceFetcher } from '../src/abstract/abstract_balance_and_proxy_allowance_fetcher'; +import { AbstractOrderFilledCancelledFetcher } from '../src/abstract/abstract_order_filled_cancelled_fetcher'; +import { OrderStateUtils } from '../src/order_state_utils'; import { chaiSetup } from './utils/chai_setup'; import { testOrderFactory } from './utils/test_order_factory'; diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index 0f4caeb63..38bfde7ef 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -501,7 +501,7 @@ describe('OrderWatcher', () => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; expect(invalidOrderState.orderHash).to.be.equal(orderHash); - expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderCancelled); }); orderWatcher.subscribe(callback); await contractWrappers.exchange.cancelOrderAsync(signedOrder); diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index fa634420d..04480d093 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -62,8 +62,7 @@ export interface ValidatorSignature { export enum ExchangeContractErrs { OrderFillExpired = 'ORDER_FILL_EXPIRED', OrderCancelExpired = 'ORDER_CANCEL_EXPIRED', - OrderCancelAmountZero = 'ORDER_CANCEL_AMOUNT_ZERO', - OrderAlreadyCancelledOrFilled = 'ORDER_ALREADY_CANCELLED_OR_FILLED', + OrderCancelled = 'ORDER_CANCELLED', OrderFillAmountZero = 'ORDER_FILL_AMOUNT_ZERO', OrderRemainingFillAmountZero = 'ORDER_REMAINING_FILL_AMOUNT_ZERO', OrderFillRoundingError = 'ORDER_FILL_ROUNDING_ERROR', diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 39bbd404c..32b07473c 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -247,12 +247,9 @@ export const utils = { } = { [ExchangeContractErrs.OrderFillExpired]: 'This order has expired', [ExchangeContractErrs.OrderCancelExpired]: 'This order has expired', - [ExchangeContractErrs.OrderCancelAmountZero]: "Order cancel amount can't be 0", - [ExchangeContractErrs.OrderAlreadyCancelledOrFilled]: - 'This order has already been completely filled or cancelled', + [ExchangeContractErrs.OrderCancelled]: 'This order has been cancelled', [ExchangeContractErrs.OrderFillAmountZero]: "Order fill amount can't be 0", - [ExchangeContractErrs.OrderRemainingFillAmountZero]: - 'This order has already been completely filled or cancelled', + [ExchangeContractErrs.OrderRemainingFillAmountZero]: 'This order has already been completely filled', [ExchangeContractErrs.OrderFillRoundingError]: 'Rounding error will occur when filling this order. Please try filling a different amount.', [ExchangeContractErrs.InsufficientTakerBalance]: -- cgit