aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChi Kei Chan <chikeichan@gmail.com>2019-05-07 23:03:27 +0800
committerDan J Miller <danjm.com@gmail.com>2019-05-07 23:03:26 +0800
commit581128503c161bc3b569ca5d87e4eea8b0d15150 (patch)
tree14b4b01936a7d7241e8cc65b4cd7f4141a5c8274
parenta58e549c3f6513d60b3b995598af14df7871546c (diff)
downloadtangerine-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
-rw-r--r--package-lock.json401
-rw-r--r--package.json2
-rw-r--r--ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js187
-rw-r--r--ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.state.js41
-rw-r--r--ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js126
-rw-r--r--ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss93
-rw-r--r--ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js76
-rw-r--r--ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js169
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')
+ })
+})