diff options
author | Chi Kei Chan <chikeichan@gmail.com> | 2019-05-07 23:03:27 +0800 |
---|---|---|
committer | Dan J Miller <danjm.com@gmail.com> | 2019-05-07 23:03:26 +0800 |
commit | 581128503c161bc3b569ca5d87e4eea8b0d15150 (patch) | |
tree | 14b4b01936a7d7241e8cc65b4cd7f4141a5c8274 | |
parent | a58e549c3f6513d60b3b995598af14df7871546c (diff) | |
download | tangerine-wallet-browser-581128503c161bc3b569ca5d87e4eea8b0d15150.tar tangerine-wallet-browser-581128503c161bc3b569ca5d87e4eea8b0d15150.tar.gz tangerine-wallet-browser-581128503c161bc3b569ca5d87e4eea8b0d15150.tar.bz2 tangerine-wallet-browser-581128503c161bc3b569ca5d87e4eea8b0d15150.tar.lz tangerine-wallet-browser-581128503c161bc3b569ca5d87e4eea8b0d15150.tar.xz tangerine-wallet-browser-581128503c161bc3b569ca5d87e4eea8b0d15150.tar.zst tangerine-wallet-browser-581128503c161bc3b569ca5d87e4eea8b0d15150.zip |
Allow dragging seed phrase during Confirm Seed Phrase (#6557)
* Add basic drag and drop functionality
* Refactor seed phrase data structure
* Insert to list when drop
* Save before refactor
* Finish DND
* Fix linter
* update package-lock.json
* Address styling feedbacks
* Add box shadow on hover
* Finish adding unit tests
* Remove describe.only
8 files changed, 818 insertions, 277 deletions
diff --git a/package-lock.json b/package-lock.json index 902dbe004..99aac3d53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1746,6 +1746,16 @@ } } }, + "@types/invariant": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.29.tgz", + "integrity": "sha512-lRVw09gOvgviOfeUrKc/pmTiRZ7g7oDOU6OAutyuSHpm1/o2RaBQvRhgK8QEdu+FFuw/wnWb29A/iuxv9i8OpQ==" + }, + "@types/lodash": { + "version": "4.14.123", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz", + "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==" + }, "@types/node": { "version": "8.5.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.5.tgz", @@ -1768,6 +1778,14 @@ "@types/react": "*" } }, + "@types/redux": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@types/redux/-/redux-3.6.0.tgz", + "integrity": "sha1-8evh5UEVGAcuT9/KXHbhbnTBOZo=", + "requires": { + "redux": "*" + } + }, "@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -8281,6 +8299,55 @@ } } }, + "disposables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/disposables/-/disposables-1.0.2.tgz", + "integrity": "sha1-NsamdEdfVaLWkTVnpgFETkh7S24=" + }, + "dnd-core": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-3.0.2.tgz", + "integrity": "sha1-6UdXdiBTHH7jelGM1d3hfQ798PM=", + "requires": { + "@types/invariant": "^2.2.29", + "@types/lodash": "^4.14.107", + "@types/node": "^8.10.11", + "@types/redux": "^3.6.0", + "asap": "^2.0.6", + "invariant": "^2.0.0", + "lodash": "^4.2.0", + "redux": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "8.10.48", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.48.tgz", + "integrity": "sha512-c35YEBTkL4rzXY2ucpSKy+UYHjUBIIkuJbWYbsGIrKLEWU5dgJMmLkkIb3qeC3O3Tpb1ZQCwecscvJTDjDjkRw==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "redux": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz", + "integrity": "sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + } + } + }, "dnode": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/dnode/-/dnode-1.2.2.tgz", @@ -9804,18 +9871,18 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" }, "dependencies": { "ethereumjs-util": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", - "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", - "ethjs-util": "0.1.6", + "ethjs-util": "^0.1.3", "keccak": "^1.0.2", "rlp": "^2.0.0", "safe-buffer": "^5.1.1", @@ -9823,23 +9890,15 @@ } } } - }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } } } }, "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" } }, "ethereumjs-util": { @@ -9873,7 +9932,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -9918,18 +9977,18 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" }, "dependencies": { "ethereumjs-util": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", - "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", - "ethjs-util": "0.1.6", + "ethjs-util": "^0.1.3", "keccak": "^1.0.2", "rlp": "^2.0.0", "safe-buffer": "^5.1.1", @@ -9937,15 +9996,6 @@ } } } - }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } } } }, @@ -9953,7 +10003,8 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" } }, "ethereumjs-util": { @@ -10122,19 +10173,19 @@ "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" }, "dependencies": { "ethereumjs-util": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", - "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", - "ethjs-util": "0.1.6", + "ethjs-util": "^0.1.3", "keccak": "^1.0.2", "rlp": "^2.0.0", "safe-buffer": "^5.1.1", @@ -10142,31 +10193,21 @@ } } } - }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } } } }, "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" } }, "ethereumjs-util": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -10267,7 +10308,8 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" } }, "ethereumjs-util": { @@ -10576,7 +10618,8 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" } }, "ethereumjs-util": { @@ -13616,7 +13659,7 @@ "dependencies": { "jsesc": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, @@ -13785,13 +13828,13 @@ }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", "dev": true }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", "dev": true }, @@ -14211,7 +14254,7 @@ }, "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "dev": true, "requires": { @@ -14298,7 +14341,7 @@ }, "bl": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "dev": true, "requires": { @@ -14376,7 +14419,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -14415,7 +14458,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -14604,7 +14647,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -14688,7 +14731,7 @@ }, "commander": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", "dev": true, "requires": { @@ -14787,7 +14830,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -14800,7 +14843,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -14891,7 +14934,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, "optional": true @@ -14968,14 +15011,14 @@ "dependencies": { "file-type": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", "dev": true, "optional": true }, "get-stream": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", "dev": true, "optional": true, @@ -14986,7 +15029,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, "optional": true @@ -15082,7 +15125,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "optional": true, @@ -15292,7 +15335,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -15313,7 +15356,7 @@ }, "eth-json-rpc-middleware": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", + "resolved": "http://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", "dev": true, "requires": { @@ -15340,7 +15383,7 @@ }, "ethereumjs-block": { "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "resolved": "http://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", "dev": true, "requires": { @@ -15456,13 +15499,13 @@ "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" } }, "ethereumjs-block": { "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "resolved": "http://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", "dev": true, "requires": { @@ -15494,7 +15537,7 @@ }, "fs-extra": { "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "dev": true, "requires": { @@ -15507,7 +15550,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -15532,7 +15575,7 @@ }, "web3-provider-engine": { "version": "13.8.0", - "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz", + "resolved": "http://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz", "integrity": "sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ==", "dev": true, "requires": { @@ -15577,7 +15620,7 @@ "dependencies": { "ethereumjs-util": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "resolved": "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", "dev": true, "requires": { @@ -15986,7 +16029,7 @@ }, "finalhandler": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "dev": true, "requires": { @@ -16610,7 +16653,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, @@ -16809,7 +16852,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -17051,7 +17094,7 @@ }, "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true }, @@ -17113,13 +17156,13 @@ }, "json5": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, "jsonfile": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { @@ -17201,7 +17244,7 @@ }, "level-iterator-stream": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "resolved": "http://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", "dev": true, "requires": { @@ -17222,7 +17265,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -17292,7 +17335,7 @@ "dependencies": { "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -17359,7 +17402,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { @@ -17372,7 +17415,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -17458,7 +17501,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, @@ -17501,7 +17544,7 @@ }, "merkle-patricia-tree": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", + "resolved": "http://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", "dev": true, "requires": { @@ -17517,7 +17560,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, @@ -17629,13 +17672,13 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -17686,7 +17729,7 @@ }, "nan": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "nano-json-stream-parser": { @@ -17703,7 +17746,7 @@ }, "node-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", "dev": true }, @@ -17796,13 +17839,13 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { @@ -17811,7 +17854,7 @@ }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, @@ -17886,7 +17929,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -17915,7 +17958,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -18117,7 +18160,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -18193,7 +18236,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -18259,7 +18302,7 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, @@ -18565,7 +18608,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -18730,7 +18773,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -18816,7 +18859,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -18824,7 +18867,7 @@ }, "tar": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "resolved": "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "optional": true, @@ -18865,7 +18908,7 @@ "dependencies": { "bluebird": { "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", "dev": true, "optional": true @@ -18892,7 +18935,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, @@ -19324,7 +19367,7 @@ }, "uuid": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", "dev": true, "optional": true @@ -19439,8 +19482,8 @@ "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" } }, "ethereumjs-block": { @@ -19557,7 +19600,7 @@ }, "utf8": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=", "dev": true } @@ -19588,7 +19631,7 @@ }, "whatwg-fetch": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", "dev": true }, @@ -19606,7 +19649,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { @@ -19696,7 +19739,7 @@ }, "yargs": { "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "dev": true, "requires": { @@ -19718,7 +19761,7 @@ }, "yargs-parser": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "dev": true, "requires": { @@ -24069,7 +24112,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -24108,7 +24151,7 @@ }, "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -26534,7 +26577,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -29849,16 +29892,6 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, - "ping-pong-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ping-pong-stream/-/ping-pong-stream-1.0.0.tgz", - "integrity": "sha1-TF6wm6atsCGInawNyr+45XcGhUo=", - "requires": { - "end-of-stream": "^1.1.0", - "readable-stream": "^2.1.5", - "tape": "^4.6.2" - } - }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", @@ -32546,6 +32579,84 @@ } } }, + "react-dnd": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-3.0.2.tgz", + "integrity": "sha1-sMI9jYKWn1t740y8T4T6H/xcfdw=", + "requires": { + "disposables": "^1.0.1", + "dnd-core": "^3.0.2", + "hoist-non-react-statics": "^2.5.0", + "invariant": "^2.1.0", + "lodash": "^4.2.0", + "prop-types": "^15.5.10", + "shallowequal": "^1.0.2" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", + "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + } + } + }, + "react-dnd-html5-backend": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-7.4.4.tgz", + "integrity": "sha512-X/lP92ateY0glHan8mU0JzjBuZL6VHv2Gc/H9OBBxaf/ZCN1oC16MLKdesqG4x1f/NWFTNtuG3W4B99r5gPVog==", + "requires": { + "dnd-core": "^7.4.4" + }, + "dependencies": { + "dnd-core": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-7.4.4.tgz", + "integrity": "sha512-xR8SINDCJG9AmKSjXUMJ1PEl8ih1+xSHH8x4DgBtzScXnEtpCnV1ibDZNV0uyps9VgkXTTbYYzJdF04y0v0e3Q==", + "requires": { + "asap": "^2.0.6", + "invariant": "^2.2.4", + "redux": "^4.0.1" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "redux": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz", + "integrity": "sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + } + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + } + } + }, "react-docgen": { "version": "3.0.0-beta9", "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-3.0.0-beta9.tgz", @@ -38924,34 +39035,24 @@ "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.10.0", + "ethereumjs-util": "^5.0.0" }, "dependencies": { "ethereumjs-util": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", - "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", - "ethjs-util": "0.1.6", + "ethjs-util": "^0.1.3", "keccak": "^1.0.2", "rlp": "^2.0.0", "safe-buffer": "^5.1.1", "secp256k1": "^3.0.1" } - }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } } } }, diff --git a/package.json b/package.json index 21e9b0de8..0626b4ac8 100644 --- a/package.json +++ b/package.json @@ -151,6 +151,8 @@ "ramda": "^0.24.1", "react": "^15.6.2", "react-addons-css-transition-group": "^15.6.0", + "react-dnd": "^3.0.2", + "react-dnd-html5-backend": "^7.4.4", "react-dom": "^15.6.2", "react-hyperscript": "^3.0.0", "react-inspector": "^2.3.0", diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index f3bfc3171..04fe651e6 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -8,7 +8,9 @@ import { INITIALIZE_SEED_PHRASE_ROUTE, } from '../../../../helpers/constants/routes' import { exportAsFile } from '../../../../helpers/utils/util' -import { selectSeedWord, deselectSeedWord } from './confirm-seed-phrase.state' +import DraggableSeed from './draggable-seed.component' + +const EMPTY_SEEDS = Array(12).fill(null) export default class ConfirmSeedPhrase extends PureComponent { static contextTypes = { @@ -27,10 +29,32 @@ export default class ConfirmSeedPhrase extends PureComponent { } state = { - selectedSeedWords: [], + selectedSeedIndices: [], shuffledSeedWords: [], - // Hash of shuffledSeedWords index {Number} to selectedSeedWords index {Number} - selectedSeedWordsHash: {}, + pendingSeedIndices: [], + draggingSeedIndex: -1, + hoveringIndex: -1, + isDragging: false, + } + + shouldComponentUpdate (nextProps, nextState, nextContext) { + const { seedPhrase } = this.props + const { + selectedSeedIndices, + shuffledSeedWords, + pendingSeedIndices, + draggingSeedIndex, + hoveringIndex, + isDragging, + } = this.state + + return seedPhrase !== nextProps.seedPhrase || + draggingSeedIndex !== nextState.draggingSeedIndex || + isDragging !== nextState.isDragging || + hoveringIndex !== nextState.hoveringIndex || + selectedSeedIndices.join(' ') !== nextState.selectedSeedIndices.join(' ') || + shuffledSeedWords.join(' ') !== nextState.shuffledSeedWords.join(' ') || + pendingSeedIndices.join(' ') !== nextState.pendingSeedIndices.join(' ') } componentDidMount () { @@ -39,6 +63,26 @@ export default class ConfirmSeedPhrase extends PureComponent { this.setState({ shuffledSeedWords }) } + setDraggingSeedIndex = draggingSeedIndex => this.setState({ draggingSeedIndex }) + + setHoveringIndex = hoveringIndex => this.setState({ hoveringIndex }) + + onDrop = targetIndex => { + const { + selectedSeedIndices, + draggingSeedIndex, + } = this.state + + const indices = insert(selectedSeedIndices, draggingSeedIndex, targetIndex, true) + + this.setState({ + selectedSeedIndices: indices, + pendingSeedIndices: indices, + draggingSeedIndex: -1, + hoveringIndex: -1, + }) + } + handleExport = () => { exportAsFile('MetaMask Secret Backup Phrase', this.props.seedPhrase, 'text/plain') } @@ -65,23 +109,34 @@ export default class ConfirmSeedPhrase extends PureComponent { } handleSelectSeedWord = (word, shuffledIndex) => { - this.setState(selectSeedWord(word, shuffledIndex)) + this.setState({ + selectedSeedIndices: [...this.state.selectedSeedIndices, shuffledIndex], + pendingSeedIndices: [...this.state.pendingSeedIndices, shuffledIndex], + }) } handleDeselectSeedWord = shuffledIndex => { - this.setState(deselectSeedWord(shuffledIndex)) + this.setState({ + selectedSeedIndices: this.state.selectedSeedIndices.filter(i => shuffledIndex !== i), + pendingSeedIndices: this.state.pendingSeedIndices.filter(i => shuffledIndex !== i), + }) } isValid () { const { seedPhrase } = this.props - const { selectedSeedWords } = this.state + const { selectedSeedIndices, shuffledSeedWords } = this.state + const selectedSeedWords = selectedSeedIndices.map(i => shuffledSeedWords[i]) return seedPhrase === selectedSeedWords.join(' ') } render () { const { t } = this.context const { history } = this.props - const { selectedSeedWords, shuffledSeedWords, selectedSeedWordsHash } = this.state + const { + selectedSeedIndices, + shuffledSeedWords, + draggingSeedIndex, + } = this.state return ( <div className="confirm-seed-phrase"> @@ -102,31 +157,30 @@ export default class ConfirmSeedPhrase extends PureComponent { <div className="first-time-flow__text-block"> { t('selectEachPhrase') } </div> - <div className="confirm-seed-phrase__selected-seed-words"> - { - selectedSeedWords.map((word, index) => ( - <div - key={index} - className="confirm-seed-phrase__seed-word" - > - { word } - </div> - )) - } + <div + className={classnames('confirm-seed-phrase__selected-seed-words', { + 'confirm-seed-phrase__selected-seed-words--dragging': draggingSeedIndex > -1, + })} + > + { this.renderPendingSeeds() } + { this.renderSelectedSeeds() } </div> <div className="confirm-seed-phrase__shuffled-seed-words"> { shuffledSeedWords.map((word, index) => { - const isSelected = index in selectedSeedWordsHash + const isSelected = selectedSeedIndices.includes(index) return ( - <div + <DraggableSeed key={index} - className={classnames( - 'confirm-seed-phrase__seed-word', - 'confirm-seed-phrase__seed-word--shuffled', - { 'confirm-seed-phrase__seed-word--selected': isSelected } - )} + seedIndex={index} + index={index} + draggingSeedIndex={this.state.draggingSeedIndex} + setDraggingSeedIndex={this.setDraggingSeedIndex} + setHoveringIndex={this.setHoveringIndex} + onDrop={this.onDrop} + className="confirm-seed-phrase__seed-word--shuffled" + selected={isSelected} onClick={() => { if (!isSelected) { this.handleSelectSeedWord(word, index) @@ -134,9 +188,8 @@ export default class ConfirmSeedPhrase extends PureComponent { this.handleDeselectSeedWord(index) } }} - > - { word } - </div> + word={word} + /> ) }) } @@ -152,4 +205,80 @@ export default class ConfirmSeedPhrase extends PureComponent { </div> ) } + + renderSelectedSeeds () { + const { shuffledSeedWords, selectedSeedIndices, draggingSeedIndex } = this.state + return EMPTY_SEEDS.map((_, index) => { + const seedIndex = selectedSeedIndices[index] + const word = shuffledSeedWords[seedIndex] + + return ( + <DraggableSeed + key={`selected-${seedIndex}-${index}`} + className="confirm-seed-phrase__selected-seed-words__selected-seed" + index={index} + seedIndex={seedIndex} + word={word} + draggingSeedIndex={draggingSeedIndex} + setDraggingSeedIndex={this.setDraggingSeedIndex} + setHoveringIndex={this.setHoveringIndex} + onDrop={this.onDrop} + draggable + /> + ) + }) + } + + renderPendingSeeds () { + const { + pendingSeedIndices, + shuffledSeedWords, + draggingSeedIndex, + hoveringIndex, + } = this.state + + const indices = insert(pendingSeedIndices, draggingSeedIndex, hoveringIndex) + + return EMPTY_SEEDS.map((_, index) => { + const seedIndex = indices[index] + const word = shuffledSeedWords[seedIndex] + + return ( + <DraggableSeed + key={`pending-${seedIndex}-${index}`} + index={index} + className={classnames('confirm-seed-phrase__selected-seed-words__pending-seed', { + 'confirm-seed-phrase__seed-word--hidden': draggingSeedIndex === seedIndex && index !== hoveringIndex, + })} + seedIndex={seedIndex} + word={word} + draggingSeedIndex={draggingSeedIndex} + setDraggingSeedIndex={this.setDraggingSeedIndex} + setHoveringIndex={this.setHoveringIndex} + onDrop={this.onDrop} + droppable={!!word} + /> + ) + }) + } +} + +function insert (list, value, target, removeOld) { + let nextList = [...list] + + if (typeof list[target] === 'number') { + nextList = [...list.slice(0, target), value, ...list.slice(target)] + } + + if (removeOld) { + nextList = nextList.filter((seed, i) => { + return seed !== value || i === target + }) + } + + if (nextList.length > 12) { + nextList.pop() + } + + return nextList } diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.state.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.state.js deleted file mode 100644 index f2476fc5c..000000000 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.state.js +++ /dev/null @@ -1,41 +0,0 @@ -export function selectSeedWord (word, shuffledIndex) { - return function update (state) { - const { selectedSeedWords, selectedSeedWordsHash } = state - const nextSelectedIndex = selectedSeedWords.length - - return { - selectedSeedWords: [ ...selectedSeedWords, word ], - selectedSeedWordsHash: { ...selectedSeedWordsHash, [shuffledIndex]: nextSelectedIndex }, - } - } -} - -export function deselectSeedWord (shuffledIndex) { - return function update (state) { - const { - selectedSeedWords: prevSelectedSeedWords, - selectedSeedWordsHash: prevSelectedSeedWordsHash, - } = state - - const selectedSeedWords = [...prevSelectedSeedWords] - const indexToRemove = prevSelectedSeedWordsHash[shuffledIndex] - selectedSeedWords.splice(indexToRemove, 1) - const selectedSeedWordsHash = Object.keys(prevSelectedSeedWordsHash).reduce((acc, index) => { - const output = { ...acc } - const selectedSeedWordIndex = prevSelectedSeedWordsHash[index] - - if (selectedSeedWordIndex < indexToRemove) { - output[index] = selectedSeedWordIndex - } else if (selectedSeedWordIndex > indexToRemove) { - output[index] = selectedSeedWordIndex - 1 - } - - return output - }, {}) - - return { - selectedSeedWords, - selectedSeedWordsHash, - } - } -} diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js new file mode 100644 index 000000000..97dbd2a4b --- /dev/null +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js @@ -0,0 +1,126 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' +import { DragSource, DropTarget } from 'react-dnd' + +class DraggableSeed extends Component { + + static propTypes = { + // React DnD Props + connectDragSource: PropTypes.func.isRequired, + connectDropTarget: PropTypes.func.isRequired, + isDragging: PropTypes.bool, + isOver: PropTypes.bool, + canDrop: PropTypes.bool, + // Own Props + onClick: PropTypes.func.isRequired, + setHoveringIndex: PropTypes.func.isRequired, + index: PropTypes.number, + draggingSeedIndex: PropTypes.number, + word: PropTypes.string, + className: PropTypes.string, + selected: PropTypes.bool, + droppable: PropTypes.bool, + } + + static defaultProps = { + className: '', + onClick () {}, + } + + componentWillReceiveProps (nextProps, nextContext) { + const { isOver, setHoveringIndex } = this.props + if (isOver && !nextProps.isOver) { + setHoveringIndex(-1) + } + } + + render () { + const { + connectDragSource, + connectDropTarget, + isDragging, + index, + word, + selected, + className, + onClick, + isOver, + canDrop, + } = this.props + + return connectDropTarget(connectDragSource( + <div + key={index} + className={classnames('btn-secondary confirm-seed-phrase__seed-word', className, { + 'confirm-seed-phrase__seed-word--selected btn-primary': selected, + 'confirm-seed-phrase__seed-word--dragging': isDragging, + 'confirm-seed-phrase__seed-word--empty': !word, + 'confirm-seed-phrase__seed-word--active-drop': !isOver && canDrop, + 'confirm-seed-phrase__seed-word--drop-hover': isOver && canDrop, + })} + onClick={onClick} + > + { word } + </div> + )) + } +} + +const SEEDWORD = 'SEEDWORD' + +const seedSource = { + beginDrag (props) { + setTimeout(() => props.setDraggingSeedIndex(props.seedIndex), 0) + return { + seedIndex: props.seedIndex, + word: props.word, + } + }, + canDrag (props) { + return props.draggable + }, + endDrag (props, monitor) { + const dropTarget = monitor.getDropResult() + + if (!dropTarget) { + setTimeout(() => props.setDraggingSeedIndex(-1), 0) + return + } + + props.onDrop(dropTarget.targetIndex) + }, +} + +const seedTarget = { + drop (props) { + return { + targetIndex: props.index, + } + }, + canDrop (props) { + return props.droppable + }, + hover (props) { + props.setHoveringIndex(props.index) + }, +} + +const collectDrag = (connect, monitor) => { + return { + connectDragSource: connect.dragSource(), + isDragging: monitor.isDragging(), + } +} + +const collectDrop = (connect, monitor) => { + return { + connectDropTarget: connect.dropTarget(), + isOver: monitor.isOver(), + canDrop: monitor.canDrop(), + } +} + +export default DropTarget(SEEDWORD, seedTarget, collectDrop)(DragSource(SEEDWORD, seedSource, collectDrag)(DraggableSeed)) + + diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss index 93137618c..f025a503f 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss @@ -3,37 +3,58 @@ margin-bottom: 12px; } - &__selected-seed-words { - min-height: 190px; - max-width: 496px; - border: 1px solid #CDCDCD; - border-radius: 6px; - background-color: $white; - margin: 24px 0 36px; - padding: 12px; - } - &__shuffled-seed-words { - max-width: 496px; + max-width: 575px; } &__seed-word { - display: inline-block; - color: #5B5D67; - background-color: #E7E7E7; + display: inline-flex; + flex-flow: row nowrap; + align-items: center; + justify-content: center; padding: 8px 18px; - min-width: 64px; + width: 128px; + height: 41px; margin: 4px; text-align: center; + border-radius: 4px; + cursor: move; + + &--shuffled { + cursor: pointer; + margin: 6px; + } &--selected { - background-color: #85D1CC; color: $white; } - &--shuffled { - cursor: pointer; - margin: 6px; + &--dragging { + margin: 0; + } + + &--empty { + background-color: transparent; + border-color: transparent; + cursor: default; + + &:hover, + &:active { + background-color: transparent; + border-color: transparent; + cursor: default; + box-shadow: none !important; + } + } + + &--hidden { + display: none !important; + } + + &--drop-hover { + background-color: transparent; + border-color: transparent; + color: transparent; } @media screen and (max-width: 575px) { @@ -42,7 +63,37 @@ } } - button { - margin-top: 0xp; + &__selected-seed-words { + display: flex; + flex-flow: row wrap; + min-height: 161px; + max-width: 575px; + border: 1px solid #CDCDCD; + border-radius: 6px; + background-color: $white; + margin: 24px 0 36px; + padding: 12px; + + &__pending-seed { + display: none; + } + + &__selected-seed { + display: inline-flex; + + &:hover { + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); + } + } + + &--dragging { + .confirm-seed-phrase__selected-seed-words__pending-seed { + display: inline-flex; + } + + .confirm-seed-phrase__selected-seed-words__selected-seed { + display: none; + } + } } } diff --git a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js index 9a9f84049..0b19af18c 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js @@ -8,6 +8,8 @@ import { INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE, DEFAULT_ROUTE, } from '../../../helpers/constants/routes' +import HTML5Backend from 'react-dnd-html5-backend' +import {DragDropContextProvider} from 'react-dnd' export default class SeedPhrase extends PureComponent { static propTypes = { @@ -28,43 +30,45 @@ export default class SeedPhrase extends PureComponent { const { seedPhrase } = this.props return ( - <div className="first-time-flow__wrapper"> - <div className="app-header__logo-container"> - <img - className="app-header__metafox-logo app-header__metafox-logo--horizontal" - src="/images/logo/metamask-logo-horizontal.svg" - height={30} - /> - <img - className="app-header__metafox-logo app-header__metafox-logo--icon" - src="/images/logo/metamask-fox.svg" - height={42} - width={42} - /> + <DragDropContextProvider backend={HTML5Backend}> + <div className="first-time-flow__wrapper"> + <div className="app-header__logo-container"> + <img + className="app-header__metafox-logo app-header__metafox-logo--horizontal" + src="/images/logo/metamask-logo-horizontal.svg" + height={30} + /> + <img + className="app-header__metafox-logo app-header__metafox-logo--icon" + src="/images/logo/metamask-fox.svg" + height={42} + width={42} + /> + </div> + <Switch> + <Route + exact + path={INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE} + render={props => ( + <ConfirmSeedPhrase + { ...props } + seedPhrase={seedPhrase} + /> + )} + /> + <Route + exact + path={INITIALIZE_SEED_PHRASE_ROUTE} + render={props => ( + <RevealSeedPhrase + { ...props } + seedPhrase={seedPhrase} + /> + )} + /> + </Switch> </div> - <Switch> - <Route - exact - path={INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE} - render={props => ( - <ConfirmSeedPhrase - { ...props } - seedPhrase={seedPhrase} - /> - )} - /> - <Route - exact - path={INITIALIZE_SEED_PHRASE_ROUTE} - render={props => ( - <RevealSeedPhrase - { ...props } - seedPhrase={seedPhrase} - /> - )} - /> - </Switch> - </div> + </DragDropContextProvider> ) } } diff --git a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js new file mode 100644 index 000000000..8339a6f6f --- /dev/null +++ b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js @@ -0,0 +1,169 @@ +import React from 'react' +import assert from 'assert' +import { shallow } from 'enzyme' +import sinon from 'sinon' +import ConfirmSeedPhrase from '../confirm-seed-phrase/confirm-seed-phrase.component' + +function shallowRender (props = {}, context = {}) { + return shallow( + <ConfirmSeedPhrase {...props} />, + { + context: { + t: str => str + '_t', + ...context, + }, + } + ) +} + +describe('ConfirmSeedPhrase Component', () => { + it('should render correctly', () => { + const root = shallowRender({ + seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', + }) + + assert.equal( + root.find('.confirm-seed-phrase__seed-word--shuffled').length, + 12, + 'should render 12 seed phrases' + ) + }) + + it('should add/remove selected on click', () => { + const metricsEventSpy = sinon.spy() + const pushSpy = sinon.spy() + const root = shallowRender( + { + seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', + history: { push: pushSpy }, + }, + { + metricsEvent: metricsEventSpy, + } + ) + + const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + + // Click on 3 seeds to add to selected + seeds.at(0).simulate('click') + seeds.at(1).simulate('click') + seeds.at(2).simulate('click') + + assert.deepEqual( + root.state().selectedSeedIndices, + [0, 1, 2], + 'should add seed phrase to selected on click', + ) + + // Click on a selected seed to remove + root.state() + root.update() + root.state() + root.find('.confirm-seed-phrase__seed-word--shuffled').at(1).simulate('click') + assert.deepEqual( + root.state().selectedSeedIndices, + [0, 2], + 'should remove seed phrase from selected when click again', + ) + }) + + it('should render correctly on hover', () => { + const metricsEventSpy = sinon.spy() + const pushSpy = sinon.spy() + const root = shallowRender( + { + seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', + history: { push: pushSpy }, + }, + { + metricsEvent: metricsEventSpy, + } + ) + + const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + + // Click on 3 seeds to add to selected + seeds.at(0).simulate('click') + seeds.at(1).simulate('click') + seeds.at(2).simulate('click') + + // Dragging Seed # 2 to 0 placeth + root.instance().setDraggingSeedIndex(2) + root.instance().setHoveringIndex(0) + + root.update() + + const pendingSeeds = root.find('.confirm-seed-phrase__selected-seed-words__pending-seed') + + assert.equal(pendingSeeds.at(0).props().seedIndex, 2) + assert.equal(pendingSeeds.at(1).props().seedIndex, 0) + assert.equal(pendingSeeds.at(2).props().seedIndex, 1) + }) + + it('should insert seed in place on drop', () => { + const metricsEventSpy = sinon.spy() + const pushSpy = sinon.spy() + const root = shallowRender( + { + seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', + history: { push: pushSpy }, + }, + { + metricsEvent: metricsEventSpy, + } + ) + + const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + + // Click on 3 seeds to add to selected + seeds.at(0).simulate('click') + seeds.at(1).simulate('click') + seeds.at(2).simulate('click') + + // Drop Seed # 2 to 0 placeth + root.instance().setDraggingSeedIndex(2) + root.instance().setHoveringIndex(0) + root.instance().onDrop(0) + + root.update() + + assert.deepEqual(root.state().selectedSeedIndices, [2, 0, 1]) + assert.deepEqual(root.state().pendingSeedIndices, [2, 0, 1]) + }) + + it('should submit correctly', () => { + const originalSeed = ['鼠', '牛', '虎', '兔', '龍', '蛇', '馬', '羊', '猴', '雞', '狗', '豬'] + const metricsEventSpy = sinon.spy() + const pushSpy = sinon.spy() + const root = shallowRender( + { + seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', + history: { push: pushSpy }, + }, + { + metricsEvent: metricsEventSpy, + } + ) + + const shuffled = root.state().shuffledSeedWords + const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + + + originalSeed.forEach(seed => { + const seedIndex = shuffled.findIndex(s => s === seed) + seeds.at(seedIndex).simulate('click') + }) + + root.update() + + root.find('.first-time-flow__button').simulate('click') + assert.deepEqual(metricsEventSpy.args[0][0], { + eventOpts: { + category: 'Onboarding', + action: 'Seed Phrase Setup', + name: 'Verify Complete', + }, + }) + assert.equal(pushSpy.args[0][0], '/initialize/end-of-flow') + }) +}) |