Compare commits

..

143 Commits

Author SHA1 Message Date
Leonid Logvinov
fe1b7f15e8 Publish
- 0x.js@2.0.4
 - @0x/abi-gen@1.0.16
 - @0x/abi-gen-wrappers@1.0.5
 - @0x/assert@1.0.17
 - @0x/asset-buyer@3.0.0
 - @0x/base-contract@3.0.6
 - @0x/connect@3.0.6
 - @0x/contract-wrappers@4.0.2
 - contracts@2.1.54
 - @0x/dev-tools-pages@0.0.6
 - @0x/dev-utils@1.0.17
 - @0x/fill-scenarios@1.0.12
 - @0x/instant@0.0.7
 - @0x/json-schemas@2.1.1
 - @0x/metacoin@0.0.28
 - @0x/migrations@2.0.4
 - @0x/order-utils@3.0.2
 - @0x/order-watcher@2.2.4
 - @0x/react-docs@1.0.18
 - @0x/react-shared@1.0.21
 - @0x/sol-compiler@1.1.12
 - @0x/sol-cov@2.1.12
 - @0x/sol-doc@1.0.7
 - @0x/sra-spec@1.0.10
 - @0x/subproviders@2.1.4
 - @0x/testnet-faucets@1.0.56
 - @0x/utils@2.0.5
 - @0x/web3-wrapper@3.1.4
 - @0x/website@0.0.59
2018-11-14 16:16:46 +01:00
Leonid Logvinov
3f647c259a Updated CHANGELOGS 2018-11-14 16:16:32 +01:00
Leonid Logvinov
06dcf24496 Merge pull request #1259 from 0xProject/feature/ow-zrx-bug
[@0x/order-watcher] Fix a bug in an order removal when maker token is ZRX
2018-11-14 16:04:25 +01:00
Leonid Logvinov
77c77631e1 Add a comment 2018-11-14 16:03:19 +01:00
Leonid Logvinov
b0e9f58033 Fix a bug in an order-watcher order removal when maker token is ZRX 2018-11-14 15:41:58 +01:00
Francesco Agosti
4fc457b78b Merge pull request #1242 from 0xProject/feature/instant/metamask-connect-flow
[instant] Install/Unlock MetaMask, connect PaymentDropdown to redux state
2018-11-13 17:31:38 -08:00
fragosti
2f6b1273aa Merge branch 'feature/instant/metamask-connect-flow' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-13 17:12:51 -08:00
fragosti
da9de70bbc Merge https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-13 17:09:58 -08:00
Steve Klebanoff
b174a891bc Merge pull request #1255 from 0xProject/feature/instant/metamask-connect-flow-input-fix
[instant] Fix input bug
2018-11-13 16:19:15 -08:00
Steve Klebanoff
bb79a5e324 linting 2018-11-13 15:18:29 -08:00
Steve Klebanoff
9e0c232a73 Remove ConnectedZeroExInstantContainer, introduce ConnectedBuyOrderProgressOrPaymentMethod 2018-11-13 15:07:21 -08:00
Brandon Millman
e02dc13805 Merge pull request #1252 from 0xProject/fix/asset-buyer/price-per-token
[asset-buyer][instant] Fix incorrect token prices for non 18-decimal tokens
2018-11-13 14:35:09 -08:00
Brandon Millman
820ab062a6 chore(instant): fix prettier 2018-11-13 14:18:19 -08:00
F. Eugene Aumson
7b4f63a39c feat(order_utils.py) generate_order_hash_hex() (#1234) 2018-11-13 16:30:12 -05:00
Brandon Millman
3a3fe0e69a Merge branch 'development' into fix/asset-buyer/price-per-token
* development:
  Publish
  Updated CHANGELOGS
  Fix a bug when undefined was been tried to convert to an array
  feat(instant): add extra asset metadata
  chore: fix linter error
  Improve logo spacing
  fix: lowercase supplied address before comparing with derived addresses (which are not checksummed)
  Remove unused instance variable
  update yarn.lock
  Increase logo size
  Replace remaining scroll-links with Link component
  Adjust paddin
  Fix menuItem background colors depending on the context
  Remove "Home" menu item, instead make different parts of logo link to different sections of the website
  Rename tutorial to match verb structure
  chore: Make `External exports` clickable on sidebar
  style: reduce border size on version dropdown
  style: make line-height of sidebar title 26px, make sure still bottom aligned with version picker
  Update yarn.lock
  style: remove small gap under topbar
2018-11-13 11:38:20 -08:00
Fabio B
5c21d3f6af Merge pull request #1244 from 0xProject/developerSectionNits
Remaining Developer Section Design Nits
2018-11-13 20:36:48 +01:00
Brandon Millman
baba78f545 chore(asset-buyer): update changelog to major version bump 2018-11-13 11:36:19 -08:00
fragosti
f03afe6f1b Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-13 10:46:19 -08:00
Leonid Logvinov
a824264da2 Publish
- 0x.js@2.0.3
 - @0x/abi-gen-wrappers@1.0.4
 - @0x/asset-buyer@2.2.2
 - @0x/base-contract@3.0.5
 - @0x/connect@3.0.5
 - @0x/contract-wrappers@4.0.1
 - contracts@2.1.53
 - @0x/dev-tools-pages@0.0.5
 - @0x/dev-utils@1.0.16
 - @0x/fill-scenarios@1.0.11
 - @0x/instant@0.0.6
 - @0x/metacoin@0.0.27
 - @0x/migrations@2.0.3
 - @0x/order-utils@3.0.1
 - @0x/order-watcher@2.2.3
 - @0x/react-docs@1.0.17
 - @0x/react-shared@1.0.20
 - @0x/sol-compiler@1.1.11
 - @0x/sol-cov@2.1.11
 - @0x/sol-doc@1.0.6
 - @0x/subproviders@2.1.3
 - @0x/testnet-faucets@1.0.55
 - @0x/web3-wrapper@3.1.3
 - @0x/website@0.0.58
2018-11-13 19:41:43 +01:00
Leonid Logvinov
a66c03aa21 Updated CHANGELOGS 2018-11-13 19:41:25 +01:00
fragosti
bed134c1da chore: PR feedback 2018-11-13 10:37:42 -08:00
fragosti
d36cf58b82 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-13 10:37:27 -08:00
Brandon Millman
5527de62ff chore(instant): update selectedAssetAmount in the redux state to be named selectedAssetUnitAmount 2018-11-13 10:29:21 -08:00
Leonid Logvinov
11f0bebd7f Fix a bug when undefined was been tried to convert to an array 2018-11-13 19:27:44 +01:00
Fabio B
3fb29041b0 Merge pull request #1248 from 0xProject/fixLowercaseAddressBug
Fix lowercase address bug in LedgerSubprovider and MnemonicSubprovider
2018-11-13 15:03:30 +01:00
Brandon Millman
161a935003 Merge pull request #1251 from 0xProject/feature/instant/asset-data-map
[instant] Add extra asset metadata
2018-11-12 21:48:34 -08:00
Brandon Millman
e8afc66a5a chore(asset-buyer): update changelog 2018-11-12 20:51:37 -08:00
Brandon Millman
49a9345bf4 feat(instant): calculate per unit eth amount to populate OrderDetails component 2018-11-12 20:50:28 -08:00
Brandon Millman
d73faf1b81 fix(asset-buyer): output assetEthAmount instead of ethPerAssetPrice in BuyQuoteInfos 2018-11-12 20:50:27 -08:00
fragosti
0c6110b736 chore: run linter 2018-11-12 18:50:18 -08:00
fragosti
2da258f5be feat: use Omit type to improve type defitions in some containers 2018-11-12 18:48:20 -08:00
fragosti
e9bf7206bd chore: remove unused constant 2018-11-12 18:34:45 -08:00
fragosti
2b4dcb419e fix: rename handler creator name 2018-11-12 17:48:13 -08:00
fragosti
c67632dff5 feat: make all button fontsizes 16px by default 2018-11-12 17:42:56 -08:00
fragosti
01b36b4949 fix: remove requirement of default case in all switch statements 2018-11-12 17:30:28 -08:00
fragosti
711b307e6c feat: prevent eth balance blink 2018-11-12 17:09:28 -08:00
fragosti
1ab19a7c23 Merge branch 'feature/instant/asset-data-map' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-12 15:11:36 -08:00
fragosti
7068f7b4d1 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-12 15:10:46 -08:00
fragosti
79f0324abc feat: integrate wallet flow with heartbeat and other branches 2018-11-12 13:30:47 -08:00
Brandon Millman
b82148ea60 feat(instant): add extra asset metadata 2018-11-12 13:26:09 -08:00
Fabio B
add1cfd261 Merge pull request #1227 from WyseNynja/patch-1
[web3-wrapper] start jsonRpcRequestId at 1, not 0
2018-11-12 20:43:00 +01:00
Bryan Stitt
cdf78494d5 Update CHANGELOG.json 2018-11-12 09:12:59 -08:00
Bryan Stitt
789f573452 Merge branch 'development' into patch-1 2018-11-12 09:10:40 -08:00
Bryan Stitt
22f217807d Update CHANGELOG.json 2018-11-12 09:08:23 -08:00
Fabio B
08797392e0 Update packages/order-watcher/CHANGELOG.json
Co-Authored-By: WyseNynja <bryan@stitthappens.com>
2018-11-12 09:08:02 -08:00
Leonid Logvinov
853c77dc09 Update packages/order-watcher/CHANGELOG.json
Co-Authored-By: WyseNynja <bryan@stitthappens.com>
2018-11-12 09:07:54 -08:00
Leonid Logvinov
0ebbbdfca4 Publish
- 0x.js@2.0.2
 - @0x/abi-gen-wrappers@1.0.3
 - @0x/assert@1.0.16
 - @0x/asset-buyer@2.2.1
 - @0x/base-contract@3.0.4
 - @0x/connect@3.0.4
 - @0x/contract-wrappers@4.0.0
 - contracts@2.1.52
 - @0x/dev-tools-pages@0.0.4
 - @0x/dev-utils@1.0.15
 - @0x/fill-scenarios@1.0.10
 - @0x/instant@0.0.5
 - @0x/json-schemas@2.1.0
 - @0x/metacoin@0.0.26
 - @0x/migrations@2.0.2
 - @0x/order-utils@3.0.0
 - @0x/order-watcher@2.2.2
 - @0x/react-docs@1.0.16
 - @0x/react-shared@1.0.19
 - @0x/sol-compiler@1.1.10
 - @0x/sol-cov@2.1.10
 - @0x/sol-doc@1.0.5
 - @0x/sra-spec@1.0.9
 - @0x/subproviders@2.1.2
 - @0x/testnet-faucets@1.0.54
 - @0x/web3-wrapper@3.1.2
 - @0x/website@0.0.57
2018-11-12 14:30:26 +01:00
Leonid Logvinov
085d34834b Updated CHANGELOGS 2018-11-12 14:30:14 +01:00
Leonid Logvinov
b866ce787c Merge pull request #1250 from 0xProject/feature/json-schemas-connect
Move @0x/connect schemas to @0x/json-schemas
2018-11-12 14:04:28 +01:00
Leonid Logvinov
4d5bc8b8ee Fix static tests 2018-11-12 13:54:38 +01:00
Leonid Logvinov
7f013515e7 Add PR number 2018-11-12 13:53:39 +01:00
Fabio Berger
a4a46dc076 chore: fix linter error 2018-11-12 13:50:23 +01:00
Leonid Logvinov
33dbdb0184 Move connect schemas to JSON Schemas 2018-11-12 13:44:24 +01:00
Fabio Berger
0d565fe32f Improve logo spacing 2018-11-12 13:27:14 +01:00
Fabio Berger
320460feb9 fix: lowercase supplied address before comparing with derived addresses (which are not checksummed) 2018-11-12 13:21:25 +01:00
Fabio Berger
dbce3f8935 Remove unused instance variable 2018-11-12 13:20:41 +01:00
Fabio B
c41622c20a Merge pull request #1235 from 0xProject/fixOrderValidation
[order-utils] Fix order validation method
2018-11-12 12:17:27 +01:00
Fabio Berger
348556a544 Add fixes affecting the public interface to the CHANGELOGs 2018-11-12 12:07:19 +01:00
Fabio Berger
6fa6579c31 Use correctly formatted signature so that it rejects with the expected reason and not because the signature is mal-formatted 2018-11-12 11:57:54 +01:00
Fabio B
6f61268514 Merge pull request #1246 from 0xProject/bug/web3-wrapper/eth-call-null
[web3-wrapper] Throws when contract returns null
2018-11-12 10:42:28 +01:00
Fabio Berger
8efc6c2112 Remove unnecessary conversion to BigNumber 2018-11-12 10:25:33 +01:00
Fabio Berger
b21c1bea46 Use rejectedWith 2018-11-12 10:23:42 +01:00
Fabio Berger
fd7ba3ecea Use RevertReason when possible 2018-11-12 10:22:22 +01:00
Fabio Berger
8aeb18bcc3 rename param 2018-11-12 10:22:03 +01:00
Brandon Millman
9e4a594eb1 Merge pull request #1238 from 0xProject/fix/website/code-splitting
[website] Fix code splitting
2018-11-11 21:21:36 -08:00
Brandon Millman
3b421ef796 fix(website): fix code splitting 2018-11-11 20:58:47 -08:00
Jacob Evans
e0c4f58970 bug(web3-wrapper): throws when contract returns null 2018-11-12 13:55:46 +11:00
Amir Bandeali
df8fd36c94 Merge pull request #1241 from 0xProject/feature/contracts/changelogs
Add CHANGELOG.json to contracts package
2018-11-11 15:57:21 -08:00
Bryan Stitt
76b3caa124 Update CHANGELOG.json 2018-11-11 15:13:42 -08:00
Bryan Stitt
0101cd73aa Merge branch 'development' into patch-1 2018-11-11 15:13:09 -08:00
Bryan Stitt
6ef628613e update changelog 2018-11-11 15:09:59 -08:00
Amir Bandeali
bc960fe8f8 Add CHANGELOG comment to README 2018-11-11 14:57:24 -08:00
Amir Bandeali
517c620397 Add CHANGELOG.json 2018-11-11 14:57:24 -08:00
Fabio Berger
498be7ac41 update yarn.lock 2018-11-11 22:11:40 +01:00
Fabio Berger
0391f93490 merge development 2018-11-11 22:11:10 +01:00
Fabio Berger
399a7d5fec Increase logo size 2018-11-11 22:07:58 +01:00
Fabio Berger
0d201173ef Replace remaining scroll-links with Link component 2018-11-11 17:51:00 +01:00
Fabio Berger
2d43f312c8 Adjust paddin 2018-11-11 16:50:08 +01:00
Fabio Berger
1ec8a4115f Fix menuItem background colors depending on the context 2018-11-11 16:48:31 +01:00
Fabio Berger
753b33aec5 Remove "Home" menu item, instead make different parts of logo link to different sections of the website 2018-11-11 15:31:52 +01:00
Fabio Berger
7626d1d6fe Rename tutorial to match verb structure 2018-11-11 14:54:07 +01:00
Fabio Berger
d3592d362e address linter errors 2018-11-11 13:02:45 +01:00
fragosti
a8a1ea92a6 fix: no longer refer to error account state 2018-11-09 16:30:38 -08:00
fragosti
ff027ee36a Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-09 16:22:36 -08:00
Brandon Millman
397b4e2890 Merge pull request #1239 from 0xProject/feature/instant/privacy-mode
[instant] Handle privacy mode in wallets
2018-11-09 16:21:32 -08:00
fragosti
ba292ead45 fix: set all button font sizes in buy flow to 16px 2018-11-09 16:20:39 -08:00
fragosti
5355f3c538 fix: remove unused ProgressBar from BuyOrderProgress and fix issue where payment method is not shown for pending metamask confirmation 2018-11-09 16:16:04 -08:00
fragosti
478330c12d fix: minimize height difference between different states 2018-11-09 16:06:58 -08:00
Brandon Millman
38896c9358 feat(instant): handle privacy mode in wallets 2018-11-09 16:04:29 -08:00
Steve Klebanoff
26cbe7ae66 Merge pull request #1237 from 0xProject/feature/instant/buy-quote-heartbeat
[instant] Heartbeats for account info and buy quotes
2018-11-09 16:02:09 -08:00
Steve Klebanoff
fd83ca2cb8 linting 2018-11-09 15:52:25 -08:00
fragosti
b1376059d3 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-09 15:43:03 -08:00
Steve Klebanoff
4072076965 Don't start heartbeat if no account 2018-11-09 15:40:13 -08:00
fragosti
2bba01c664 feat: toggle wallet connection color 2018-11-09 15:40:02 -08:00
Steve Klebanoff
93054ae52b Lodash noop 2018-11-09 15:28:29 -08:00
Steve Klebanoff
5c1b1a1203 Using built in intervalUtils instead of rolling own 2018-11-09 15:28:08 -08:00
fragosti
433fb3597d feat: refactor button styles and add href to Text 2018-11-09 15:26:57 -08:00
Steve Klebanoff
acb7e876b2 Update account more frequently 2018-11-09 15:19:16 -08:00
Steve Klebanoff
2c585bfbdc feat(instant): Dismissible overlay error messages
Adds dismissible overlay to error messages on mobile
2018-11-09 15:15:57 -08:00
Fabio Berger
1f0ac47bd9 Move signature validation into OrderValidationUtils.validateOrderFillableOrThrowAsync 2018-11-10 00:14:48 +01:00
fragosti
7460f2796a feat: add more info section to the metamask panel 2018-11-09 15:11:47 -08:00
fragosti
7249cc7b49 feat: allow href prop on button 2018-11-09 15:08:01 -08:00
fragosti
b598827708 feat: implement basic StandardModalContent with accompanying InstallWalletPanelContent 2018-11-09 14:57:29 -08:00
fragosti
128abb39dd feat: add padding to close icon to increase tap area 2018-11-09 14:21:41 -08:00
fragosti
79a533940e feat: open metamask sliding panel if locked on click 2018-11-09 14:20:14 -08:00
Fabio Berger
773cf3cd14 Merge branch 'development' into fixOrderValidation
* development: (25 commits)
  Publish
  Updated CHANGELOGS
  fix(instant): fix bug where we potentially fetch balance for the wrong account
  fix: Lock Ledger hw-transport to 4.24.0
  fix: wrong prop names used
  chore: PR feedback
  fix: broken features because of merge
  fix: remove default props, fix lint problems
  chore: convert payment method to stateless component
  feat: add boxShadow on dropdown hover
  fix: various style issues
  fix: remove all:initial rule from all div based ui compoennts
  fix: token selector scrolling container height
  chore(instant): fix lint errors
  feat(instant): fetch balance at startup
  feat(instant): fetch account address at startup and drive account state changes
  chore: cleanup
  fix: restore button to previous state
  feat: implement copy-to-clipboard
  feat: add MetaMask sign, refactor Circle
  ...
2018-11-09 23:20:06 +01:00
Fabio Berger
53d0f5b98e Revert comment change 2018-11-09 23:15:34 +01:00
fragosti
3a51bd1e69 feat: create connect metamask 2018-11-09 13:56:04 -08:00
fragosti
3f1f19e344 feat: connect payment method to state and display different content based on account state 2018-11-09 13:41:32 -08:00
fragosti
3aa831ad77 feat: add account payment method container 2018-11-09 13:29:28 -08:00
fragosti
3fd667b3be feat: make zero ex instant container switch between progress and payment 2018-11-09 13:23:01 -08:00
fragosti
fa7bd072d0 feat: refactor progress bar code to expose static progress bar 2018-11-09 13:19:59 -08:00
Steve Klebanoff
cc8debe53b Linting and renaming variables 2018-11-09 11:39:36 -08:00
Steve Klebanoff
36b8c9c5dd Use interface like named parameters here 2018-11-09 11:28:08 -08:00
Steve Klebanoff
474db7c18d Emulate named parameters with interface 2018-11-09 11:22:46 -08:00
fragosti
daa011f7cb feat: implement CurrentStandardSlidingPanel and put it in the main container 2018-11-09 11:15:32 -08:00
Steve Klebanoff
39657b633b Make sure we only update price when they are not in the middle of an order 2018-11-09 11:04:44 -08:00
Steve Klebanoff
2e8f74abce Use existing functions instead of writing our own 2018-11-09 10:40:47 -08:00
fragosti
239eada7d9 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-09 10:34:14 -08:00
Steve Klebanoff
df91d34315 Merge branch 'development' into feature/instant/buy-quote-heartbeat 2018-11-09 10:06:22 -08:00
Fabio Berger
3980bf39a9 Keep more helpful error messages, and stop swallowing errors when returning contract error 2018-11-09 18:50:25 +01:00
fragosti
a50f0ca997 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow 2018-11-08 17:38:46 -08:00
Steve Klebanoff
d703c13f8e Variable name cleanup 2018-11-08 17:21:17 -08:00
Steve Klebanoff
3dacc6157b Remove unneeded Promise.resolve 2018-11-08 17:20:15 -08:00
Steve Klebanoff
fd12bdbbd5 Remove old TODO 2018-11-08 17:13:33 -08:00
Steve Klebanoff
297a62fe80 move files around and rename 2018-11-08 17:13:22 -08:00
Steve Klebanoff
1e39d56cf7 wip: BuyQuote heartbeat 2018-11-08 17:09:26 -08:00
fragosti
39ae21d693 feat: allow panel children to fill entire content / remove title from panel component 2018-11-08 16:58:44 -08:00
Steve Klebanoff
e45b6c7e98 Make heartbeat more generic 2018-11-08 16:54:45 -08:00
fragosti
fc138cd73d feat: add metamask logo 2018-11-08 16:40:21 -08:00
fragosti
990d510d05 feat: add lock icon 2018-11-08 16:40:21 -08:00
Steve Klebanoff
dd4d3b10cf wip: abstract out updating buy quote 2018-11-08 16:14:00 -08:00
Fabio Berger
eb5f514d25 Merge branch 'development' into fixOrderValidation
* development: (51 commits)
  [instant] Viewport specific errors (#1228)
  Added more comments
  Include wholeNumberSchema in sra-spec schemas
  chore(instant): fix linter
  Fix isNode
  fix(instant): update buy quote at start up in the case of default amount
  chore(instant): increase max bundle size for bundle watch
  Small code review tweaks
  fix: apply css reset to overlay as well
  fix(website): turn off production flag when building locally
  feat(instant): add Account to the ProviderState
  feat(instant): fallback to an empty wallet provider when none is injected
  [order_utils.py] is_signature_valid, via Exchange contract (#1216)
  chore: linter
  fix: progress bar
  fix: use fontSize prop in button
  feat: make instant resistant to external styles
  chore(instant): update OrderState enum to follow capitalization conventions
  feat: add faux externall css file
  Take out unneeded conditionals
  ...
2018-11-09 00:46:32 +01:00
Fabio Berger
57318a6ef2 Remove unused validateFillOrKill method 2018-11-09 00:46:07 +01:00
Fabio Berger
857a35d4f7 Fix validateOrderFillableOrThrowAsync method so it also checks order signature, cancelled, cancelledUpTo, and throws helpful error messages 2018-11-09 00:45:48 +01:00
Steve Klebanoff
624f5cee8d linting 2018-11-08 15:01:59 -08:00
Steve Klebanoff
7acaae37a9 feat(instant): Heartbeat for updating account info 2018-11-08 14:57:39 -08:00
Bryan Stitt
801004be66 start jsonRpcRequestId at 1, not 0
I'm trying to use the 0x-watcher against a parity websocket rpc and getting an error that I think is the same as https://github.com/ethereum/web3.js/issues/1967
2018-11-07 16:39:07 -08:00
Fabio Berger
81fb8d614f chore: Make External exports clickable on sidebar 2018-10-26 17:19:53 +02:00
Fabio Berger
3e75daafa1 style: reduce border size on version dropdown 2018-10-26 14:01:15 +02:00
Fabio Berger
6696aa46ee style: make line-height of sidebar title 26px, make sure still bottom aligned with version picker 2018-10-26 14:01:00 +02:00
Fabio Berger
14a9770d57 Update yarn.lock 2018-10-26 13:52:39 +02:00
Fabio Berger
b8d2cc1221 style: remove small gap under topbar 2018-10-26 13:52:29 +02:00
217 changed files with 2792 additions and 859 deletions

View File

@@ -1,4 +1,31 @@
[
{
"timestamp": 1542208198,
"version": "2.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542134075,
"version": "2.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "2.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.0.1",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.0.4 - _November 14, 2018_
* Dependencies updated
## v2.0.3 - _November 13, 2018_
* Dependencies updated
## v2.0.2 - _November 12, 2018_
* Dependencies updated
## v2.0.1 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "0x.js",
"version": "2.0.1",
"version": "2.0.4",
"engines": {
"node": ">=6.12"
},
@@ -42,11 +42,11 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@0x/abi-gen": "^1.0.15",
"@0x/abi-gen-wrappers": "^1.0.2",
"@0x/abi-gen": "^1.0.16",
"@0x/abi-gen-wrappers": "^1.0.5",
"@0x/contract-addresses": "^1.1.0",
"@0x/dev-utils": "^1.0.14",
"@0x/migrations": "^2.0.1",
"@0x/dev-utils": "^1.0.17",
"@0x/migrations": "^2.0.4",
"@0x/tslint-config": "^1.0.10",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
@@ -73,16 +73,16 @@
"webpack": "^4.20.2"
},
"dependencies": {
"@0x/assert": "^1.0.15",
"@0x/base-contract": "^3.0.3",
"@0x/contract-wrappers": "^3.0.1",
"@0x/order-utils": "^2.0.1",
"@0x/order-watcher": "^2.2.1",
"@0x/subproviders": "^2.1.1",
"@0x/assert": "^1.0.17",
"@0x/base-contract": "^3.0.6",
"@0x/contract-wrappers": "^4.0.2",
"@0x/order-utils": "^3.0.2",
"@0x/order-watcher": "^2.2.4",
"@0x/subproviders": "^2.1.4",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"@types/web3-provider-engine": "^14.0.0",
"ethereum-types": "^1.1.2",
"ethers": "~4.0.4",

View File

@@ -1,4 +1,31 @@
[
{
"timestamp": 1542208198,
"version": "1.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542134075,
"version": "1.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "1.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.2",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.5 - _November 14, 2018_
* Dependencies updated
## v1.0.4 - _November 13, 2018_
* Dependencies updated
## v1.0.3 - _November 12, 2018_
* Dependencies updated
## v1.0.2 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/abi-gen-wrappers",
"version": "1.0.2",
"version": "1.0.5",
"engines": {
"node": ">=6.12"
},
@@ -30,17 +30,17 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md",
"devDependencies": {
"@0x/abi-gen": "^1.0.15",
"@0x/abi-gen": "^1.0.16",
"@0x/tslint-config": "^1.0.10",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"ethereum-types": "^1.1.2",
"ethers": "~4.0.4",
"lodash": "^4.17.5",
"shx": "^0.2.2"
},
"dependencies": {
"@0x/base-contract": "^3.0.3"
"@0x/base-contract": "^3.0.6"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1542208198,
"version": "1.0.16",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.15",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.16 - _November 14, 2018_
* Dependencies updated
## v1.0.15 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/abi-gen",
"version": "1.0.15",
"version": "1.0.16",
"engines": {
"node": ">=6.12"
},
@@ -32,7 +32,7 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/utils": "^2.0.5",
"chalk": "^2.3.0",
"ethereum-types": "^1.1.2",
"glob": "^7.1.2",

View File

@@ -1,4 +1,22 @@
[
{
"timestamp": 1542208198,
"version": "1.0.17",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "1.0.16",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.15",
"changes": [

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.17 - _November 14, 2018_
* Dependencies updated
## v1.0.16 - _November 12, 2018_
* Dependencies updated
## v1.0.15 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/assert",
"version": "1.0.15",
"version": "1.0.17",
"engines": {
"node": ">=6.12"
},
@@ -44,9 +44,9 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/json-schemas": "^2.0.1",
"@0x/json-schemas": "^2.1.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/utils": "^2.0.5",
"lodash": "^4.17.5",
"valid-url": "^1.0.9"
},

View File

@@ -1,4 +1,32 @@
[
{
"version": "3.0.0",
"changes": [
{
"note": "update `getBuyQuoteAsync` to return eth spent on assets instead of per unit amount",
"pr": 1252
}
],
"timestamp": 1542208198
},
{
"timestamp": 1542134075,
"version": "2.2.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "2.2.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.2.0",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.0.0 - _November 14, 2018_
* update `getBuyQuoteAsync` to return eth spent on assets instead of per unit amount (#1252)
## v2.2.2 - _November 13, 2018_
* Dependencies updated
## v2.2.1 - _November 12, 2018_
* Dependencies updated
## v2.2.0 - _November 9, 2018_
* `getAssetBuyerForProvidedOrders` factory function now takes 3 args instead of 4 (#1187)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/asset-buyer",
"version": "2.2.0",
"version": "3.0.0",
"engines": {
"node": ">=6.12"
},
@@ -36,16 +36,16 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
"dependencies": {
"@0x/assert": "^1.0.15",
"@0x/connect": "^3.0.3",
"@0x/contract-wrappers": "^3.0.1",
"@0x/json-schemas": "^2.0.1",
"@0x/order-utils": "^2.0.1",
"@0x/subproviders": "^2.1.1",
"@0x/assert": "^1.0.17",
"@0x/connect": "^3.0.6",
"@0x/contract-wrappers": "^4.0.2",
"@0x/json-schemas": "^2.1.1",
"@0x/order-utils": "^3.0.2",
"@0x/subproviders": "^2.1.4",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"ethereum-types": "^1.1.2",
"lodash": "^4.17.10"
},

View File

@@ -54,12 +54,12 @@ export interface BuyQuote {
}
/**
* ethPerAssetPrice: The price of one unit of the desired asset in ETH
* assetEthAmount: The amount of eth required to pay for the requested asset.
* feeEthAmount: The amount of eth required to pay the affiliate fee.
* totalEthAmount: the total amount of eth required to complete the buy. (Filling orders, feeOrders, and paying affiliate fee)
* totalEthAmount: The total amount of eth required to complete the buy (filling orders, feeOrders, and paying affiliate fee).
*/
export interface BuyQuoteInfo {
ethPerAssetPrice: BigNumber;
assetEthAmount: BigNumber;
feeEthAmount: BigNumber;
totalEthAmount: BigNumber;
}

View File

@@ -18,7 +18,7 @@ export const assert = {
}
},
isValidBuyQuoteInfo(variableName: string, buyQuoteInfo: BuyQuoteInfo): void {
sharedAssert.isBigNumber(`${variableName}.ethPerAssetPrice`, buyQuoteInfo.ethPerAssetPrice);
sharedAssert.isBigNumber(`${variableName}.assetEthAmount`, buyQuoteInfo.assetEthAmount);
sharedAssert.isBigNumber(`${variableName}.feeEthAmount`, buyQuoteInfo.feeEthAmount);
sharedAssert.isBigNumber(`${variableName}.totalEthAmount`, buyQuoteInfo.totalEthAmount);
},

View File

@@ -106,28 +106,28 @@ function calculateQuoteInfo(
isMakerAssetZrxToken: boolean,
): BuyQuoteInfo {
// find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right
let ethAmountToBuyAsset = constants.ZERO_AMOUNT;
let ethAmountToBuyZrx = constants.ZERO_AMOUNT;
let assetEthAmount = constants.ZERO_AMOUNT;
let zrxEthAmount = constants.ZERO_AMOUNT;
if (isMakerAssetZrxToken) {
ethAmountToBuyAsset = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
assetEthAmount = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
} else {
// find eth and zrx amounts needed to buy
const ethAndZrxAmountToBuyAsset = findEthAndZrxAmountNeededToBuyAsset(ordersAndFillableAmounts, assetBuyAmount);
ethAmountToBuyAsset = ethAndZrxAmountToBuyAsset[0];
assetEthAmount = ethAndZrxAmountToBuyAsset[0];
const zrxAmountToBuyAsset = ethAndZrxAmountToBuyAsset[1];
// find eth amount needed to buy zrx
ethAmountToBuyZrx = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
zrxEthAmount = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
}
/// find the eth amount needed to buy the affiliate fee
const ethAmountToBuyAffiliateFee = ethAmountToBuyAsset.mul(feePercentage).ceil();
const totalEthAmountWithoutAffiliateFee = ethAmountToBuyAsset.plus(ethAmountToBuyZrx);
const ethAmountTotal = totalEthAmountWithoutAffiliateFee.plus(ethAmountToBuyAffiliateFee);
// divide into the assetBuyAmount in order to find rate of makerAsset / WETH
const ethPerAssetPrice = totalEthAmountWithoutAffiliateFee.div(assetBuyAmount);
// eth amount needed to buy the affiliate fee
const affiliateFeeEthAmount = assetEthAmount.mul(feePercentage).ceil();
// eth amount needed for fees is the sum of affiliate fee and zrx fee
const feeEthAmount = affiliateFeeEthAmount.plus(zrxEthAmount);
// eth amount needed in total is the sum of the amount needed for the asset and the amount needed for fees
const totalEthAmount = assetEthAmount.plus(feeEthAmount);
return {
totalEthAmount: ethAmountTotal,
feeEthAmount: ethAmountToBuyAffiliateFee,
ethPerAssetPrice,
assetEthAmount,
feeEthAmount,
totalEthAmount,
};
}

View File

@@ -108,17 +108,17 @@ describe('buyQuoteCalculator', () => {
// 50 eth to fill the first order + 100 eth for fees
const expectedEthAmountForAsset = new BigNumber(50);
const expectedEthAmountForZrxFees = new BigNumber(100);
const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
const expectedFillEthAmount = expectedEthAmountForAsset;
const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount);
expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
// because we have no slippage protection, minRate is equal to maxRate
expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
// test if feePercentage gets passed through
expect(buyQuote.feePercentage).to.equal(feePercentage);
});
@@ -146,23 +146,23 @@ describe('buyQuoteCalculator', () => {
// 50 eth to fill the first order + 100 eth for fees
const expectedEthAmountForAsset = new BigNumber(50);
const expectedEthAmountForZrxFees = new BigNumber(100);
const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
const expectedFillEthAmount = expectedEthAmountForAsset;
const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount);
expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
// 100 eth to fill the first order + 208 eth for fees
const expectedWorstEthAmountForAsset = new BigNumber(100);
const expectedWorstEthAmountForZrxFees = new BigNumber(208);
const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset.plus(expectedWorstEthAmountForZrxFees);
const expectedWorstFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage);
const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset;
const expectedWorstAffiliateFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage);
const expectedWorstFeeEthAmount = expectedWorstAffiliateFeeEthAmount.plus(expectedWorstEthAmountForZrxFees);
const expectedWorstTotalEthAmount = expectedWorstFillEthAmount.plus(expectedWorstFeeEthAmount);
const expectedWorstEthPerAssetPrice = expectedWorstFillEthAmount.div(assetBuyAmount);
expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedWorstFillEthAmount);
expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedWorstFeeEthAmount);
expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedWorstTotalEthAmount);
expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedWorstEthPerAssetPrice);
// test if feePercentage gets passed through
expect(buyQuote.feePercentage).to.equal(feePercentage);
});

View File

@@ -1,4 +1,31 @@
[
{
"timestamp": 1542208198,
"version": "3.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542134075,
"version": "3.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "3.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.3",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.0.6 - _November 14, 2018_
* Dependencies updated
## v3.0.5 - _November 13, 2018_
* Dependencies updated
## v3.0.4 - _November 12, 2018_
* Dependencies updated
## v3.0.3 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/base-contract",
"version": "3.0.3",
"version": "3.0.6",
"engines": {
"node": ">=6.12"
},
@@ -41,8 +41,8 @@
},
"dependencies": {
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"ethereum-types": "^1.1.2",
"ethers": "~4.0.4",
"lodash": "^4.17.5"

View File

@@ -1,4 +1,31 @@
[
{
"timestamp": 1542208198,
"version": "3.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542134075,
"version": "3.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "3.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.3",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.0.6 - _November 14, 2018_
* Dependencies updated
## v3.0.5 - _November 13, 2018_
* Dependencies updated
## v3.0.4 - _November 12, 2018_
* Dependencies updated
## v3.0.3 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/connect",
"version": "3.0.3",
"version": "3.0.6",
"engines": {
"node": ">=6.12"
},
@@ -44,12 +44,12 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
"dependencies": {
"@0x/assert": "^1.0.15",
"@0x/json-schemas": "^2.0.1",
"@0x/order-utils": "^2.0.1",
"@0x/assert": "^1.0.17",
"@0x/json-schemas": "^2.1.1",
"@0x/order-utils": "^3.0.2",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/utils": "^2.0.5",
"lodash": "^4.17.5",
"query-string": "^5.0.1",
"sinon": "^4.0.0",

View File

@@ -19,7 +19,6 @@ import { fetchAsync } from '@0x/utils';
import * as _ from 'lodash';
import * as queryString from 'query-string';
import { schemas as clientSchemas } from './schemas/schemas';
import { Client, HttpRequestOptions, HttpRequestType } from './types';
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
@@ -61,9 +60,9 @@ export class HttpClient implements Client {
requestOpts?: RequestOpts & AssetPairsRequestOpts & PagedRequestOpts,
): Promise<AssetPairsResponse> {
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.assetPairsRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.assetPairsRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
}
const httpRequestOpts = {
params: requestOpts,
@@ -81,9 +80,9 @@ export class HttpClient implements Client {
requestOpts?: RequestOpts & OrdersRequestOpts & PagedRequestOpts,
): Promise<OrdersResponse> {
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.ordersRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
}
const httpRequestOpts = {
params: requestOpts,
@@ -99,7 +98,7 @@ export class HttpClient implements Client {
*/
public async getOrderAsync(orderHash: string, requestOpts?: RequestOpts): Promise<APIOrder> {
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
}
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const httpRequestOpts = {
@@ -119,10 +118,10 @@ export class HttpClient implements Client {
request: OrderbookRequest,
requestOpts?: RequestOpts & PagedRequestOpts,
): Promise<OrderbookResponse> {
assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema);
assert.doesConformToSchema('request', request, schemas.orderBookRequestSchema);
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
}
const httpRequestOpts = {
params: _.defaults({}, request, requestOpts),
@@ -142,9 +141,9 @@ export class HttpClient implements Client {
requestOpts?: RequestOpts,
): Promise<OrderConfigResponse> {
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
}
assert.doesConformToSchema('request', request, clientSchemas.orderConfigRequestSchema);
assert.doesConformToSchema('request', request, schemas.orderConfigRequestSchema);
const httpRequestOpts = {
params: requestOpts,
payload: request,
@@ -160,8 +159,8 @@ export class HttpClient implements Client {
*/
public async getFeeRecipientsAsync(requestOpts?: RequestOpts & PagedRequestOpts): Promise<FeeRecipientsResponse> {
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
}
const httpRequestOpts = {
params: requestOpts,

View File

@@ -1,8 +0,0 @@
export const assetPairsRequestOptsSchema = {
id: '/AssetPairsRequestOpts',
type: 'object',
properties: {
assetDataA: { $ref: '/hexSchema' },
assetDataB: { $ref: '/hexSchema' },
},
};

View File

@@ -1,24 +0,0 @@
export const orderConfigRequestSchema = {
id: '/OrderConfigRequest',
type: 'object',
properties: {
makerAddress: { $ref: '/addressSchema' },
takerAddress: { $ref: '/addressSchema' },
makerAssetAmount: { $ref: '/numberSchema' },
takerAssetAmount: { $ref: '/numberSchema' },
makerAssetData: { $ref: '/hexSchema' },
takerAssetData: { $ref: '/hexSchema' },
exchangeAddress: { $ref: '/addressSchema' },
expirationTimeSeconds: { $ref: '/numberSchema' },
},
required: [
'makerAddress',
'takerAddress',
'makerAssetAmount',
'takerAssetAmount',
'makerAssetData',
'takerAssetData',
'exchangeAddress',
'expirationTimeSeconds',
],
};

View File

@@ -1,9 +0,0 @@
export const orderBookRequestSchema = {
id: '/OrderBookRequest',
type: 'object',
properties: {
baseAssetData: { $ref: '/hexSchema' },
quoteAssetData: { $ref: '/hexSchema' },
},
required: ['baseAssetData', 'quoteAssetData'],
};

View File

@@ -1,19 +0,0 @@
export const ordersRequestOptsSchema = {
id: '/OrdersRequestOpts',
type: 'object',
properties: {
makerAssetProxyId: { $ref: '/hexSchema' },
takerAssetProxyId: { $ref: '/hexSchema' },
makerAssetAddress: { $ref: '/addressSchema' },
takerAssetAddress: { $ref: '/addressSchema' },
exchangeAddress: { $ref: '/addressSchema' },
senderAddress: { $ref: '/addressSchema' },
makerAssetData: { $ref: '/hexSchema' },
takerAssetData: { $ref: '/hexSchema' },
traderAssetData: { $ref: '/hexSchema' },
makerAddress: { $ref: '/addressSchema' },
takerAddress: { $ref: '/addressSchema' },
traderAddress: { $ref: '/addressSchema' },
feeRecipientAddress: { $ref: '/addressSchema' },
},
};

View File

@@ -1,8 +0,0 @@
export const pagedRequestOptsSchema = {
id: '/PagedRequestOpts',
type: 'object',
properties: {
page: { type: 'number' },
perPage: { type: 'number' },
},
};

View File

@@ -1,7 +0,0 @@
export const requestOptsSchema = {
id: '/RequestOpts',
type: 'object',
properties: {
networkId: { type: 'number' },
},
};

View File

@@ -1,15 +0,0 @@
import { assetPairsRequestOptsSchema } from './asset_pairs_request_opts_schema';
import { orderConfigRequestSchema } from './order_config_request_schema';
import { orderBookRequestSchema } from './orderbook_request_schema';
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
import { requestOptsSchema } from './request_opts_schema';
export const schemas = {
orderConfigRequestSchema,
orderBookRequestSchema,
ordersRequestOptsSchema,
pagedRequestOptsSchema,
requestOptsSchema,
assetPairsRequestOptsSchema,
};

View File

@@ -1,4 +1,43 @@
[
{
"timestamp": 1542208198,
"version": "4.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542134075,
"version": "4.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "4.0.0",
"changes": [
{
"note":
"Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync`",
"pr": 1235
},
{
"note":
"Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive",
"pr": 1235
},
{
"note":
"Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218)",
"pr": 1235
}
],
"timestamp": 1542028948
},
{
"version": "3.0.1",
"changes": [

View File

@@ -5,6 +5,20 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.0.2 - _November 14, 2018_
* Dependencies updated
## v4.0.1 - _November 13, 2018_
* Dependencies updated
## v4.0.0 - _November 12, 2018_
* Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync` (#1235)
* Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive (#1235)
* Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218) (#1235)
## v3.0.1 - _November 9, 2018_
* Fix bug in `ForwarderWrapper` where `feeRecipientAddress` was not correctly normalized. (#1178)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contract-wrappers",
"version": "3.0.1",
"version": "4.0.2",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -37,9 +37,9 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0x/dev-utils": "^1.0.14",
"@0x/migrations": "^2.0.1",
"@0x/subproviders": "^2.1.1",
"@0x/dev-utils": "^1.0.17",
"@0x/migrations": "^2.0.4",
"@0x/subproviders": "^2.1.4",
"@0x/tslint-config": "^1.0.10",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
@@ -65,17 +65,17 @@
"web3-provider-engine": "14.0.6"
},
"dependencies": {
"@0x/abi-gen-wrappers": "^1.0.2",
"@0x/assert": "^1.0.15",
"@0x/abi-gen-wrappers": "^1.0.5",
"@0x/assert": "^1.0.17",
"@0x/contract-addresses": "^1.1.0",
"@0x/contract-artifacts": "^1.1.0",
"@0x/fill-scenarios": "^1.0.9",
"@0x/json-schemas": "^2.0.1",
"@0x/order-utils": "^2.0.1",
"@0x/fill-scenarios": "^1.0.12",
"@0x/json-schemas": "^2.1.1",
"@0x/order-utils": "^3.0.2",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"ethereum-types": "^1.1.2",
"ethereumjs-blockstream": "6.0.0",
"ethereumjs-util": "^5.1.1",

View File

@@ -18,6 +18,7 @@ import { OrderFilledCancelledFetcher } from '../fetchers/order_filled_cancelled_
import { methodOptsSchema } from '../schemas/method_opts_schema';
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
import { txOptsSchema } from '../schemas/tx_opts_schema';
import { validateOrderFillableOptsSchema } from '../schemas/validate_order_fillable_opts_schema';
import {
BlockRange,
EventCallback,
@@ -1114,6 +1115,9 @@ export class ExchangeWrapper extends ContractWrapper {
signedOrder: SignedOrder,
opts: ValidateOrderFillableOpts = {},
): Promise<void> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
assert.doesConformToSchema('opts', opts, validateOrderFillableOptsSchema);
const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
this._erc20TokenWrapper,
this._erc721TokenWrapper,
@@ -1124,7 +1128,7 @@ export class ExchangeWrapper extends ContractWrapper {
const expectedFillTakerTokenAmountIfExists = opts.expectedFillTakerTokenAmount;
const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider());
await orderValidationUtils.validateOrderFillableOrThrowAsync(
exchangeTradeSimulator,
signedOrder,
@@ -1152,7 +1156,7 @@ export class ExchangeWrapper extends ContractWrapper {
const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore);
const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider());
await orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
exchangeTradeSimulator,
this._web3Wrapper.getProvider(),

View File

@@ -1,5 +1,6 @@
// tslint:disable:no-unnecessary-type-assertion
import { AbstractOrderFilledCancelledFetcher } from '@0x/order-utils';
import { AbstractOrderFilledCancelledFetcher, orderHashUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BlockParamLiteral } from 'ethereum-types';
@@ -18,9 +19,18 @@ export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelled
});
return filledTakerAmount;
}
public async isOrderCancelledAsync(orderHash: string): Promise<boolean> {
public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> {
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const isCancelled = await this._exchange.isCancelledAsync(orderHash);
return isCancelled;
const orderEpoch = await this._exchange.getOrderEpochAsync(
signedOrder.makerAddress,
signedOrder.senderAddress,
{
defaultBlock: this._stateLayer,
},
);
const isCancelledByOrderEpoch = orderEpoch > signedOrder.salt;
return isCancelled || isCancelledByOrderEpoch;
}
public getZRXAssetData(): string {
const zrxAssetData = this._exchange.getZRXAssetData();

View File

@@ -0,0 +1,7 @@
export const validateOrderFillableOptsSchema = {
id: '/ValidateOrderFillableOpts',
properties: {
expectedFillTakerTokenAmount: { $ref: '/wholeNumberSchema' },
},
type: 'object',
};

View File

@@ -1,7 +1,7 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
import { FillScenarios } from '@0x/fill-scenarios';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { DoneCallback, SignedOrder } from '@0x/types';
import { DoneCallback, RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
@@ -282,6 +282,19 @@ describe('ExchangeWrapper', () => {
expect(ordersInfo[1].orderHash).to.be.equal(anotherOrderHash);
});
});
describe('#validateOrderFillableOrThrowAsync', () => {
it('should throw if signature is invalid', async () => {
const signedOrderWithInvalidSignature = {
...signedOrder,
signature:
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403',
};
expect(
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrderWithInvalidSignature),
).to.eventually.to.be.rejectedWith(RevertReason.InvalidOrderSignature);
});
});
describe('#isValidSignature', () => {
it('should check if the signature is valid', async () => {
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);

View File

@@ -0,0 +1,115 @@
[
{
"name": "Forwarder",
"version": "1.1.0",
"changes": [
{
"note": "Round up when calculating remaining amounts in marketBuy functions",
"pr": 1162,
"networks": {
"1": "0x5468a1dc173652ee28d249c271fa9933144746b1",
"3": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e",
"42": "0x17992e4ffb22730138e4b62aaa6367fa9d3699a6"
}
}
]
},
{
"name": "Forwarder",
"version": "1.0.0",
"changes": [
{
"note": "protocol v2 deploy",
"networks": {
"1": "0x7afc2d5107af94c462a194d2c21b5bdd238709d6",
"3": "0x3983e204b12b3c02fb0638caf2cd406a62e0ead3",
"42": "0xd85e2fa7e7e252b27b01bf0d65c946959d2f45b8"
}
}
]
},
{
"name": "OrderValidator",
"version": "1.0.0",
"changes": [
{
"note": "protocol v2 deploy",
"networks": {
"1": "0x9463e518dea6810309563c81d5266c1b1d149138",
"3": "0x90431a90516ab49af23a0530e04e8c7836e7122f",
"42": "0xb389da3d204b412df2f75c6afb3d0a7ce0bc283d"
}
}
]
},
{
"name": "Exchange",
"version": "2.0.0",
"changes": [
{
"note": "protocol v2 deploy",
"networks": {
"1": "0x4f833a24e1f95d70f028921e27040ca56e09ab0b",
"3": "0x4530c0483a1633c7a1c97d2c53721caff2caaaaf",
"42": "0x35dd2932454449b14cee11a94d3674a936d5d7b2"
}
}
]
},
{
"name": "ERC20Proxy",
"version": "1.0.0",
"changes": [
{
"note": "protocol v2 deploy",
"networks": {
"1": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e",
"3": "0xb1408f4c245a23c31b98d2c626777d4c0d766caa",
"42": "0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e"
}
}
]
},
{
"name": "ERC721Proxy",
"version": "1.0.0",
"changes": [
{
"note": "protocol v2 deploy",
"networks": {
"1": "0x208e41fb445f1bb1b6780d58356e81405f3e6127",
"3": "0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4",
"42": "0x2a9127c745688a165106c11cd4d647d2220af821"
}
}
]
},
{
"name": "AssetProxyOwner",
"version": "1.0.0",
"changes": [
{
"note": "protocol v2 deploy",
"networks": {
"1": "0x17992e4ffb22730138e4b62aaa6367fa9d3699a6",
"3": "0xf5fa5b5fed2727a0e44ac67f6772e97977aa358b",
"42": "0x2c824d2882baa668e0d5202b1e7f2922278703f8"
}
}
]
},
{
"name": "ZRXToken",
"version": "1.0.0",
"changes": [
{
"note": "protocol v1 deploy",
"networks": {
"1": "0xe41d2489571d322189246dafa5ebde1f4699f498",
"3": "0xff67881f8d12f372d91baae9752eb3631ff0ed00",
"42": "0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa"
}
}
]
}
]

View File

@@ -1,6 +1,6 @@
## Contracts
Smart contracts that implement the 0x protocol. Addresses of the deployed contracts can be found [here](https://0xproject.com/wiki#Deployed-Addresses).
Smart contracts that implement the 0x protocol. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [CHANGELOG](./CHANGELOG.json) of this package.
## Usage

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "contracts",
"version": "2.1.51",
"version": "2.1.54",
"engines": {
"node": ">=6.12"
},
@@ -45,11 +45,11 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
"devDependencies": {
"@0x/abi-gen": "^1.0.15",
"@0x/dev-utils": "^1.0.14",
"@0x/sol-compiler": "^1.1.9",
"@0x/sol-cov": "^2.1.9",
"@0x/subproviders": "^2.1.1",
"@0x/abi-gen": "^1.0.16",
"@0x/dev-utils": "^1.0.17",
"@0x/sol-compiler": "^1.1.12",
"@0x/sol-cov": "^2.1.12",
"@0x/subproviders": "^2.1.4",
"@0x/tslint-config": "^1.0.10",
"@types/bn.js": "^4.11.0",
"@types/ethereumjs-abi": "^0.6.0",
@@ -71,12 +71,12 @@
"yargs": "^10.0.3"
},
"dependencies": {
"@0x/base-contract": "^3.0.3",
"@0x/order-utils": "^2.0.1",
"@0x/base-contract": "^3.0.6",
"@0x/order-utils": "^3.0.2",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"@types/js-combinatorics": "^0.5.29",
"bn.js": "^4.11.8",
"ethereum-types": "^1.1.2",

View File

@@ -212,13 +212,17 @@ export class ExchangeWrapper {
return tx;
}
public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
const filledAmount = new BigNumber(await this._exchange.filled.callAsync(orderHashHex));
const filledAmount = await this._exchange.filled.callAsync(orderHashHex);
return filledAmount;
}
public async isCancelledAsync(orderHashHex: string): Promise<boolean> {
const isCancelled = await this._exchange.cancelled.callAsync(orderHashHex);
return isCancelled;
}
public async getOrderEpochAsync(makerAddress: string, senderAddress: string): Promise<BigNumber> {
const orderEpoch = await this._exchange.orderEpoch.callAsync(makerAddress, senderAddress);
return orderEpoch;
}
public async getOrderInfoAsync(signedOrder: SignedOrder): Promise<OrderInfo> {
const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo;
return orderInfo;

View File

@@ -392,7 +392,7 @@ export class FillOrderCombinatorialUtils {
);
// 5. If I fill it by X, what are the resulting balances/allowances/filled amounts expected?
const orderValidationUtils = new OrderValidationUtils(orderFilledCancelledFetcher);
const orderValidationUtils = new OrderValidationUtils(orderFilledCancelledFetcher, provider);
const lazyStore = new BalanceAndProxyAllowanceLazyStore(balanceAndProxyAllowanceFetcher);
const exchangeTransferSimulator = new ExchangeTransferSimulator(lazyStore);

View File

@@ -1,4 +1,5 @@
import { AbstractOrderFilledCancelledFetcher } from '@0x/order-utils';
import { AbstractOrderFilledCancelledFetcher, orderHashUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { ExchangeWrapper } from './exchange_wrapper';
@@ -14,9 +15,15 @@ export class SimpleOrderFilledCancelledFetcher implements AbstractOrderFilledCan
const filledTakerAmount = new BigNumber(await this._exchangeWrapper.getTakerAssetFilledAmountAsync(orderHash));
return filledTakerAmount;
}
public async isOrderCancelledAsync(orderHash: string): Promise<boolean> {
public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> {
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const isCancelled = await this._exchangeWrapper.isCancelledAsync(orderHash);
return isCancelled;
const orderEpoch = await this._exchangeWrapper.getOrderEpochAsync(
signedOrder.makerAddress,
signedOrder.senderAddress,
);
const isCancelledByOrderEpoch = orderEpoch > signedOrder.salt;
return isCancelled || isCancelledByOrderEpoch;
}
public getZRXAssetData(): string {
return this._zrxAssetData;

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/dev-tools-pages",
"version": "0.0.3",
"version": "0.0.6",
"engines": {
"node": ">=6.12"
},
@@ -16,7 +16,7 @@
},
"license": "Apache-2.0",
"dependencies": {
"@0x/react-shared": "^1.0.18",
"@0x/react-shared": "^1.0.21",
"basscss": "^8.0.3",
"bowser": "^1.9.3",
"less": "^2.7.2",

View File

@@ -1,4 +1,31 @@
[
{
"timestamp": 1542208198,
"version": "1.0.17",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542134075,
"version": "1.0.16",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "1.0.15",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.14",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.17 - _November 14, 2018_
* Dependencies updated
## v1.0.16 - _November 13, 2018_
* Dependencies updated
## v1.0.15 - _November 12, 2018_
* Dependencies updated
## v1.0.14 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/dev-utils",
"version": "1.0.14",
"version": "1.0.17",
"engines": {
"node": ">=6.12"
},
@@ -41,11 +41,11 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/subproviders": "^2.1.1",
"@0x/subproviders": "^2.1.4",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"@types/web3-provider-engine": "^14.0.0",
"chai": "^4.0.1",
"ethereum-types": "^1.1.2",

View File

@@ -1,4 +1,31 @@
[
{
"timestamp": 1542208198,
"version": "1.0.12",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542134075,
"version": "1.0.11",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542028948,
"version": "1.0.10",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.9",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.12 - _November 14, 2018_
* Dependencies updated
## v1.0.11 - _November 13, 2018_
* Dependencies updated
## v1.0.10 - _November 12, 2018_
* Dependencies updated
## v1.0.9 - _November 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/fill-scenarios",
"version": "1.0.9",
"version": "1.0.12",
"description": "0x order fill scenario generator",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -28,14 +28,14 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/abi-gen-wrappers": "^1.0.2",
"@0x/base-contract": "^3.0.3",
"@0x/abi-gen-wrappers": "^1.0.5",
"@0x/base-contract": "^3.0.6",
"@0x/contract-artifacts": "^1.1.0",
"@0x/order-utils": "^2.0.1",
"@0x/order-utils": "^3.0.2",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"ethereum-types": "^1.1.2",
"ethers": "~4.0.4",
"lodash": "^4.17.5"

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/instant",
"version": "0.0.4",
"version": "0.0.7",
"engines": {
"node": ">=6.12"
},
@@ -45,15 +45,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": {
"@0x/assert": "^1.0.15",
"@0x/asset-buyer": "^2.2.0",
"@0x/json-schemas": "^2.0.1",
"@0x/order-utils": "^2.0.1",
"@0x/subproviders": "^2.1.1",
"@0x/assert": "^1.0.17",
"@0x/asset-buyer": "^3.0.0",
"@0x/json-schemas": "^2.1.1",
"@0x/order-utils": "^3.0.2",
"@0x/subproviders": "^2.1.4",
"@0x/types": "^1.2.1",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.4",
"@0x/web3-wrapper": "^3.1.1",
"@0x/utils": "^2.0.5",
"@0x/web3-wrapper": "^3.1.4",
"copy-to-clipboard": "^3.0.8",
"ethereum-types": "^1.1.2",
"lodash": "^4.17.10",

View File

@@ -1,10 +1,10 @@
import * as React from 'react';
import { OptionallyScreenSpecific } from '../../style/media';
import { SlideAnimationState } from '../../types';
import { PositionAnimation, PositionAnimationSettings } from './position_animation';
export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none';
export interface SlideAnimationProps {
animationState: SlideAnimationState;
slideInSettings: OptionallyScreenSpecific<PositionAnimationSettings>;

View File

@@ -43,7 +43,6 @@ export class BuyButton extends React.Component<BuyButtonProps> {
onClick={this._handleClick}
isDisabled={shouldDisableButton}
fontColor={ColorOption.white}
fontSize="20px"
>
Buy
</Button>

View File

@@ -12,7 +12,6 @@ export interface BuyOrderProgressProps {
export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> = props => {
const { buyOrderState } = props;
if (
buyOrderState.processState === OrderProcessState.Processing ||
buyOrderState.processState === OrderProcessState.Success ||
@@ -30,6 +29,5 @@ export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> =
</Container>
);
}
return null;
};

View File

@@ -35,7 +35,7 @@ export const BuyOrderStateButtons: React.StatelessComponent<BuyOrderStateButtonP
if (props.buyOrderProcessingState === OrderProcessState.Failure) {
return (
<Flex justify="space-between">
<Button width="48%" onClick={props.onRetry} fontColor={ColorOption.white} fontSize="16px">
<Button width="48%" onClick={props.onRetry} fontColor={ColorOption.white}>
Back
</Button>
<SecondaryButton width="48%" onClick={props.onViewTransaction}>

View File

@@ -29,13 +29,18 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
const { tokens, onTokenSelect } = this.props;
return (
<Container height="100%">
<Container marginBottom="10px">
<Text fontColor={ColorOption.darkGrey} fontSize="18px" fontWeight="600" lineHeight="22px">
Select Token
</Text>
</Container>
<SearchInput
placeholder="Search tokens..."
width="100%"
value={this.state.searchQuery}
onChange={this._handleSearchInputChange}
/>
<Container overflow="scroll" height="calc(100% - 80px)" marginTop="10px">
<Container overflow="scroll" height="calc(100% - 90px)" marginTop="10px">
{_.map(tokens, token => {
if (!this._isTokenQueryMatch(token)) {
return null;

View File

@@ -0,0 +1,32 @@
import * as React from 'react';
import { META_MASK_CHROME_STORE_URL, META_MASK_SITE_URL } from '../constants';
import { ColorOption } from '../style/theme';
import { MetaMaskLogo } from './meta_mask_logo';
import { StandardPanelContent } from './standard_panel_content';
import { Button } from './ui/button';
export interface InstallWalletPanelContentProps {}
export const InstallWalletPanelContent: React.StatelessComponent<InstallWalletPanelContentProps> = () => (
<StandardPanelContent
image={<MetaMaskLogo width={85} height={80} />}
title="Install MetaMask"
description="Please install the MetaMask wallet extension from the Chrome Store."
moreInfoSettings={{
href: META_MASK_SITE_URL,
text: 'What is MetaMask?',
}}
action={
<Button
href={META_MASK_CHROME_STORE_URL}
width="100%"
fontColor={ColorOption.white}
backgroundColor={ColorOption.darkOrange}
>
Get Chrome Extension
</Button>
}
/>
);

View File

@@ -15,8 +15,8 @@ import { Spinner } from './ui/spinner';
import { Text } from './ui/text';
export interface InstantHeadingProps {
selectedAssetAmount?: BigNumber;
totalEthBaseAmount?: BigNumber;
selectedAssetUnitAmount?: BigNumber;
totalEthBaseUnitAmount?: BigNumber;
ethUsdPrice?: BigNumber;
quoteRequestState: AsyncProcessState;
buyOrderState: OrderState;
@@ -104,7 +104,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
if (this.props.quoteRequestState === AsyncProcessState.Pending) {
return <AmountPlaceholder isPulsating={true} color={PLACEHOLDER_COLOR} />;
}
if (_.isUndefined(this.props.selectedAssetAmount)) {
if (_.isUndefined(this.props.selectedAssetUnitAmount)) {
return <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />;
}
return amountFunction();
@@ -113,8 +113,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
private readonly _renderEthAmount = (): React.ReactNode => {
return (
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
{format.ethBaseAmount(
this.props.totalEthBaseAmount,
{format.ethBaseUnitAmount(
this.props.totalEthBaseUnitAmount,
4,
<AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
)}
@@ -125,8 +125,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
private readonly _renderDollarAmount = (): React.ReactNode => {
return (
<Text fontSize="16px" fontColor={ColorOption.white}>
{format.ethBaseAmountInUsd(
this.props.totalEthBaseAmount,
{format.ethBaseUnitAmountInUsd(
this.props.totalEthBaseUnitAmount,
this.props.ethUsdPrice,
2,
<AmountPlaceholder isPulsating={false} color={ColorOption.white} />,

View File

@@ -0,0 +1,78 @@
import * as React from 'react';
export interface MetaMaskLogoProps {
width?: number;
height?: number;
}
export const MetaMaskLogo: React.StatelessComponent<MetaMaskLogoProps> = ({ width, height }) => (
<svg width={width} height={height} viewBox="0 0 85 80" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M80.578 0L47.7107 24.8648L53.542 10.2702L80.578 0Z" fill="#E2761B" />
<path d="M4.24075 0L37.1081 25.4053L31.2768 10.2702L4.24075 0Z" fill="#E4761B" />
<path d="M68.9152 57.8379L59.9032 71.8919L78.9874 77.2973L84.2886 58.3785L68.9152 57.8379Z" fill="#E4761B" />
<path d="M0.53006 58.3785L5.83124 77.2973L24.9155 71.8919L15.9035 57.8379L0.53006 58.3785Z" fill="#E4761B" />
<path d="M23.8552 34.5941L18.554 42.7022L37.1082 43.7833L36.5781 23.2428L23.8552 34.5941Z" fill="#E4761B" />
<path d="M60.9635 34.5941L47.7106 23.2428V43.7833L66.2647 42.7022L60.9635 34.5941Z" fill="#E4761B" />
<path d="M24.9156 71.8914L36.0481 66.4861L26.5059 58.378L24.9156 71.8914Z" fill="#E4761B" />
<path d="M48.7709 66.4861L59.9034 71.8914L58.313 58.378L48.7709 66.4861Z" fill="#E4761B" />
<path d="M59.9034 71.8919L48.7709 66.4865L49.301 73.5135V76.7567L59.9034 71.8919Z" fill="#D7C1B3" />
<path d="M24.9157 71.892L35.518 76.7568V73.5136L36.0482 66.4866L24.9157 71.892Z" fill="#D7C1B3" />
<path d="M35.5179 53.5138L25.9758 50.8111L32.8673 47.5678L35.5179 53.5138Z" fill="#233447" />
<path d="M49.3009 53.5138L51.9515 47.5678L58.843 50.8111L49.3009 53.5138Z" fill="#233447" />
<path d="M24.9155 71.892L26.5059 57.838L15.9035 58.3785L24.9155 71.892Z" fill="#CD6116" />
<path d="M58.313 57.838L59.9034 71.892L68.9154 58.3785L58.313 57.838Z" fill="#CD6116" />
<path
d="M66.2648 42.7025L47.7106 43.7836L49.301 53.5132L51.9516 47.5673L58.8431 50.8106L66.2648 42.7025Z"
fill="#CD6116"
/>
<path
d="M25.9758 50.8106L32.8673 47.5673L35.5179 53.5132L37.1083 43.7836L18.5541 42.7025L25.9758 50.8106Z"
fill="#CD6116"
/>
<path d="M18.5541 42.7024L26.5059 58.378L25.9758 50.8105L18.5541 42.7024Z" fill="#E4751F" />
<path d="M58.8431 50.8106L58.313 58.3781L66.2647 42.7025L58.8431 50.8106Z" fill="#E4751F" />
<path d="M37.1083 43.7838L35.518 53.5135L37.6384 65.4053L38.1686 49.7297L37.1083 43.7838Z" fill="#E4751F" />
<path d="M47.7105 43.7838L46.6503 49.7297L47.1804 65.4053L49.3009 53.5135L47.7105 43.7838Z" fill="#E4751F" />
<path
d="M49.301 53.5134L47.1805 65.4052L48.7709 66.4863L58.313 58.3782L58.8431 50.8107L49.301 53.5134Z"
fill="#F6851B"
/>
<path
d="M25.9758 50.8107L26.5059 58.3782L36.048 66.4863L37.6384 65.4052L35.5179 53.5134L25.9758 50.8107Z"
fill="#F6851B"
/>
<path
d="M49.3011 76.7568V73.5135L48.771 72.973H36.0482L35.518 73.5135V76.7568L24.9157 71.8919L28.6265 75.1351L36.0482 80H48.771L56.1927 75.1351L59.9035 71.8919L49.3011 76.7568Z"
fill="#C0AD9E"
/>
<path
d="M48.771 66.486L47.1806 65.405H37.6385L36.0482 66.486L35.518 73.513L36.0482 72.9725H48.771L49.3011 73.513L48.771 66.486Z"
fill="#161616"
/>
<path
d="M82.1685 26.4864L84.8191 12.9729L80.5781 0L48.771 24.3242L60.9637 34.5945L78.4576 39.9998L82.1685 35.6755L80.5781 34.0539L83.2287 31.8918L81.1082 30.2702L83.7588 28.108L82.1685 26.4864Z"
fill="#763D16"
/>
<path
d="M0 12.9729L2.65059 26.4864L1.06024 28.108L3.71083 30.2702L1.59036 31.8918L4.24095 34.0539L2.65059 35.6755L6.36142 39.9998L23.8553 34.5945L36.0481 24.3242L4.24095 0L0 12.9729Z"
fill="#763D16"
/>
<path
d="M78.4575 39.9993L60.9636 34.5939L66.2648 42.702L58.313 58.3776H68.9154H84.2888L78.4575 39.9993Z"
fill="#F6851B"
/>
<path
d="M23.8554 34.5939L6.36147 39.9993L0.530167 58.3776H15.9036H26.506L18.5542 42.702L23.8554 34.5939Z"
fill="#F6851B"
/>
<path
d="M47.7106 43.7833L48.7709 24.3239L53.5419 10.2699H31.2769L36.048 24.3239L37.1083 43.7833L37.6384 49.7292V65.4048H47.1805V49.7292L47.7106 43.7833Z"
fill="#F6851B"
/>
</svg>
);
MetaMaskLogo.defaultProps = {
width: 85,
height: 80,
};

View File

@@ -4,6 +4,7 @@ import * as _ from 'lodash';
import * as React from 'react';
import { oc } from 'ts-optchain';
import { BIG_NUMBER_ZERO } from '../constants';
import { ColorOption } from '../style/theme';
import { format } from '../util/format';
@@ -15,16 +16,23 @@ import { Text } from './ui/text';
export interface OrderDetailsProps {
buyQuoteInfo?: BuyQuoteInfo;
selectedAssetUnitAmount?: BigNumber;
ethUsdPrice?: BigNumber;
isLoading: boolean;
}
export class OrderDetails extends React.Component<OrderDetailsProps> {
public render(): React.ReactNode {
const { buyQuoteInfo, ethUsdPrice } = this.props;
const { buyQuoteInfo, ethUsdPrice, selectedAssetUnitAmount } = this.props;
const buyQuoteAccessor = oc(buyQuoteInfo);
const ethAssetPrice = buyQuoteAccessor.ethPerAssetPrice();
const ethTokenFee = buyQuoteAccessor.feeEthAmount();
const totalEthAmount = buyQuoteAccessor.totalEthAmount();
const assetEthBaseUnitAmount = buyQuoteAccessor.assetEthAmount();
const feeEthBaseUnitAmount = buyQuoteAccessor.feeEthAmount();
const totalEthBaseUnitAmount = buyQuoteAccessor.totalEthAmount();
const pricePerTokenEth =
!_.isUndefined(assetEthBaseUnitAmount) &&
!_.isUndefined(selectedAssetUnitAmount) &&
!selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO)
? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil()
: undefined;
return (
<Container padding="20px" width="100%" flexGrow={1}>
<Container marginBottom="10px">
@@ -40,20 +48,19 @@ export class OrderDetails extends React.Component<OrderDetailsProps> {
</Container>
<EthAmountRow
rowLabel="Token Price"
ethAmount={ethAssetPrice}
ethAmount={pricePerTokenEth}
ethUsdPrice={ethUsdPrice}
isEthAmountInBaseUnits={false}
isLoading={this.props.isLoading}
/>
<EthAmountRow
rowLabel="Fee"
ethAmount={ethTokenFee}
ethAmount={feeEthBaseUnitAmount}
ethUsdPrice={ethUsdPrice}
isLoading={this.props.isLoading}
/>
<EthAmountRow
rowLabel="Total Cost"
ethAmount={totalEthAmount}
ethAmount={totalEthBaseUnitAmount}
ethUsdPrice={ethUsdPrice}
shouldEmphasize={true}
isLoading={this.props.isLoading}
@@ -81,7 +88,7 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> {
const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props;
const fontWeight = shouldEmphasize ? 700 : 400;
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseAmount : format.ethUnitAmount;
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseUnitAmount : format.ethUnitAmount;
return (
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
<Flex justify="space-between">
@@ -105,7 +112,9 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> {
);
}
private _renderUsdSection(): React.ReactNode {
const usdFormatter = this.props.isEthAmountInBaseUnits ? format.ethBaseAmountInUsd : format.ethUnitAmountInUsd;
const usdFormatter = this.props.isEthAmountInBaseUnits
? format.ethBaseUnitAmountInUsd
: format.ethUnitAmountInUsd;
const shouldHideUsdPriceSection = _.isUndefined(this.props.ethUsdPrice) || _.isUndefined(this.props.ethAmount);
return shouldHideUsdPriceSection ? null : (
<Container marginRight="3px" display="inline-block">

View File

@@ -1,45 +1,132 @@
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import * as React from 'react';
import { ColorOption } from '../style/theme';
import { Network } from '../types';
import { Account, AccountState, Network } from '../types';
import { MetaMaskLogo } from './meta_mask_logo';
import { PaymentMethodDropdown } from './payment_method_dropdown';
import { Circle } from './ui/circle';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
import { Icon } from './ui/icon';
import { Text } from './ui/text';
export interface PaymentMethodProps {}
export interface PaymentMethodProps {
account: Account;
network: Network;
onInstallWalletClick: () => void;
onUnlockWalletClick: () => void;
}
export const PaymentMethod: React.StatelessComponent<PaymentMethodProps> = () => (
<Container padding="20px" width="100%">
<Container marginBottom="10px">
<Flex justify="space-between">
<Text
letterSpacing="1px"
fontColor={ColorOption.primaryColor}
fontWeight={600}
textTransform="uppercase"
fontSize="14px"
>
Payment Method
</Text>
<Flex>
<Circle color={ColorOption.green} diameter={8} />
export class PaymentMethod extends React.Component<PaymentMethodProps> {
public render(): React.ReactNode {
return (
<Container padding="20px" width="100%">
<Container marginBottom="12px">
<Flex justify="space-between">
<Text
letterSpacing="1px"
fontColor={ColorOption.primaryColor}
fontWeight={600}
textTransform="uppercase"
fontSize="14px"
>
{this._renderTitleText()}
</Text>
<Flex>{this._renderTitleLabel()}</Flex>
</Flex>
</Container>
{this._renderMainContent()}
</Container>
);
}
private readonly _renderTitleText = (): string => {
const { account } = this.props;
switch (account.state) {
case AccountState.Loading:
return 'loading...';
case AccountState.Locked:
case AccountState.None:
return 'connect your wallet';
case AccountState.Ready:
return 'payment method';
}
};
private readonly _renderTitleLabel = (): React.ReactNode => {
const { account } = this.props;
if (account.state === AccountState.Ready || account.state === AccountState.Locked) {
const circleColor: ColorOption = account.state === AccountState.Ready ? ColorOption.green : ColorOption.red;
return (
<React.Fragment>
<Circle diameter={8} color={circleColor} />
<Container marginLeft="3px">
<Text fontColor={ColorOption.darkGrey} fontSize="12px">
MetaMask
</Text>
</Container>
</Flex>
</Flex>
</Container>
<PaymentMethodDropdown
accountAddress="0xa1b2c3d4e5f6g7h8j9k10"
accountEthBalanceInWei={new BigNumber(10500000000000000000)}
network={Network.Mainnet}
/>
</React.Fragment>
);
}
return null;
};
private readonly _renderMainContent = (): React.ReactNode => {
const { account, network } = this.props;
switch (account.state) {
case AccountState.Loading:
// Just take up the same amount of space as the other states.
return <Container height="52px" />;
case AccountState.Locked:
return (
<WalletPrompt
onClick={this.props.onUnlockWalletClick}
image={<Icon width={13} icon="lock" color={ColorOption.black} />}
>
Please Unlock MetaMask
</WalletPrompt>
);
case AccountState.None:
return (
<WalletPrompt
onClick={this.props.onInstallWalletClick}
image={<MetaMaskLogo width={19} height={18} />}
>
Install MetaMask
</WalletPrompt>
);
case AccountState.Ready:
return (
<PaymentMethodDropdown
accountAddress={account.address}
accountEthBalanceInWei={account.ethBalanceInWei}
network={network}
/>
);
}
};
}
interface WalletPromptProps {
image: React.ReactNode;
onClick?: () => void;
}
const WalletPrompt: React.StatelessComponent<WalletPromptProps> = ({ onClick, image, children }) => (
<Container
padding="14.5px"
border={`1px solid ${ColorOption.darkOrange}`}
backgroundColor={ColorOption.lightOrange}
width="100%"
borderRadius="4px"
onClick={onClick}
cursor={onClick ? 'pointer' : undefined}
boxShadowOnHover={!!onClick}
>
<Flex>
<Container marginRight="10px">{image}</Container>
<Text fontSize="16px" fontColor={ColorOption.darkOrange}>
{children}
</Text>
</Flex>
</Container>
);

View File

@@ -18,7 +18,7 @@ export class PaymentMethodDropdown extends React.Component<PaymentMethodDropdown
public render(): React.ReactNode {
const { accountAddress, accountEthBalanceInWei } = this.props;
const value = format.ethAddress(accountAddress);
const label = format.ethBaseAmount(accountEthBalanceInWei, 4, '') as string;
const label = format.ethBaseUnitAmount(accountEthBalanceInWei, 4, '') as string;
return <Dropdown value={value} label={label} items={this._getDropdownItemConfigs()} />;
}
private readonly _getDropdownItemConfigs = (): DropdownItemConfig[] => {

View File

@@ -7,9 +7,9 @@ import { Container } from './ui/container';
import { Spinner } from './ui/spinner';
export const PlacingOrderButton: React.StatelessComponent<{}> = props => (
<Button isDisabled={true} width="100%" fontColor={ColorOption.white} fontSize="20px">
<Button isDisabled={true} width="100%" fontColor={ColorOption.white}>
<Container display="inline-block" position="relative" top="3px" marginRight="8px">
<Spinner widthPx={20} heightPx={20} />
<Spinner widthPx={16} heightPx={16} />
</Container>
Placing Order&hellip;
</Button>

View File

@@ -156,8 +156,6 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
return `${width}px`;
}
return `${textLengthThreshold}ch`;
default:
return '1ch';
}
};
private readonly _calculateFontSize = (phase: ScalingInputPhase): number => {

View File

@@ -15,8 +15,6 @@ export const SecondaryButton: React.StatelessComponent<SecondaryButtonProps> = p
borderColor={ColorOption.lightGrey}
width={props.width}
onClick={props.onClick}
fontColor={ColorOption.primaryColor}
fontSize="16px"
{...buttonProps}
>
{props.children}

View File

@@ -3,9 +3,10 @@ import * as React from 'react';
import { ScreenSpecification } from '../style/media';
import { ColorOption } from '../style/theme';
import { zIndex } from '../style/z_index';
import { SlideAnimationState } from '../types';
import { PositionAnimationSettings } from './animations/position_animation';
import { SlideAnimation, SlideAnimationState } from './animations/slide_animation';
import { SlideAnimation } from './animations/slide_animation';
import { Container } from './ui/container';
import { Flex } from './ui/flex';

View File

@@ -2,35 +2,25 @@ import * as React from 'react';
import { ColorOption } from '../style/theme';
import { zIndex } from '../style/z_index';
import { SlideAnimationState } from '../types';
import { PositionAnimationSettings } from './animations/position_animation';
import { SlideAnimation, SlideAnimationState } from './animations/slide_animation';
import { SlideAnimation } from './animations/slide_animation';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
import { Icon } from './ui/icon';
import { Text } from './ui/text';
export interface PanelProps {
title?: string;
onClose?: () => void;
}
export const Panel: React.StatelessComponent<PanelProps> = ({ title, children, onClose }) => (
export const Panel: React.StatelessComponent<PanelProps> = ({ children, onClose }) => (
<Container backgroundColor={ColorOption.white} width="100%" height="100%" zIndex={zIndex.panel} padding="20px">
<Flex justify="space-between">
{title && (
<Container marginTop="3px">
<Text fontColor={ColorOption.darkGrey} fontSize="18px" fontWeight="600" lineHeight="22px">
{title}
</Text>
</Container>
)}
<Container position="relative" bottom="7px">
<Icon width={12} color={ColorOption.lightGrey} icon="closeX" onClick={onClose} />
</Container>
<Flex justify="flex-end">
<Icon padding="5px" width={12} color={ColorOption.lightGrey} icon="closeX" onClick={onClose} />
</Flex>
<Container marginTop="10px" height="100%">
<Container position="relative" top="-10px" height="100%">
{children}
</Container>
</Container>

View File

@@ -0,0 +1,60 @@
import * as React from 'react';
import { ColorOption } from '../style/theme';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
import { Text } from './ui/text';
export interface MoreInfoSettings {
text: string;
href: string;
}
export interface StandardPanelContentProps {
image: React.ReactNode;
title: string;
description: string;
moreInfoSettings?: MoreInfoSettings;
action: React.ReactNode;
}
const SPACING_BETWEEN_PX = '20px';
export const StandardPanelContent: React.StatelessComponent<StandardPanelContentProps> = ({
image,
title,
description,
moreInfoSettings,
action,
}) => (
<Container height="100%">
<Flex direction="column" height="calc(100% - 58px)">
<Container marginBottom={SPACING_BETWEEN_PX}>{image}</Container>
<Container marginBottom={SPACING_BETWEEN_PX}>
<Text fontSize="20px" fontWeight={700} fontColor={ColorOption.black}>
{title}
</Text>
</Container>
<Container marginBottom={SPACING_BETWEEN_PX}>
<Text fontSize="14px" fontColor={ColorOption.grey} center={true}>
{description}
</Text>
</Container>
<Container marginBottom={SPACING_BETWEEN_PX}>
{moreInfoSettings && (
<Text
center={true}
fontSize="13px"
textDecorationLine="underline"
fontColor={ColorOption.lightGrey}
href={moreInfoSettings.href}
>
{moreInfoSettings.text}
</Text>
)}
</Container>
</Flex>
<Container>{action}</Container>
</Container>
);

View File

@@ -0,0 +1,29 @@
import * as React from 'react';
import { SlideAnimationState, StandardSlidingPanelContent, StandardSlidingPanelSettings } from '../types';
import { InstallWalletPanelContent } from './install_wallet_panel_content';
import { SlidingPanel } from './sliding_panel';
export interface StandardSlidingPanelProps extends StandardSlidingPanelSettings {
onClose: () => void;
}
export class StandardSlidingPanel extends React.Component<StandardSlidingPanelProps> {
public render(): React.ReactNode {
const { animationState, content, onClose } = this.props;
return (
<SlidingPanel animationState={animationState} onClose={onClose}>
{this._getNodeForContent(content)}
</SlidingPanel>
);
}
private readonly _getNodeForContent = (content: StandardSlidingPanelContent): React.ReactNode => {
switch (content) {
case StandardSlidingPanelContent.InstallWallet:
return <InstallWalletPanelContent />;
case StandardSlidingPanelContent.None:
return null;
}
};
}

View File

@@ -2,7 +2,7 @@ import * as _ from 'lodash';
import * as React from 'react';
import { PROGRESS_FINISH_ANIMATION_TIME_MS, PROGRESS_STALL_AT_WIDTH } from '../constants';
import { ColorOption, keyframes, styled } from '../style/theme';
import { ColorOption, css, keyframes, styled } from '../style/theme';
import { Container } from './ui/container';
@@ -20,15 +20,11 @@ export class TimedProgressBar extends React.Component<TimedProgressBarProps, {}>
private readonly _barRef = React.createRef<HTMLDivElement>();
public render(): React.ReactNode {
const timedProgressProps = this._calculateTimedProgressProps();
return (
<Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px">
<TimedProgress {...timedProgressProps} ref={this._barRef as any} />
</Container>
);
const widthAnimationSettings = this._calculateWidthAnimationSettings();
return <ProgressBar animationSettings={widthAnimationSettings} ref={this._barRef} />;
}
private _calculateTimedProgressProps(): TimedProgressProps {
private _calculateWidthAnimationSettings(): WidthAnimationSettings {
if (this.props.hasEnded) {
if (!this._barRef.current) {
throw new Error('ended but no reference');
@@ -60,21 +56,45 @@ const expandingWidthKeyframes = (fromWidth: string, toWidth: string) => {
`;
};
interface TimedProgressProps {
export interface WidthAnimationSettings {
timeMs: number;
fromWidth: string;
toWidth: string;
}
export const TimedProgress =
interface ProgressProps {
width?: string;
animationSettings?: WidthAnimationSettings;
}
export const Progress =
styled.div <
TimedProgressProps >
ProgressProps >
`
&& {
background-color: ${props => props.theme[ColorOption.primaryColor]};
border-radius: 6px;
height: 6px;
animation: ${props => expandingWidthKeyframes(props.fromWidth, props.toWidth)}
${props => props.timeMs}ms linear 1 forwards;
${props => (props.width ? `width: ${props.width};` : '')}
${props =>
props.animationSettings
? css`
animation: ${expandingWidthKeyframes(
props.animationSettings.fromWidth,
props.animationSettings.toWidth,
)}
${props.animationSettings.timeMs}ms linear 1 forwards;
`
: ''}
}
`;
export interface ProgressBarProps extends ProgressProps {}
export const ProgressBar: React.ComponentType<ProgressBarProps & React.ClassAttributes<{}>> = React.forwardRef(
(props, ref) => (
<Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px">
<Progress {...props} ref={ref as any} />
</Container>
),
);

View File

@@ -2,6 +2,9 @@ import { darken, saturate } from 'polished';
import * as React from 'react';
import { ColorOption, styled } from '../../style/theme';
import { util } from '../../util/util';
export type ButtonOnClickHandler = (event: React.MouseEvent<HTMLElement>) => void;
export interface ButtonProps {
backgroundColor?: ColorOption;
@@ -12,15 +15,26 @@ export interface ButtonProps {
padding?: string;
type?: string;
isDisabled?: boolean;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
href?: string;
onClick?: ButtonOnClickHandler;
className?: string;
}
const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
<button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}>
{children}
</button>
);
const PlainButton: React.StatelessComponent<ButtonProps> = ({
children,
isDisabled,
onClick,
href,
type,
className,
}) => {
const computedOnClick = isDisabled ? undefined : href ? util.createOpenUrlInNewWindow(href) : onClick;
return (
<button type={type} className={className} onClick={computedOnClick} disabled={isDisabled}>
{children}
</button>
);
};
const darkenOnHoverAmount = 0.1;
const darkenOnActiveAmount = 0.2;
@@ -31,7 +45,7 @@ export const Button = styled(PlainButton)`
box-sizing: border-box;
font-size: ${props => props.fontSize};
font-family: 'Inter UI', sans-serif;
font-weight: 600;
font-weight: 500;
color: ${props => props.fontColor && props.theme[props.fontColor]};
cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
transition: background-color, opacity 0.5s ease;
@@ -64,11 +78,10 @@ export const Button = styled(PlainButton)`
Button.defaultProps = {
backgroundColor: ColorOption.primaryColor,
borderColor: ColorOption.primaryColor,
width: 'auto',
isDisabled: false,
padding: '.6em 1.2em',
fontSize: '15px',
padding: '.82em 1.2em',
fontSize: '16px',
};
Button.displayName = 'Button';

View File

@@ -20,6 +20,7 @@ interface IconInfoMapping {
success: IconInfo;
chevron: IconInfo;
search: IconInfo;
lock: IconInfo;
}
const ICONS: IconInfoMapping = {
closeX: {
@@ -58,6 +59,11 @@ const ICONS: IconInfoMapping = {
path:
'M8.39404 5.19727C8.39404 6.96289 6.96265 8.39453 5.19702 8.39453C3.4314 8.39453 2 6.96289 2 5.19727C2 3.43164 3.4314 2 5.19702 2C6.96265 2 8.39404 3.43164 8.39404 5.19727ZM8.09668 9.51074C7.26855 10.0684 6.27075 10.3945 5.19702 10.3945C2.3269 10.3945 0 8.06738 0 5.19727C0 2.32715 2.3269 0 5.19702 0C8.06738 0 10.394 2.32715 10.394 5.19727C10.394 6.27051 10.0686 7.26855 9.51074 8.09668L13.6997 12.2861L12.2854 13.7002L8.09668 9.51074Z',
},
lock: {
viewBox: '0 0 13 16',
path:
'M6.47619 0C3.79509 0 1.60489 2.21216 1.60489 4.92014V6.33135C0.717479 6.33135 0 7.05602 0 7.95232V14.379C0 15.2753 0.717479 16 1.60489 16H11.3475C12.2349 16 12.9524 15.2753 12.9524 14.379V7.95232C12.9524 7.05602 12.2349 6.33135 11.3475 6.33135V4.92014C11.3475 2.21216 9.1573 0 6.47619 0ZM9.6482 6.33135H3.30418V4.92014C3.30418 3.16567 4.72026 1.71633 6.47619 1.71633C8.23213 1.71633 9.6482 3.16567 9.6482 4.92014V6.33135Z',
},
};
export interface IconProps {

View File

@@ -1,11 +1,15 @@
import * as _ from 'lodash';
import { overlayBlack, styled } from '../../style/theme';
import { generateMediaWrapper, ScreenWidths } from '../../style/media';
import { generateOverlayBlack, styled } from '../../style/theme';
import { zIndex } from '../../style/z_index';
export interface OverlayProps {
zIndex?: number;
backgroundColor?: string;
width?: string;
height?: string;
showMaxWidth?: ScreenWidths;
}
export const Overlay =
@@ -20,12 +24,16 @@ export const Overlay =
left: 0;
z-index: ${props => props.zIndex}
background-color: ${props => props.backgroundColor};
${props => props.width && `width: ${props.width};`}
${props => props.height && `height: ${props.height};`}
display: ${props => (props.showMaxWidth ? 'none' : 'block')};
${props => props.showMaxWidth && generateMediaWrapper(props.showMaxWidth)`display: block;`}
}
`;
Overlay.defaultProps = {
zIndex: zIndex.overlayDefault,
backgroundColor: overlayBlack,
backgroundColor: generateOverlayBlack(0.6),
};
Overlay.displayName = 'Overlay';

View File

@@ -2,6 +2,7 @@ import { darken } from 'polished';
import * as React from 'react';
import { ColorOption, styled } from '../../style/theme';
import { util } from '../../util/util';
export interface TextProps {
fontColor?: ColorOption;
@@ -20,10 +21,16 @@ export interface TextProps {
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
noWrap?: boolean;
display?: string;
href?: string;
}
export const Text: React.StatelessComponent<TextProps> = ({ href, onClick, ...rest }) => {
const computedOnClick = href ? util.createOpenUrlInNewWindow(href) : onClick;
return <StyledText {...rest} onClick={computedOnClick} />;
};
const darkenOnHoverAmount = 0.3;
export const Text =
export const StyledText =
styled.div <
TextProps >
`

View File

@@ -1,8 +1,9 @@
import * as React from 'react';
import { ZeroExInstantContainer } from '../components/zero_ex_instant_container';
import { INJECTED_DIV_CLASS } from '../constants';
import { ZeroExInstantContainer } from './zero_ex_instant_container';
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
export type ZeroExInstantProps = ZeroExInstantProviderProps;

View File

@@ -1,26 +1,29 @@
import * as React from 'react';
import { AvailableERC20TokenSelector } from '../containers/available_erc20_token_selector';
import { ConnectedBuyOrderProgressOrPaymentMethod } from '../containers/connected_buy_order_progress_or_payment_method';
import { CurrentStandardSlidingPanel } from '../containers/current_standard_sliding_panel';
import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order_details';
import { LatestError } from '../containers/latest_error';
import { SelectedAssetBuyOrderProgress } from '../containers/selected_asset_buy_order_progress';
import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_buy_order_state_buttons';
import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading';
import { ColorOption } from '../style/theme';
import { zIndex } from '../style/z_index';
import { OrderProcessState, SlideAnimationState } from '../types';
import { SlideAnimationState } from './animations/slide_animation';
import { CSSReset } from './css_reset';
import { SlidingPanel } from './sliding_panel';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
export interface ZeroExInstantContainerProps {}
export interface ZeroExInstantContainerProps {
orderProcessState: OrderProcessState;
}
export interface ZeroExInstantContainerState {
tokenSelectionPanelAnimationState: SlideAnimationState;
}
export class ZeroExInstantContainer extends React.Component<ZeroExInstantContainerProps, ZeroExInstantContainerState> {
export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantContainerState> {
public state = {
tokenSelectionPanelAnimationState: 'none' as SlideAnimationState,
};
@@ -47,19 +50,19 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain
>
<Flex direction="column" justify="flex-start" height="100%">
<SelectedAssetInstantHeading onSelectAssetClick={this._handleSymbolClick} />
<SelectedAssetBuyOrderProgress />
<ConnectedBuyOrderProgressOrPaymentMethod />
<LatestBuyQuoteOrderDetails />
<Container padding="20px" width="100%">
<SelectedAssetBuyOrderStateButtons />
</Container>
</Flex>
<SlidingPanel
title="Select Token"
animationState={this.state.tokenSelectionPanelAnimationState}
onClose={this._handlePanelClose}
>
<AvailableERC20TokenSelector onTokenSelect={this._handlePanelClose} />
</SlidingPanel>
<CurrentStandardSlidingPanel />
</Container>
</Container>
</React.Fragment>

View File

@@ -1,12 +1,12 @@
import * as React from 'react';
import { ZeroExInstantContainer } from '../components/zero_ex_instant_container';
import { ColorOption } from '../style/theme';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
import { Icon } from './ui/icon';
import { Overlay } from './ui/overlay';
import { ZeroExInstantContainer } from './zero_ex_instant_container';
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
export interface ZeroExInstantOverlayProps extends ZeroExInstantProviderProps {

View File

@@ -5,15 +5,18 @@ import * as _ from 'lodash';
import * as React from 'react';
import { Provider as ReduxProvider } from 'react-redux';
import { ACCOUNT_UPDATE_INTERVAL_TIME_MS, BUY_QUOTE_UPDATE_INTERVAL_TIME_MS } from '../constants';
import { SelectedAssetThemeProvider } from '../containers/selected_asset_theme_provider';
import { asyncData } from '../redux/async_data';
import { DEFAULT_STATE, DefaultState, State } from '../redux/reducer';
import { store, Store } from '../redux/store';
import { fonts } from '../style/fonts';
import { AffiliateInfo, AssetMetaData, Network, OrderSource } from '../types';
import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource } from '../types';
import { assetUtils } from '../util/asset';
import { errorFlasher } from '../util/error_flasher';
import { gasPriceEstimator } from '../util/gas_price_estimator';
import { Heartbeater } from '../util/heartbeater';
import { generateAccountHeartbeater, generateBuyQuoteHeartbeater } from '../util/heartbeater_factory';
import { providerStateFactory } from '../util/provider_state_factory';
fonts.include();
@@ -37,6 +40,9 @@ export interface ZeroExInstantProviderOptionalProps {
export class ZeroExInstantProvider extends React.Component<ZeroExInstantProviderProps> {
private readonly _store: Store;
private _accountUpdateHeartbeat?: Heartbeater;
private _buyQuoteHeartbeat?: Heartbeater;
// TODO(fragosti): Write tests for this beast once we inject a provider.
private static _mergeDefaultStateWithProps(
props: ZeroExInstantProviderProps,
@@ -67,7 +73,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
completeAssetMetaDataMap,
networkId,
),
selectedAssetAmount: _.isUndefined(props.defaultAssetBuyAmount)
selectedAssetUnitAmount: _.isUndefined(props.defaultAssetBuyAmount)
? undefined
: new BigNumber(props.defaultAssetBuyAmount),
availableAssets: _.isUndefined(props.availableAssetDatas)
@@ -85,17 +91,29 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
}
public componentDidMount(): void {
const state = this._store.getState();
const dispatch = this._store.dispatch;
// tslint:disable-next-line:no-floating-promises
asyncData.fetchEthPriceAndDispatchToStore(this._store);
asyncData.fetchEthPriceAndDispatchToStore(dispatch);
// fetch available assets if none are specified
if (_.isUndefined(state.availableAssets)) {
// tslint:disable-next-line:no-floating-promises
asyncData.fetchAvailableAssetDatasAndDispatchToStore(this._store);
asyncData.fetchAvailableAssetDatasAndDispatchToStore(state, dispatch);
}
if (state.providerState.account.state !== AccountState.None) {
this._accountUpdateHeartbeat = generateAccountHeartbeater({
store: this._store,
shouldPerformImmediatelyOnStart: true,
});
this._accountUpdateHeartbeat.start(ACCOUNT_UPDATE_INTERVAL_TIME_MS);
}
this._buyQuoteHeartbeat = generateBuyQuoteHeartbeater({
store: this._store,
shouldPerformImmediatelyOnStart: false,
});
this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS);
// tslint:disable-next-line:no-floating-promises
asyncData.fetchAccountInfoAndDispatchToStore(this._store);
// tslint:disable-next-line:no-floating-promises
asyncData.fetchCurrentBuyQuoteAndDispatchToStore(this._store);
asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, true);
// warm up the gas price estimator cache just in case we can't
// grab the gas price estimate when submitting the transaction
// tslint:disable-next-line:no-floating-promises
@@ -103,6 +121,14 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
// tslint:disable-next-line:no-floating-promises
this._flashErrorIfWrongNetwork();
}
public componentWillUnmount(): void {
if (this._accountUpdateHeartbeat) {
this._accountUpdateHeartbeat.stop();
}
if (this._buyQuoteHeartbeat) {
this._buyQuoteHeartbeat.stop();
}
}
public render(): React.ReactNode {
return (
<ReduxProvider store={this._store}>

View File

@@ -11,12 +11,17 @@ export const WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX = 'Transaction fa
export const GWEI_IN_WEI = new BigNumber(1000000000);
export const ONE_SECOND_MS = 1000;
export const ONE_MINUTE_MS = ONE_SECOND_MS * 60;
export const ACCOUNT_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 5;
export const BUY_QUOTE_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 15;
export const DEFAULT_GAS_PRICE = GWEI_IN_WEI.mul(6);
export const DEFAULT_ESTIMATED_TRANSACTION_TIME_MS = ONE_MINUTE_MS * 2;
export const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info';
export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2';
export const PROGRESS_STALL_AT_WIDTH = '95%';
export const PROGRESS_FINISH_ANIMATION_TIME_MS = 200;
export const META_MASK_CHROME_STORE_URL =
'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en';
export const META_MASK_SITE_URL = 'https://metamask.io/';
export const ETHEREUM_NODE_URL_BY_NETWORK = {
[Network.Mainnet]: 'https://mainnet.infura.io/',
[Network.Kovan]: 'https://kovan.infura.io/',
@@ -31,6 +36,3 @@ export const LOADING_ACCOUNT: AccountNotReady = {
export const LOCKED_ACCOUNT: AccountNotReady = {
state: AccountState.Locked,
};
export const ERROR_ACCOUNT: AccountNotReady = {
state: AccountState.Error,
};

View File

@@ -0,0 +1,59 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { PaymentMethod, PaymentMethodProps } from '../components/payment_method';
import { Action, actions } from '../redux/actions';
import { asyncData } from '../redux/async_data';
import { State } from '../redux/reducer';
import { Network, Omit, ProviderState, StandardSlidingPanelContent } from '../types';
export interface ConnectedAccountPaymentMethodProps {}
interface ConnectedState {
network: Network;
providerState: ProviderState;
}
interface ConnectedDispatch {
onInstallWalletClick: () => void;
unlockWalletAndDispatchToStore: (providerState: ProviderState) => void;
}
type ConnectedProps = Omit<PaymentMethodProps, keyof ConnectedAccountPaymentMethodProps>;
type FinalProps = ConnectedProps & ConnectedAccountPaymentMethodProps;
const mapStateToProps = (state: State, _ownProps: ConnectedAccountPaymentMethodProps): ConnectedState => ({
network: state.network,
providerState: state.providerState,
});
const mapDispatchToProps = (
dispatch: Dispatch<Action>,
ownProps: ConnectedAccountPaymentMethodProps,
): ConnectedDispatch => ({
onInstallWalletClick: () => dispatch(actions.openStandardSlidingPanel(StandardSlidingPanelContent.InstallWallet)),
unlockWalletAndDispatchToStore: async (providerState: ProviderState) =>
asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true),
});
const mergeProps = (
connectedState: ConnectedState,
connectedDispatch: ConnectedDispatch,
ownProps: ConnectedAccountPaymentMethodProps,
): FinalProps => ({
...ownProps,
network: connectedState.network,
account: connectedState.providerState.account,
onInstallWalletClick: connectedDispatch.onInstallWalletClick,
onUnlockWalletClick: () => {
connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState);
},
});
export const ConnectedAccountPaymentMethod: React.ComponentClass<ConnectedAccountPaymentMethodProps> = connect(
mapStateToProps,
mapDispatchToProps,
mergeProps,
)(PaymentMethod);

View File

@@ -0,0 +1,36 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { State } from '../redux/reducer';
import { OrderProcessState } from '../types';
import { ConnectedAccountPaymentMethod } from './connected_account_payment_method';
import { SelectedAssetBuyOrderProgress } from './selected_asset_buy_order_progress';
interface BuyOrderProgressOrPaymentMethodProps {
orderProcessState: OrderProcessState;
}
export const BuyOrderProgressOrPaymentMethod = (props: BuyOrderProgressOrPaymentMethodProps) => {
const { orderProcessState } = props;
if (
orderProcessState === OrderProcessState.Processing ||
orderProcessState === OrderProcessState.Success ||
orderProcessState === OrderProcessState.Failure
) {
return <SelectedAssetBuyOrderProgress />;
}
if (orderProcessState === OrderProcessState.None) {
return <ConnectedAccountPaymentMethod />;
}
return null;
};
interface ConnectedState extends BuyOrderProgressOrPaymentMethodProps {}
export interface ConnectedBuyOrderProgressOrPaymentMethodProps {}
const mapStateToProps = (state: State, _ownProps: ConnectedBuyOrderProgressOrPaymentMethodProps): ConnectedState => ({
orderProcessState: state.buyOrderState.processState,
});
export const ConnectedBuyOrderProgressOrPaymentMethod: React.ComponentClass<
ConnectedBuyOrderProgressOrPaymentMethodProps
> = connect(mapStateToProps)(BuyOrderProgressOrPaymentMethod);

View File

@@ -0,0 +1,31 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { StandardSlidingPanel } from '../components/standard_sliding_panel';
import { Action, actions } from '../redux/actions';
import { State } from '../redux/reducer';
import { StandardSlidingPanelSettings } from '../types';
export interface CurrentStandardSlidingPanelProps {}
interface ConnectedState extends StandardSlidingPanelSettings {}
interface ConnectedDispatch {
onClose: () => void;
}
const mapStateToProps = (state: State, _ownProps: CurrentStandardSlidingPanelProps): ConnectedState =>
state.standardSlidingPanelSettings;
const mapDispatchToProps = (
dispatch: Dispatch<Action>,
ownProps: CurrentStandardSlidingPanelProps,
): ConnectedDispatch => ({
onClose: () => dispatch(actions.closeStandardSlidingPanel()),
});
export const CurrentStandardSlidingPanel: React.ComponentClass<CurrentStandardSlidingPanelProps> = connect(
mapStateToProps,
mapDispatchToProps,
)(StandardSlidingPanel);

View File

@@ -14,6 +14,7 @@ export interface LatestBuyQuoteOrderDetailsProps {}
interface ConnectedState {
buyQuoteInfo?: BuyQuoteInfo;
selectedAssetUnitAmount?: BigNumber;
ethUsdPrice?: BigNumber;
isLoading: boolean;
}
@@ -21,6 +22,7 @@ interface ConnectedState {
const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({
// use the worst case quote info
buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(),
selectedAssetUnitAmount: state.selectedAssetUnitAmount,
ethUsdPrice: state.ethUsdPrice,
isLoading: state.quoteRequestState === AsyncProcessState.Pending,
});

View File

@@ -1,35 +1,59 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { SlideAnimationState } from '../components/animations/slide_animation';
import { SlidingError } from '../components/sliding_error';
import { Overlay } from '../components/ui/overlay';
import { Action } from '../redux/actions';
import { State } from '../redux/reducer';
import { Asset, DisplayStatus } from '../types';
import { ScreenWidths } from '../style/media';
import { generateOverlayBlack } from '../style/theme';
import { zIndex } from '../style/z_index';
import { Asset, DisplayStatus, Omit, SlideAnimationState } from '../types';
import { errorFlasher } from '../util/error_flasher';
export interface LatestErrorComponentProps {
asset?: Asset;
latestErrorMessage?: string;
animationState: SlideAnimationState;
shouldRenderOverlay: boolean;
onOverlayClick: () => void;
}
export const LatestErrorComponent: React.StatelessComponent<LatestErrorComponentProps> = props => {
if (!props.latestErrorMessage) {
return <div />;
}
return <SlidingError animationState={props.animationState} icon="😢" message={props.latestErrorMessage} />;
return (
<React.Fragment>
<SlidingError animationState={props.animationState} icon="😢" message={props.latestErrorMessage} />
{props.shouldRenderOverlay && (
<Overlay
onClick={props.onOverlayClick}
zIndex={zIndex.containerOverlay}
showMaxWidth={ScreenWidths.Sm}
backgroundColor={generateOverlayBlack(0.4)}
/>
)}
</React.Fragment>
);
};
interface ConnectedState {
asset?: Asset;
latestErrorMessage?: string;
animationState: SlideAnimationState;
}
export interface LatestErrorProps {}
interface ConnectedState extends Omit<LatestErrorComponentProps, 'onOverlayClick'> {}
const mapStateToProps = (state: State, _ownProps: LatestErrorProps): ConnectedState => ({
asset: state.selectedAsset,
latestErrorMessage: state.latestErrorMessage,
animationState: state.latestErrorDisplayStatus === DisplayStatus.Present ? 'slidIn' : 'slidOut',
shouldRenderOverlay: state.latestErrorDisplayStatus === DisplayStatus.Present,
});
export const LatestError = connect(mapStateToProps)(LatestErrorComponent);
type ConnectedDispatch = Pick<LatestErrorComponentProps, 'onOverlayClick'>;
const mapDispatchToProps = (dispatch: Dispatch<Action>, _ownProps: LatestErrorProps): ConnectedDispatch => ({
onOverlayClick: () => {
errorFlasher.clearError(dispatch);
},
});
export const LatestError = connect(mapStateToProps, mapDispatchToProps)(LatestErrorComponent);

View File

@@ -14,16 +14,16 @@ export interface InstantHeadingProps {
}
interface ConnectedState {
selectedAssetAmount?: BigNumber;
totalEthBaseAmount?: BigNumber;
selectedAssetUnitAmount?: BigNumber;
totalEthBaseUnitAmount?: BigNumber;
ethUsdPrice?: BigNumber;
quoteRequestState: AsyncProcessState;
buyOrderState: OrderState;
}
const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({
selectedAssetAmount: state.selectedAssetAmount,
totalEthBaseAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(),
selectedAssetUnitAmount: state.selectedAssetUnitAmount,
totalEthBaseUnitAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(),
ethUsdPrice: state.ethUsdPrice,
quoteRequestState: state.quoteRequestState,
buyOrderState: state.buyOrderState,

View File

@@ -6,11 +6,11 @@ import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { ERC20AssetAmountInput } from '../components/erc20_asset_amount_input';
import { ERC20AssetAmountInput, ERC20AssetAmountInputProps } from '../components/erc20_asset_amount_input';
import { Action, actions } from '../redux/actions';
import { State } from '../redux/reducer';
import { ColorOption } from '../style/theme';
import { AffiliateInfo, ERC20Asset, OrderProcessState } from '../types';
import { AffiliateInfo, ERC20Asset, Omit, OrderProcessState } from '../types';
import { buyQuoteUpdater } from '../util/buy_quote_updater';
export interface SelectedERC20AssetAmountInputProps {
@@ -37,13 +37,7 @@ interface ConnectedDispatch {
) => void;
}
interface ConnectedProps {
value?: BigNumber;
asset?: ERC20Asset;
onChange: (value?: BigNumber, asset?: ERC20Asset) => void;
isDisabled: boolean;
numberOfAssetsAvailable?: number;
}
type ConnectedProps = Omit<ERC20AssetAmountInputProps, keyof SelectedERC20AssetAmountInputProps>;
type FinalProps = ConnectedProps & SelectedERC20AssetAmountInputProps;
@@ -59,7 +53,7 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP
const assetBuyer = state.providerState.assetBuyer;
return {
assetBuyer,
value: state.selectedAssetAmount,
value: state.selectedAssetUnitAmount,
asset: selectedAsset,
isDisabled,
numberOfAssetsAvailable,
@@ -69,7 +63,7 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP
const debouncedUpdateBuyQuoteAsync = _.debounce(buyQuoteUpdater.updateBuyQuoteAsync.bind(buyQuoteUpdater), 200, {
trailing: true,
});
}) as typeof buyQuoteUpdater.updateBuyQuoteAsync;
const mapDispatchToProps = (
dispatch: Dispatch<Action>,
@@ -87,7 +81,7 @@ const mapDispatchToProps = (
// even if it's debounced, give them the illusion it's loading
dispatch(actions.setQuoteRequestStatePending());
// tslint:disable-next-line:no-floating-promises
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, affiliateInfo);
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, true, affiliateInfo);
}
},
});

View File

@@ -8,42 +8,42 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
'0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: 'rgb(54, 50, 60)',
primaryColor: '#333333',
symbol: 'zrx',
name: '0x',
},
'0xf47261b000000000000000000000000042d6622dece394b54999fbd73d108123806f6a18': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#ec3e6c',
primaryColor: '#EC4F81',
symbol: 'spank',
name: 'Spank',
},
'0xf47261b0000000000000000000000000d26114cd6ee289accf82350c8d8487fedb8a0c07': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#2e61ea',
primaryColor: '#2458E7',
symbol: 'omg',
name: 'OmiseGo',
},
'0xf47261b00000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#87e4ca',
primaryColor: '#68CCBB',
symbol: 'mkr',
name: 'Maker',
},
'0xf47261b00000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#9c326c',
primaryColor: '#FF5000',
symbol: 'bat',
name: 'Basic Attention Token',
},
'0xf47261b0000000000000000000000000744d70fdbe2ba4cf95131626614a1763df805b9e': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#5663b0',
primaryColor: '#4763D7',
symbol: 'snt',
name: 'Status',
},
@@ -54,27 +54,6 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
symbol: 'mana',
name: 'Decentraland',
},
'0xf47261b0000000000000000000000000a74476443119a942de498590fe1f2454d7d4ac0d': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#263469',
symbol: 'gnt',
name: 'Golem',
},
'0xf47261b000000000000000000000000012480e24eb5bec1a9d4369cab6a80cad3c0a377a': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#de5445',
symbol: 'sub',
name: 'Substratum',
},
'0xf47261b000000000000000000000000008d32b0da63e2C3bcF8019c9c5d849d7a9d791e6': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#000',
symbol: 'dentacoin',
name: 'Dentacoin',
},
'0xf47261b00000000000000000000000001985365e9f78359a9b6ad760e32412f4a445e862': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
@@ -82,4 +61,144 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
symbol: 'rep',
name: 'Augur',
},
'0xf47261b00000000000000000000000000abdace70d3790235af448c88547603b945604ea': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#2c3c8c',
symbol: 'dnt',
name: 'district0x',
},
'0xf47261b000000000000000000000000005f4a42e251f2d52b8ed15e9fedaacfcef1fad27': {
assetProxyId: AssetProxyId.ERC20,
decimals: 12,
primaryColor: '#048998',
symbol: 'zil',
name: 'Zilliqa',
},
'0xf47261b00000000000000000000000008f8221afbb33998d8584a2b05749ba73c37a938a': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#58BFD6',
symbol: 'req',
name: 'Request Network',
},
'0xf47261b0000000000000000000000000e0b7927c4af23765cb51314a0e0521a9645f0e2a': {
assetProxyId: AssetProxyId.ERC20,
decimals: 9,
primaryColor: '#BC9952',
symbol: 'dgd',
name: 'DigixDao',
},
'0xf47261b00000000000000000000000004f3afec4e5a3f2a6a1a411def7d7dfe50ee057bf': {
assetProxyId: AssetProxyId.ERC20,
decimals: 9,
primaryColor: '#DEB564',
symbol: 'dgx',
name: 'Digix Gold Token',
},
'0xf47261b0000000000000000000000000419d0d8bdd9af5e606ae2232ed285aff190e711b': {
assetProxyId: AssetProxyId.ERC20,
decimals: 8,
primaryColor: '#E40057',
symbol: 'fun',
name: 'FunFair',
},
'0xf47261b000000000000000000000000041e5560054824ea6b0732e656e3ad64e20e94e45': {
assetProxyId: AssetProxyId.ERC20,
decimals: 8,
primaryColor: '#04bc24',
symbol: 'cvc',
name: 'Civic',
},
'0xf47261b00000000000000000000000005ca9a71b1d01849c0a95490cc00559717fcf0d1d': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#F7296E',
symbol: 'ae',
name: 'Aeternity',
},
'0xf47261b0000000000000000000000000408e41876cccdc0f92210600ef50372656052a38': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#233C5A',
symbol: 'ren',
name: 'Republic Protocol',
},
'0xf47261b0000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#325CD2',
symbol: 'link',
name: 'ChainLink',
},
'0xf47261b00000000000000000000000006810e776880c02933d47db1b9fc05908e5386b96': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#48A4C0',
symbol: 'gno',
name: 'Gnosis',
},
'0xf47261b0000000000000000000000000960b236a07cf122663c4303350609a66a7b288c0': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#04a29e',
symbol: 'ant',
name: 'Aragon',
},
'0xf47261b00000000000000000000000004156d3342d5c385a87d264f90653733592000581': {
assetProxyId: AssetProxyId.ERC20,
decimals: 8,
primaryColor: '#4CABA7',
symbol: 'salt',
name: 'Salt',
},
'0xf47261b0000000000000000000000000595832f8fc6bf59c85c527fec3740a1b7a361269': {
assetProxyId: AssetProxyId.ERC20,
decimals: 6,
primaryColor: '#5BC9D4',
symbol: 'powr',
name: 'PowerLedger',
},
'0xf47261b00000000000000000000000008eb24319393716668d768dcec29356ae9cffe285': {
assetProxyId: AssetProxyId.ERC20,
decimals: 8,
primaryColor: '#523CE8',
symbol: 'agi',
name: 'SingularityNET',
},
'0xf47261b000000000000000000000000039bb259f66e1c59d5abef88375979b4d20d98022': {
assetProxyId: AssetProxyId.ERC20,
decimals: 8,
primaryColor: '#EDB740',
symbol: 'wax',
name: 'WAX',
},
'0xf47261b0000000000000000000000000beb9ef514a379b997e0798fdcc901ee474b6d9a1': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#333333',
symbol: 'mln',
name: 'Melon',
},
'0xf47261b000000000000000000000000058b6a8a3302369daec383334672404ee733ab239': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#232D37',
symbol: 'lpt',
name: 'Livepeer',
},
'0xf47261b000000000000000000000000027054b13b1b798b345b591a4d22e6562d47ea75a': {
assetProxyId: AssetProxyId.ERC20,
decimals: 4,
primaryColor: '#3A74F6',
symbol: 'ast',
name: 'AirSwap',
},
'0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: '#F2B350',
symbol: 'dai',
name: 'Dai Stablecoin',
},
};

View File

@@ -2,7 +2,7 @@ import { BuyQuote } from '@0x/asset-buyer';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { ActionsUnion, AddressAndEthBalanceInWei, Asset } from '../types';
import { ActionsUnion, AddressAndEthBalanceInWei, Asset, StandardSlidingPanelContent } from '../types';
export interface PlainAction<T extends string> {
type: T;
@@ -23,11 +23,10 @@ function createAction<T extends string, P>(type: T, data?: P): PlainAction<T> |
export enum ActionTypes {
SET_ACCOUNT_STATE_LOADING = 'SET_ACCOUNT_STATE_LOADING',
SET_ACCOUNT_STATE_LOCKED = 'SET_ACCOUNT_STATE_LOCKED',
SET_ACCOUNT_STATE_ERROR = 'SET_ACCOUNT_STATE_ERROR',
SET_ACCOUNT_STATE_READY = 'SET_ACCOUNT_STATE_READY',
UPDATE_ACCOUNT_ETH_BALANCE = 'UPDATE_ACCOUNT_ETH_BALANCE',
UPDATE_ETH_USD_PRICE = 'UPDATE_ETH_USD_PRICE',
UPDATE_SELECTED_ASSET_AMOUNT = 'UPDATE_SELECTED_ASSET_AMOUNT',
UPDATE_SELECTED_ASSET_UNIT_AMOUNT = 'UPDATE_SELECTED_ASSET_UNIT_AMOUNT',
SET_BUY_ORDER_STATE_NONE = 'SET_BUY_ORDER_STATE_NONE',
SET_BUY_ORDER_STATE_VALIDATING = 'SET_BUY_ORDER_STATE_VALIDATING',
SET_BUY_ORDER_STATE_PROCESSING = 'SET_BUY_ORDER_STATE_PROCESSING',
@@ -42,17 +41,19 @@ export enum ActionTypes {
HIDE_ERROR = 'HIDE_ERROR',
CLEAR_ERROR = 'CLEAR_ERROR',
RESET_AMOUNT = 'RESET_AMOUNT',
OPEN_STANDARD_SLIDING_PANEL = 'OPEN_STANDARD_SLIDING_PANEL',
CLOSE_STANDARD_SLIDING_PANEL = 'CLOSE_STANDARD_SLIDING_PANEL',
}
export const actions = {
setAccountStateLoading: () => createAction(ActionTypes.SET_ACCOUNT_STATE_LOADING),
setAccountStateLocked: () => createAction(ActionTypes.SET_ACCOUNT_STATE_LOCKED),
setAccountStateError: () => createAction(ActionTypes.SET_ACCOUNT_STATE_ERROR),
setAccountStateReady: (address: string) => createAction(ActionTypes.SET_ACCOUNT_STATE_READY, address),
updateAccountEthBalance: (addressAndBalance: AddressAndEthBalanceInWei) =>
createAction(ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE, addressAndBalance),
updateEthUsdPrice: (price?: BigNumber) => createAction(ActionTypes.UPDATE_ETH_USD_PRICE, price),
updateSelectedAssetAmount: (amount?: BigNumber) => createAction(ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT, amount),
updateSelectedAssetAmount: (amount?: BigNumber) =>
createAction(ActionTypes.UPDATE_SELECTED_ASSET_UNIT_AMOUNT, amount),
setBuyOrderStateNone: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_NONE),
setBuyOrderStateValidating: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_VALIDATING),
setBuyOrderStateProcessing: (txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) =>
@@ -68,4 +69,7 @@ export const actions = {
hideError: () => createAction(ActionTypes.HIDE_ERROR),
clearError: () => createAction(ActionTypes.CLEAR_ERROR),
resetAmount: () => createAction(ActionTypes.RESET_AMOUNT),
openStandardSlidingPanel: (content: StandardSlidingPanelContent) =>
createAction(ActionTypes.OPEN_STANDARD_SLIDING_PANEL, content),
closeStandardSlidingPanel: () => createAction(ActionTypes.CLOSE_STANDARD_SLIDING_PANEL),
};

View File

@@ -1,92 +1,103 @@
import { AssetProxyId } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash';
import { Dispatch } from 'redux';
import { BIG_NUMBER_ZERO } from '../constants';
import { AccountState, ERC20Asset } from '../types';
import { AccountState, ERC20Asset, OrderProcessState, ProviderState } from '../types';
import { assetUtils } from '../util/asset';
import { buyQuoteUpdater } from '../util/buy_quote_updater';
import { coinbaseApi } from '../util/coinbase_api';
import { errorFlasher } from '../util/error_flasher';
import { actions } from './actions';
import { Store } from './store';
import { State } from './reducer';
export const asyncData = {
fetchEthPriceAndDispatchToStore: async (store: Store) => {
fetchEthPriceAndDispatchToStore: async (dispatch: Dispatch) => {
try {
const ethUsdPrice = await coinbaseApi.getEthUsdPrice();
store.dispatch(actions.updateEthUsdPrice(ethUsdPrice));
dispatch(actions.updateEthUsdPrice(ethUsdPrice));
} catch (e) {
const errorMessage = 'Error fetching ETH/USD price';
errorFlasher.flashNewErrorMessage(store.dispatch, errorMessage);
store.dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO));
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO));
}
},
fetchAvailableAssetDatasAndDispatchToStore: async (store: Store) => {
const { providerState, assetMetaDataMap, network } = store.getState();
fetchAvailableAssetDatasAndDispatchToStore: async (state: State, dispatch: Dispatch) => {
const { providerState, assetMetaDataMap, network } = state;
const assetBuyer = providerState.assetBuyer;
try {
const assetDatas = await assetBuyer.getAvailableAssetDatasAsync();
const assets = assetUtils.createAssetsFromAssetDatas(assetDatas, assetMetaDataMap, network);
store.dispatch(actions.setAvailableAssets(assets));
dispatch(actions.setAvailableAssets(assets));
} catch (e) {
const errorMessage = 'Could not find any assets';
errorFlasher.flashNewErrorMessage(store.dispatch, errorMessage);
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
// On error, just specify that none are available
store.dispatch(actions.setAvailableAssets([]));
dispatch(actions.setAvailableAssets([]));
}
},
fetchAccountInfoAndDispatchToStore: async (store: Store) => {
const { providerState } = store.getState();
fetchAccountInfoAndDispatchToStore: async (
providerState: ProviderState,
dispatch: Dispatch,
shouldAttemptUnlock: boolean = false,
shouldSetToLoading: boolean = false,
) => {
const web3Wrapper = providerState.web3Wrapper;
if (providerState.account.state !== AccountState.Loading) {
store.dispatch(actions.setAccountStateLoading());
const provider = providerState.provider;
if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) {
dispatch(actions.setAccountStateLoading());
}
let availableAddresses: string[];
try {
availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
// TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here
const isPrivacyModeEnabled = !_.isUndefined((provider as any).enable);
availableAddresses =
isPrivacyModeEnabled && shouldAttemptUnlock
? await (provider as any).enable()
: await web3Wrapper.getAvailableAddressesAsync();
} catch (e) {
store.dispatch(actions.setAccountStateError());
dispatch(actions.setAccountStateLocked());
return;
}
if (!_.isEmpty(availableAddresses)) {
const activeAddress = availableAddresses[0];
store.dispatch(actions.setAccountStateReady(activeAddress));
dispatch(actions.setAccountStateReady(activeAddress));
// tslint:disable-next-line:no-floating-promises
asyncData.fetchAccountBalanceAndDispatchToStore(store);
asyncData.fetchAccountBalanceAndDispatchToStore(activeAddress, providerState.web3Wrapper, dispatch);
} else {
store.dispatch(actions.setAccountStateLocked());
dispatch(actions.setAccountStateLocked());
}
},
fetchAccountBalanceAndDispatchToStore: async (store: Store) => {
const { providerState } = store.getState();
const web3Wrapper = providerState.web3Wrapper;
const account = providerState.account;
if (account.state !== AccountState.Ready) {
return;
}
fetchAccountBalanceAndDispatchToStore: async (address: string, web3Wrapper: Web3Wrapper, dispatch: Dispatch) => {
try {
const address = account.address;
const ethBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(address);
store.dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei }));
dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei }));
} catch (e) {
// leave balance as is
return;
}
},
fetchCurrentBuyQuoteAndDispatchToStore: async (store: Store) => {
const { providerState, selectedAsset, selectedAssetAmount, affiliateInfo } = store.getState();
fetchCurrentBuyQuoteAndDispatchToStore: async (
state: State,
dispatch: Dispatch,
shouldSetPending: boolean = false,
) => {
const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state;
const assetBuyer = providerState.assetBuyer;
if (
!_.isUndefined(selectedAssetAmount) &&
!_.isUndefined(selectedAssetUnitAmount) &&
!_.isUndefined(selectedAsset) &&
buyOrderState.processState === OrderProcessState.None &&
selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20
) {
await buyQuoteUpdater.updateBuyQuoteAsync(
assetBuyer,
store.dispatch,
dispatch,
selectedAsset as ERC20Asset,
selectedAssetAmount,
selectedAssetUnitAmount,
shouldSetPending,
affiliateInfo,
);
}

View File

@@ -4,7 +4,7 @@ import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash';
import { ERROR_ACCOUNT, LOADING_ACCOUNT, LOCKED_ACCOUNT } from '../constants';
import { LOADING_ACCOUNT, LOCKED_ACCOUNT } from '../constants';
import { assetMetaDataMap } from '../data/asset_meta_data_map';
import {
Account,
@@ -19,6 +19,8 @@ import {
OrderProcessState,
OrderState,
ProviderState,
StandardSlidingPanelContent,
StandardSlidingPanelSettings,
} from '../types';
import { Action, ActionTypes } from './actions';
@@ -30,6 +32,7 @@ export interface DefaultState {
buyOrderState: OrderState;
latestErrorDisplayStatus: DisplayStatus;
quoteRequestState: AsyncProcessState;
standardSlidingPanelSettings: StandardSlidingPanelSettings;
}
// State that is required but needs to be derived from the props
@@ -41,7 +44,7 @@ interface PropsDerivedState {
interface OptionalState {
selectedAsset: Asset;
availableAssets: Asset[];
selectedAssetAmount: BigNumber;
selectedAssetUnitAmount: BigNumber;
ethUsdPrice: BigNumber;
latestBuyQuote: BuyQuote;
latestErrorMessage: string;
@@ -56,6 +59,10 @@ export const DEFAULT_STATE: DefaultState = {
buyOrderState: { processState: OrderProcessState.None },
latestErrorDisplayStatus: DisplayStatus.Hidden,
quoteRequestState: AsyncProcessState.None,
standardSlidingPanelSettings: {
animationState: 'none',
content: StandardSlidingPanelContent.None,
},
};
export const createReducer = (initialState: State) => {
@@ -65,14 +72,20 @@ export const createReducer = (initialState: State) => {
return reduceStateWithAccount(state, LOADING_ACCOUNT);
case ActionTypes.SET_ACCOUNT_STATE_LOCKED:
return reduceStateWithAccount(state, LOCKED_ACCOUNT);
case ActionTypes.SET_ACCOUNT_STATE_ERROR:
return reduceStateWithAccount(state, ERROR_ACCOUNT);
case ActionTypes.SET_ACCOUNT_STATE_READY: {
const account: AccountReady = {
const address = action.data;
let newAccount: AccountReady = {
state: AccountState.Ready,
address: action.data,
address,
};
return reduceStateWithAccount(state, account);
const currentAccount = state.providerState.account;
if (currentAccount.state === AccountState.Ready && currentAccount.address === address) {
newAccount = {
...newAccount,
ethBalanceInWei: currentAccount.ethBalanceInWei,
};
}
return reduceStateWithAccount(state, newAccount);
}
case ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE: {
const { address, ethBalanceInWei } = action.data;
@@ -92,10 +105,10 @@ export const createReducer = (initialState: State) => {
...state,
ethUsdPrice: action.data,
};
case ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT:
case ActionTypes.UPDATE_SELECTED_ASSET_UNIT_AMOUNT:
return {
...state,
selectedAssetAmount: action.data,
selectedAssetUnitAmount: action.data,
};
case ActionTypes.UPDATE_LATEST_BUY_QUOTE:
const newBuyQuoteIfExists = action.data;
@@ -206,13 +219,29 @@ export const createReducer = (initialState: State) => {
latestBuyQuote: undefined,
quoteRequestState: AsyncProcessState.None,
buyOrderState: { processState: OrderProcessState.None },
selectedAssetAmount: undefined,
selectedAssetUnitAmount: undefined,
};
case ActionTypes.SET_AVAILABLE_ASSETS:
return {
...state,
availableAssets: action.data,
};
case ActionTypes.OPEN_STANDARD_SLIDING_PANEL:
return {
...state,
standardSlidingPanelSettings: {
content: action.data,
animationState: 'slidIn',
},
};
case ActionTypes.CLOSE_STANDARD_SLIDING_PANEL:
return {
...state,
standardSlidingPanelSettings: {
content: state.standardSlidingPanelSettings.content,
animationState: 'slidOut',
},
};
default:
return state;
}
@@ -234,9 +263,9 @@ const reduceStateWithAccount = (state: State, account: Account) => {
const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
const selectedAssetIfExists = state.selectedAsset;
const selectedAssetAmountIfExists = state.selectedAssetAmount;
const selectedAssetUnitAmountIfExists = state.selectedAssetUnitAmount;
// if no selectedAsset or selectedAssetAmount exists on the current state, return false
if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetAmountIfExists)) {
if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetUnitAmountIfExists)) {
return false;
}
// if buyQuote's assetData does not match that of the current selected asset, return false
@@ -248,7 +277,7 @@ const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
const selectedAssetMetaData = selectedAssetIfExists.metaData;
if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) {
const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount(
selectedAssetAmountIfExists,
selectedAssetUnitAmountIfExists,
selectedAssetMetaData.decimals,
);
const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(buyQuote.assetBuyAmount);

View File

@@ -8,7 +8,7 @@ export enum ScreenWidths {
Lg = 64,
}
const generateMediaWrapper = (screenWidth: ScreenWidths) => (...args: any[]) => css`
export const generateMediaWrapper = (screenWidth: ScreenWidths) => (...args: any[]) => css`
@media (max-width: ${screenWidth}em) {
${css.apply(css, args)};
}

View File

@@ -35,7 +35,10 @@ export const theme: Theme = {
};
export const transparentWhite = 'rgba(255,255,255,0.3)';
export const overlayBlack = 'rgba(0, 0, 0, 0.6)';
export const completelyTransparent = 'rga(0, 0, 0, 0)';
export const generateOverlayBlack = (opacity = 0.6) => {
return `rgba(0, 0, 0, ${opacity})`;
};
export { styled, css, keyframes, withTheme, createGlobalStyle, ThemeProvider };

View File

@@ -3,6 +3,7 @@ export const zIndex = {
mainContainer: 20,
dropdownItems: 30,
panel: 40,
containerOverlay: 45,
errorPopup: 50,
overlayDefault: 100,
};

View File

@@ -4,6 +4,7 @@ import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider } from 'ethereum-types';
// Reusable
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export type Maybe<T> = T | undefined;
export enum AsyncProcessState {
None = 'NONE',
@@ -101,11 +102,10 @@ export interface ProviderState {
}
export enum AccountState {
None = 'NONE,',
Loading = 'LOADING',
Ready = 'READY',
Locked = 'LOCKED', // TODO(bmillman): break this up into locked / privacy mode enabled
Error = 'ERROR',
None = 'NONE,',
Locked = 'LOCKED',
}
export interface AccountReady {
@@ -114,7 +114,7 @@ export interface AccountReady {
ethBalanceInWei?: BigNumber;
}
export interface AccountNotReady {
state: AccountState.None | AccountState.Loading | AccountState.Locked | AccountState.Error;
state: AccountState.None | AccountState.Loading | AccountState.Locked;
}
export type Account = AccountReady | AccountNotReady;
@@ -125,3 +125,15 @@ export interface AddressAndEthBalanceInWei {
address: string;
ethBalanceInWei: BigNumber;
}
export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none';
export enum StandardSlidingPanelContent {
None = 'NONE',
InstallWallet = 'INSTALL_WALLET',
}
export interface StandardSlidingPanelSettings {
animationState: SlideAnimationState;
content: StandardSlidingPanelContent;
}

View File

@@ -80,8 +80,6 @@ export const assetUtils = {
return metaData.symbol.toUpperCase();
case AssetProxyId.ERC721:
return metaData.name;
default:
return defaultName;
}
},
formattedSymbolForAsset: (asset?: ERC20Asset, defaultName: string = '???'): string => {

View File

@@ -15,13 +15,16 @@ export const buyQuoteUpdater = {
assetBuyer: AssetBuyer,
dispatch: Dispatch<Action>,
asset: ERC20Asset,
assetAmount: BigNumber,
assetUnitAmount: BigNumber,
setPending = true,
affiliateInfo?: AffiliateInfo,
): Promise<void> => {
// get a new buy quote.
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, asset.metaData.decimals);
// mark quote as pending
dispatch(actions.setQuoteRequestStatePending());
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals);
if (setPending) {
// mark quote as pending
dispatch(actions.setQuoteRequestStatePending());
}
const feePercentage = oc(affiliateInfo).feePercentage();
let newBuyQuote: BuyQuote | undefined;
try {

View File

@@ -8,9 +8,8 @@ const etherscanPrefix = (networkId: number): string | undefined => {
return 'kovan.';
case Network.Mainnet:
return '';
default:
return undefined;
}
return '';
};
export const etherscanUtil = {

Some files were not shown because too many files have changed in this diff Show More