Merge branch 'master' into upload-crates

This commit is contained in:
Robert Habermeier 2017-11-17 16:42:41 +01:00
commit 81212c5031
239 changed files with 9671 additions and 16026 deletions

3
.gitignore vendored
View File

@ -24,6 +24,9 @@
npm-debug.log
node_modules
# js build artifacts
.git-release.log
# gdb files
.gdb_history

View File

@ -690,9 +690,10 @@ js-release:
script:
- rustup default stable
- echo $JS_FILES_MODIFIED
- if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS rebuild since no JS files modified."; else ./js/scripts/build.sh && ./js/scripts/release.sh; fi
- if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS rebuild since no JS files modified."; else ./js/scripts/build.sh && ./js/scripts/push-precompiled.sh; fi
- echo $JS_OLD_FILES_MODIFIED
- if [ $JS_OLD_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS (old) rebuild since no JS files modified."; else ./js-old/scripts/build.sh && ./js-old/scripts/release.sh; fi
- if [ $JS_OLD_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS (old) rebuild since no JS files modified."; else ./js-old/scripts/build.sh && ./js-old/scripts/push-precompiled.sh; fi
- if [ $JS_FILES_MODIFIED -eq 0 ] && [ $JS_OLD_FILES_MODIFIED -eq 0 ]; then echo "Skipping Cargo update since no JS files modified."; else ./js/scripts/push-cargo.sh; fi
tags:
- javascript

View File

@ -1,3 +1,42 @@
## Parity [v1.8.3](https://github.com/paritytech/parity/releases/tag/v1.8.3) (2017-11-15)
Parity 1.8.3 contains several bug-fixes and removes the ability to deploy built-in multi-signature wallets.
The full list of included changes:
- Backports to beta ([#7043](https://github.com/paritytech/parity/pull/7043))
- pwasm-std update ([#7018](https://github.com/paritytech/parity/pull/7018))
- Version 1.8.3
- Make CLI arguments parsing more backwards compatible ([#7004](https://github.com/paritytech/parity/pull/7004))
- Skip nonce check for gas estimation ([#6997](https://github.com/paritytech/parity/pull/6997))
- Events in WASM runtime ([#6967](https://github.com/paritytech/parity/pull/6967))
- Return decoded seal fields. ([#6932](https://github.com/paritytech/parity/pull/6932))
- Fix serialization of status in transaction receipts. ([#6926](https://github.com/paritytech/parity/pull/6926))
- Windows fixes ([#6921](https://github.com/paritytech/parity/pull/6921))
- Disallow built-in multi-sig deploy (only watch) ([#7014](https://github.com/paritytech/parity/pull/7014))
- Add hint in ActionParams for splitting code/data ([#6968](https://github.com/paritytech/parity/pull/6968))
- Action params and embedded params handling
- Fix name-spaces
## Parity [v1.8.2](https://github.com/paritytech/parity/releases/tag/v1.8.2) (2017-10-26)
Parity 1.8.2 fixes an important potential consensus issue and a few additional minor issues:
- `blockNumber` transaction field is now returned correctly in RPC calls.
- Possible crash when `--force-sealing` option is used.
The full list of included changes:
- Beta Backports ([#6891](https://github.com/paritytech/parity/pull/6891))
- Bump to v1.8.2
- Refactor static context check in CREATE. ([#6886](https://github.com/paritytech/parity/pull/6886))
- Refactor static context check in CREATE.
- Fix wasm.
- Fix serialization of non-localized transactions ([#6868](https://github.com/paritytech/parity/pull/6868))
- Fix serialization of non-localized transactions.
- Return proper SignedTransactions representation.
- Allow force sealing and reseal=0 for non-dev chains. ([#6878](https://github.com/paritytech/parity/pull/6878))
## Parity [v1.8.1](https://github.com/paritytech/parity/releases/tag/v1.8.1) (2017-10-20)
Parity 1.8.1 fixes several bugs with token balances, tweaks snapshot-sync, improves the performance of nodes with huge amounts of accounts and changes the Trezor account derivation path.
@ -13,7 +52,7 @@ Parity 1.8.1 fixes several bugs with token balances, tweaks snapshot-sync, impro
If you don't want to downgrade or move your funds off your Trezor-device, you can also use the official Trezor application or other wallets allowing to select the derivation path to access the funds.
Full list of included changes:
The full list of included changes:
- Add ECIP1017 to Morden config ([#6845](https://github.com/paritytech/parity/pull/6845))
- Ethstore optimizations ([#6844](https://github.com/paritytech/parity/pull/6844))
@ -45,7 +84,7 @@ Further, users upgrading from 1.7 should acknowledge the following changes:
- `trace_filter` RPC method now comes with pagination. [#6312](https://github.com/paritytech/parity/pull/6312)
- Added tracing of rewards on closing blocks. [#6194](https://github.com/paritytech/parity/pull/6194)
Full list of included changes:
The full list of included changes:
- Updated ethabi to fix auto-update ([#6771](https://github.com/paritytech/parity/pull/6771))
- Fixed kovan chain validation ([#6760](https://github.com/paritytech/parity/pull/6760))

135
Cargo.lock generated
View File

@ -424,9 +424,6 @@ dependencies = [
name = "error-chain"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "eth-secp256k1"
@ -586,7 +583,6 @@ dependencies = [
"ethcore 1.9.0",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
"ethcore-devtools 1.9.0",
"ethcore-io 1.9.0",
"ethcore-network 1.9.0",
"ethcore-util 1.9.0",
@ -610,6 +606,7 @@ dependencies = [
"serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"stats 0.1.0",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.0",
"vm 0.1.0",
@ -637,6 +634,7 @@ dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
"ethcore-devtools 1.9.0",
@ -673,7 +671,6 @@ dependencies = [
"ethcore 1.9.0",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
"ethcore-devtools 1.9.0",
"ethcore-logger 1.9.0",
"ethcore-util 1.9.0",
"ethcrypto 0.1.0",
@ -692,6 +689,7 @@ dependencies = [
"serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -706,12 +704,11 @@ version = "1.9.0"
dependencies = [
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1",
"ethcore-devtools 1.9.0",
"ethcore-logger 1.9.0",
"ethcore-util 1.9.0",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"keccak-hash 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -847,7 +844,6 @@ dependencies = [
"ethcore 1.9.0",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
"ethcore-devtools 1.9.0",
"ethcore-io 1.9.0",
"ethcore-light 1.9.0",
"ethcore-network 1.9.0",
@ -1168,6 +1164,11 @@ name = "integer-encoding"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "interleaved-ordered"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "iovec"
version = "0.1.0"
@ -1227,7 +1228,7 @@ dependencies = [
[[package]]
name = "jsonrpc-core"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1239,11 +1240,11 @@ dependencies = [
[[package]]
name = "jsonrpc-http-server"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"hyper 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1252,10 +1253,10 @@ dependencies = [
[[package]]
name = "jsonrpc-ipc-server"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1264,19 +1265,19 @@ dependencies = [
[[package]]
name = "jsonrpc-macros"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jsonrpc-pubsub"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1284,11 +1285,11 @@ dependencies = [
[[package]]
name = "jsonrpc-server-utils"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1297,10 +1298,10 @@ dependencies = [
[[package]]
name = "jsonrpc-tcp-server"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1309,10 +1310,11 @@ dependencies = [
[[package]]
name = "jsonrpc-ws-server"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8#cf6f3481760f6ee8fbef7a987954ffc720ff4acf"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
dependencies = [
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1362,6 +1364,7 @@ version = "0.1.0"
dependencies = [
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1",
"interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"kvdb 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1923,7 +1926,7 @@ dependencies = [
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"journaldb 0.1.0",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"keccak-hash 0.1.0",
"kvdb 0.1.0",
"kvdb-rocksdb 0.1.0",
@ -1977,8 +1980,8 @@ dependencies = [
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"keccak-hash 0.1.0",
"linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2056,9 +2059,8 @@ dependencies = [
"ethcore 1.9.0",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
"ethcore-util 1.9.0",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1",
"unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2070,7 +2072,6 @@ version = "0.1.0"
dependencies = [
"ethcore 1.9.0",
"ethcore-io 1.9.0",
"ethcore-util 1.9.0",
"ethkey 0.2.0",
"kvdb 0.1.0",
"kvdb-memorydb 0.1.0",
@ -2124,13 +2125,12 @@ dependencies = [
"futures-cpupool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"hardware-wallet 1.9.0",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-ipc-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"keccak-hash 0.1.0",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-ipc-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"kvdb-memorydb 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"macros 0.1.0",
@ -2151,6 +2151,7 @@ dependencies = [
"serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"stats 0.1.0",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
@ -2161,8 +2162,8 @@ name = "parity-rpc-client"
version = "1.4.0"
dependencies = [
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"keccak-hash 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2196,7 +2197,7 @@ version = "1.9.0"
dependencies = [
"parity-ui-dev 1.9.0",
"parity-ui-old-dev 1.9.0",
"parity-ui-old-precompiled 1.8.0 (git+https://github.com/paritytech/js-precompiled.git?branch=v1)",
"parity-ui-old-precompiled 1.9.0 (git+https://github.com/paritytech/js-precompiled.git?branch=v1)",
"parity-ui-precompiled 1.9.0 (git+https://github.com/paritytech/js-precompiled.git)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2217,8 +2218,8 @@ dependencies = [
[[package]]
name = "parity-ui-old-precompiled"
version = "1.8.0"
source = "git+https://github.com/paritytech/js-precompiled.git?branch=v1#94b0a89aac7eb5ddfdb53cd9bb039da6fdbf7583"
version = "1.9.0"
source = "git+https://github.com/paritytech/js-precompiled.git?branch=v1#f3fa5e5efb0ed8ada6cd091694fcdaa921e6720f"
dependencies = [
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2226,7 +2227,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.9.0"
source = "git+https://github.com/paritytech/js-precompiled.git#1626d64235241e75c531eece004a4923d9d4fcc6"
source = "git+https://github.com/paritytech/js-precompiled.git#5b3e31509c369f558c8cb90f6f9918e50cdb2501"
dependencies = [
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2253,7 +2254,7 @@ dependencies = [
[[package]]
name = "parity-wasm"
version = "0.15.1"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2272,9 +2273,9 @@ dependencies = [
"ethcrypto 0.1.0",
"ethkey 0.2.0",
"hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2939,6 +2940,7 @@ name = "snappy"
version = "0.1.0"
dependencies = [
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)",
]
[[package]]
@ -3417,7 +3419,7 @@ dependencies = [
"ethcore-logger 1.9.0",
"ethcore-util 1.9.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
]
@ -3433,7 +3435,7 @@ dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -3580,19 +3582,20 @@ dependencies = [
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356a0dc23a4fa0f8ce4777258085d00a01ea4923b2efd93538fc44bf5e1bda76"
"checksum integer-encoding 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a053c9c7dcb7db1f2aa012c37dc176c62e4cdf14898dee0eecc606de835b8acb"
"checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77"
"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
"checksum ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2134e210e2a024b5684f90e1556d5f71a1ce7f8b12e9ac9924c67fb36f63b336"
"checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f"
"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
"checksum jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-ipc-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)" = "<none>"
"checksum jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum jsonrpc-ipc-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)" = "<none>"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
@ -3645,9 +3648,9 @@ dependencies = [
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "261c025c67ba416e9fe63aa9b3236520ce3c74cfbe43590c9cdcec4ccc8180e4"
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
"checksum parity-ui-old-precompiled 1.8.0 (git+https://github.com/paritytech/js-precompiled.git?branch=v1)" = "<none>"
"checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/paritytech/js-precompiled.git?branch=v1)" = "<none>"
"checksum parity-ui-precompiled 1.9.0 (git+https://github.com/paritytech/js-precompiled.git)" = "<none>"
"checksum parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "95f6243c2d6fadf903b5edfd0011817efc20522ce5f360abf4648c24ea87581a"
"checksum parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8431a184ad88cfbcd71a792aaca319cc7203a94300c26b8dce2d0df0681ea87d"
"checksum parity-wordlist 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81451bfab101d186f8fc4a0aa13cb5539b31b02c4ed96425a0842e2a413daba6"
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"

View File

@ -31,7 +31,7 @@ futures-cpupool = "0.1"
fdlimit = "0.1"
ws2_32-sys = "0.2"
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.8" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.9" }
ethsync = { path = "sync" }
ethcore = { path = "ethcore" }
ethcore-util = { path = "util" }

View File

@ -25,8 +25,8 @@ unicase = "1.4"
zip = { version = "0.1", default-features = false }
itertools = "0.5"
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.8" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.8" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.9" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.9" }
ethcore-util = { path = "../util" }
ethcore-bigint = { path = "../util/bigint" }

View File

@ -18,7 +18,7 @@
use std::collections::BTreeMap;
use jsonrpc_core::BoxFuture;
use futures::Future;
use hyper;
#[derive(Debug, PartialEq, Default, Clone)]
@ -47,7 +47,7 @@ pub struct EndpointInfo {
}
pub type Endpoints = BTreeMap<String, Box<Endpoint>>;
pub type Response = BoxFuture<hyper::Response, hyper::Error>;
pub type Response = Box<Future<Item=hyper::Response, Error=hyper::Error> + Send>;
pub type Request = hyper::Request;
pub trait Endpoint : Send + Sync {

View File

@ -24,7 +24,6 @@ use fetch::{self, Fetch};
use futures::sync::oneshot;
use futures::{self, Future};
use hyper::{self, Method, StatusCode};
use jsonrpc_core::BoxFuture;
use parking_lot::Mutex;
use endpoint::{self, EndpointPath};
@ -212,7 +211,7 @@ impl Errors {
enum FetchState {
Error(ContentHandler),
InProgress(BoxFuture<FetchState, ()>),
InProgress(Box<Future<Item=FetchState, Error=()> + Send>),
Streaming(hyper::Response),
Done(local::Dapp, endpoint::Response),
Empty,
@ -289,7 +288,7 @@ impl ContentFetcherHandler {
path: EndpointPath,
errors: Errors,
installer: H,
) -> BoxFuture<FetchState, ()> {
) -> Box<Future<Item=FetchState, Error=()> + Send> {
// Start fetching the content
let fetch2 = fetch.clone();
let future = fetch.fetch_with_abort(url, abort.into()).then(move |result| {

View File

@ -32,7 +32,6 @@ extern crate serde_json;
extern crate unicase;
extern crate zip;
extern crate jsonrpc_core;
extern crate jsonrpc_http_server;
extern crate ethcore_util as util;
@ -52,10 +51,12 @@ extern crate log;
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate env_logger;
#[cfg(test)]
extern crate ethcore_devtools as devtools;
#[cfg(test)]
extern crate env_logger;
extern crate jsonrpc_core;
#[cfg(test)]
extern crate parity_reactor;

View File

@ -14,8 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::env;
use std::str;
use std::{env, io, str};
use std::net::SocketAddr;
use std::path::{Path, PathBuf};
use std::sync::Arc;
@ -187,7 +186,7 @@ impl<T: Fetch> ServerBuilder<T> {
/// Asynchronously start server with no authentication,
/// returns result with `Server` handle on success or an error.
pub fn start_unsecured_http(self, addr: &SocketAddr, io: IoHandler) -> Result<Server, http::Error> {
pub fn start_unsecured_http(self, addr: &SocketAddr, io: IoHandler) -> io::Result<Server> {
let fetch = self.fetch_client();
Server::start_http(
addr,
@ -234,7 +233,7 @@ impl Server {
remote: Remote,
fetch: F,
serve_ui: bool,
) -> Result<Server, http::Error> {
) -> io::Result<Server> {
let health = NodeHealth::new(
sync_status.clone(),
TimeChecker::new::<String>(&[], CpuPool::new(1)),

View File

@ -1,23 +1,26 @@
### Parity [v1.7.8](https://github.com/paritytech/parity/releases/tag/v1.7.8) (2017-10-27)
### Parity [v1.7.9](https://github.com/paritytech/parity/releases/tag/v1.7.9) (2017-11-14)
- [stable] Refactor static context check in CREATE ([#6889](https://github.com/paritytech/parity/pull/6889))
- Fix #6228: do not display eth price in cli for etc ([#6877](https://github.com/paritytech/parity/pull/6877))
- Fix mining help ([#6885](https://github.com/paritytech/parity/pull/6885))
- [stable] v1.7.8 ([#6890](https://github.com/paritytech/parity/pull/6890))
- Refactor static context check in CREATE. ([#6886](https://github.com/paritytech/parity/pull/6886))
- Cleanup some configuration options ([#6878](https://github.com/paritytech/parity/pull/6878))
- Fix serialization of non-localized transactions ([#6868](https://github.com/paritytech/parity/pull/6868))
- Updated NTP to version 0.3 ([#6854](https://github.com/paritytech/parity/pull/6854))
- Align README with 1.8 and prepare CHANGELOG with 1.8.1 ([#6833](https://github.com/paritytech/parity/pull/6833))
- Return error on timed unlock ([#6777](https://github.com/paritytech/parity/pull/6777))
- Fix dapps tests in master ([#6866](https://github.com/paritytech/parity/pull/6866))
- [Beta] Add ECIP1017 to Morden config (#6810) ([#6845](https://github.com/paritytech/parity/pull/6845))
Parity 1.7.9 removes the ability to deploy built-in multi-signature wallets.
The full list of included changes:
- Bump to v1.7.9 ([#7047](https://github.com/paritytech/parity/pull/7047))
- Disallow built-in multi-sig deploy (only watch) ([#7017](https://github.com/paritytech/parity/pull/7017))
### Parity [v1.7.8](https://github.com/paritytech/parity/releases/tag/v1.7.8) (2017-10-26)
Parity 1.7.8 fixes a critical Byzantium consensus issue. Update is highly recommended.
The full list of included changes:
- Refactor static context check in CREATE ([#6889](https://github.com/paritytech/parity/pull/6889))
- Bump to v1.7.8 ([#6890](https://github.com/paritytech/parity/pull/6890))
## Parity [v1.7.7](https://github.com/paritytech/parity/releases/tag/v1.7.7) (2017-10-15)
Parity 1.7.7 Fixes an issue with auto-update system. Updating is recommended, but not required for Byzantium.
Parity 1.7.7 fixes an issue with auto-update system. Updating is recommended, but not required for Byzantium.
Full list of included changes:
The full list of included changes:
- Fix auto-update ([#6769](https://github.com/paritytech/parity/pull/6759))
- Bump to v1.7.7
@ -28,7 +31,7 @@ Full list of included changes:
Parity 1.7.6 includes a critical consensus-relevant fix for the Byzantium hard-fork. Please upgrade your Ethereum client before block number `4_370_000`.
Full list of included changes:
The full list of included changes:
- Fixed modexp gas calculation overflow ([#6746](https://github.com/paritytech/parity/pull/6746))
- Fixed modexp gas calculation overflow ([#6741](https://github.com/paritytech/parity/pull/6741))
@ -40,7 +43,7 @@ Parity 1.7.5 includes a critical consensus-relevant fix for the Byzantium hard-f
Parity 1.7.5 is the first stable release of the 1.7 branch. With this release the support for 1.6 releases ends. Please upgrade your stable nodes to 1.7.5.
Full list of included changes:
The full list of included changes:
- Backport stable - Fixes Badges ([#6731](https://github.com/paritytech/parity/pull/6731))
- Fix badges not showing up ([#6730](https://github.com/paritytech/parity/pull/6730))
@ -67,7 +70,7 @@ Full list of included changes:
Parity 1.7.4 includes a critical consensus-relevant fix for the Byzantium hard-fork. Please upgrade your Ethereum client before block number `4_370_000`.
Full list of included changes:
The full list of included changes:
- Backport ([#6715](https://github.com/paritytech/parity/pull/6715))
- Fix estimate gas if from is not provided. ([#6714](https://github.com/paritytech/parity/pull/6714))
@ -95,7 +98,7 @@ Parity 1.7.3 enables the Byzantium fork for Ethereum main network on Block 4_370
- Revised timeout and batch size constants for bigger blocks.
- Renamed RPC receipt `statusCode` field to `status`.
Full list of included changes:
The full list of included changes:
- Backporting ([#6676](https://github.com/paritytech/parity/pull/6676))
- Fix wallet view ([#6597](https://github.com/paritytech/parity/pull/6597))
@ -143,7 +146,7 @@ Parity 1.7.2 is a bug-fix release to improve performance and stability. Among ot
- Tweaked warp-sync to quickly catch up with chains fallen back more than 10,000 blocks.
- Fixes to the Chrome extension and macOS installer upgrades.
Full list of included changes:
The full list of included changes:
- Fix output from eth_call. ([#6538](https://github.com/paritytech/parity/pull/6538))
- Ropsten fork ([#6532](https://github.com/paritytech/parity/pull/6532))
@ -294,7 +297,7 @@ Parity 1.7.0 is a major release introducing several important features:
- **PubSub API**. https://github.com/paritytech/parity/wiki/JSONRPC-Parity-Pub-Sub-module
- **Signer apps for IOS and Android**.
Full list of included changes:
The full list of included changes:
- Backports [#6163](https://github.com/paritytech/parity/pull/6163)
- Light client improvements ([#6156](https://github.com/paritytech/parity/pull/6156))

View File

@ -16,7 +16,6 @@ memorydb = { path = "../../util/memorydb" }
patricia-trie = { path = "../../util/patricia_trie" }
ethcore-network = { path = "../../util/network" }
ethcore-io = { path = "../../util/io" }
ethcore-devtools = { path = "../../devtools" }
evm = { path = "../evm" }
heapsize = "0.4"
vm = { path = "../vm" }
@ -39,5 +38,8 @@ kvdb-rocksdb = { path = "../../util/kvdb-rocksdb" }
kvdb-memorydb = { path = "../../util/kvdb-memorydb" }
memory-cache = { path = "../../util/memory_cache" }
[dev-dependencies]
tempdir = "0.3"
[features]
default = []

View File

@ -120,7 +120,6 @@ impl<T: ChainDataFetcher> IoHandler<ClientIoMessage> for ImportBlocks<T> {
#[cfg(test)]
mod tests {
use super::Service;
use devtools::RandomTempPath;
use ethcore::spec::Spec;
use std::sync::Arc;
@ -128,13 +127,14 @@ mod tests {
use client::fetch;
use time::Duration;
use parking_lot::Mutex;
use tempdir::TempDir;
#[test]
fn it_works() {
let tempdir = TempDir::new("").unwrap();
let spec = Spec::new_test();
let temp_path = RandomTempPath::new();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
Service::start(Default::default(), &spec, fetch::unavailable(), temp_path.as_path(), cache).unwrap();
Service::start(Default::default(), &spec, fetch::unavailable(), tempdir.path(), cache).unwrap();
}
}

View File

@ -84,4 +84,4 @@ extern crate kvdb_rocksdb;
extern crate memory_cache;
#[cfg(test)]
extern crate ethcore_devtools as devtools;
extern crate tempdir;

View File

@ -17,10 +17,8 @@
//! Defines error types and levels of punishment to use upon
//! encountering.
use rlp::DecoderError;
use network::NetworkError;
use std::fmt;
use {rlp, network};
/// Levels of punishment.
///
@ -41,9 +39,9 @@ pub enum Punishment {
#[derive(Debug)]
pub enum Error {
/// An RLP decoding error.
Rlp(DecoderError),
Rlp(rlp::DecoderError),
/// A network error.
Network(NetworkError),
Network(network::Error),
/// Out of credits.
NoCredits,
/// Unrecognized packet code.
@ -92,14 +90,14 @@ impl Error {
}
}
impl From<DecoderError> for Error {
fn from(err: DecoderError) -> Self {
impl From<rlp::DecoderError> for Error {
fn from(err: rlp::DecoderError) -> Self {
Error::Rlp(err)
}
}
impl From<NetworkError> for Error {
fn from(err: NetworkError) -> Self {
impl From<network::Error> for Error {
fn from(err: network::Error) -> Self {
Error::Network(err)
}
}

View File

@ -264,8 +264,9 @@ mod tests {
#[test]
fn file_store() {
let path = ::devtools::RandomTempPath::new();
let store = FileStore(path.as_path().clone());
let tempdir = ::tempdir::TempDir::new("").unwrap();
let path = tempdir.path().join("file");
let store = FileStore(path);
let mut samples = store.load();
assert!(samples.is_empty());

View File

@ -23,7 +23,8 @@
]
},
"validateScoreTransition": 1000000,
"validateStepTransition": 1500000
"validateStepTransition": 1500000,
"maximumUncleCount": 2
}
}
},

@ -1 +1 @@
Subproject commit 94b7877b5826a53627b8732ea0feb45869dd04ab
Subproject commit 9a1fcbf0d4e73bea437577e807bc38c7ba243d80

View File

@ -65,6 +65,8 @@ pub struct AuthorityRoundParams {
pub immediate_transitions: bool,
/// Block reward in base units.
pub block_reward: U256,
/// Number of accepted uncles.
pub maximum_uncle_count: usize,
}
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
@ -77,6 +79,7 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
validate_step_transition: p.validate_step_transition.map_or(0, Into::into),
immediate_transitions: p.immediate_transitions.unwrap_or(false),
block_reward: p.block_reward.map_or_else(Default::default, Into::into),
maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into),
}
}
}
@ -218,6 +221,7 @@ pub struct AuthorityRound {
epoch_manager: Mutex<EpochManager>,
immediate_transitions: bool,
block_reward: U256,
maximum_uncle_count: usize,
machine: EthereumMachine,
}
@ -365,6 +369,7 @@ impl AuthorityRound {
epoch_manager: Mutex::new(EpochManager::blank()),
immediate_transitions: our_params.immediate_transitions,
block_reward: our_params.block_reward,
maximum_uncle_count: our_params.maximum_uncle_count,
machine: machine,
});
@ -436,6 +441,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
]
}
fn maximum_uncle_count(&self) -> usize { self.maximum_uncle_count }
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
let new_difficulty = U256::from(U128::max_value()) + header_step(parent).expect("Header has been verified; qed").into() - self.step.load().into();
@ -949,6 +956,7 @@ mod tests {
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count: 0,
block_reward: Default::default(),
};

View File

@ -192,7 +192,7 @@ pub trait Engine<M: Machine>: Sync + Send {
fn extra_info(&self, _header: &M::Header) -> BTreeMap<String, String> { BTreeMap::new() }
/// Maximum number of uncles a block is allowed to declare.
fn maximum_uncle_count(&self) -> usize { 2 }
fn maximum_uncle_count(&self) -> usize { 0 }
/// The number of generations back that uncles can be.
fn maximum_uncle_age(&self) -> usize { 6 }

View File

@ -95,6 +95,8 @@ impl<M: WithBalances> Engine<M> for NullEngine<M> {
self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards)
}
fn maximum_uncle_count(&self) -> usize { 2 }
fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> {
Ok(())
}

View File

@ -181,6 +181,8 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
}
}
fn maximum_uncle_count(&self) -> usize { 2 }
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
let difficulty = self.calculate_difficulty(header, parent);
header.set_difficulty(difficulty);

View File

@ -127,12 +127,14 @@ pub struct WasmCosts {
pub mul: u32,
/// Memory (load/store) operations multiplier.
pub mem: u32,
/// Memory copy operation.
/// Memory copy operation, per byte.
pub mem_copy: u32,
/// Memory move operation, per byte.
pub mem_move: u32,
/// Memory set operation, per byte.
pub mem_set: u32,
/// Static region charge, per byte.
pub static_region: u32,
/// General static query of u64 value from env-info
pub static_u64: u32,
/// General static query of U256 value from env-info
pub static_u256: u32,
/// General static query of Address value from env-info
@ -147,11 +149,9 @@ impl Default for WasmCosts {
mul: 4,
mem: 2,
mem_copy: 1,
mem_move: 1,
mem_set: 1,
static_region: 1,
// due to runtime issues, this can be slow
static_u64: 32,
static_u256: 64,
static_address: 40,
}

View File

@ -38,12 +38,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
None,
),
Static(
"_malloc",
"_ext_malloc",
&[I32],
Some(I32),
),
Static(
"_free",
"_ext_free",
&[I32],
None,
),
@ -92,6 +92,21 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
&[I32; 3],
Some(I32),
),
Static(
"_ext_memcpy",
&[I32; 3],
Some(I32),
),
Static(
"_ext_memset",
&[I32; 3],
Some(I32),
),
Static(
"_ext_memmove",
&[I32; 3],
Some(I32),
),
Static(
"_panic",
&[I32; 2],
@ -99,7 +114,7 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
),
Static(
"_blockhash",
&[I32; 3],
&[I64, I32],
Some(I32),
),
Static(
@ -130,12 +145,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
Static(
"_timestamp",
&[],
Some(I32),
Some(I64),
),
Static(
"_blocknumber",
&[],
Some(I32),
Some(I64),
),
Static(
"_difficulty",
@ -162,8 +177,8 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
Static(
"_llvm_bswap_i64",
&[I32; 2],
Some(I32)
&[I64],
Some(I64)
),
];

View File

@ -560,32 +560,67 @@ impl<'a, 'b> Runtime<'a, 'b> {
fn mem_copy(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
//
// method signature:
// fn memcpy(dest: *const u8, src: *const u8, len: u32) -> *mut u8;
//
let len = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
let src = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.mem_copy as u64 * len as u64)?;
let mem = self.memory().get(src, len as usize)?;
self.memory().set(dst, &mem)?;
self.memory().copy_nonoverlapping(src as usize, dst as usize, len as usize)?;
Ok(Some(0i32.into()))
Ok(Some(Into::into(dst as i32)))
}
fn bswap_32(x: u32) -> u32 {
x >> 24 | x >> 8 & 0xff00 | x << 8 & 0xff0000 | x << 24
fn mem_move(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
//
// method signature:
// fn memmove(dest: *const u8, src: *const u8, len: u32) -> *mut u8;
//
let len = context.value_stack.pop_as::<i32>()? as u32;
let src = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.mem_move as u64 * len as u64)?;
self.memory().copy(src as usize, dst as usize, len as usize)?;
Ok(Some(Into::into(dst as i32)))
}
fn mem_set(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
//
// method signature:
// fn memset(dest: *const u8, c: u32, len: u32) -> *mut u8;
//
let len = context.value_stack.pop_as::<i32>()? as u32;
let c = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.mem_set as u64 * len as u64)?;
self.memory().clear(dst as usize, c as u8, len as usize)?;
Ok(Some(Into::into(dst as i32)))
}
fn bitswap_i64(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let x1 = context.value_stack.pop_as::<i32>()?;
let x2 = context.value_stack.pop_as::<i32>()?;
let x = context.value_stack.pop_as::<i64>()?;
let result = x.swap_bytes();
let result = ((Runtime::bswap_32(x2 as u32) as u64) << 32
| Runtime::bswap_32(x1 as u32) as u64) as i64;
self.return_i64(result)
Ok(Some(result.into()))
}
fn user_panic(&mut self, context: InterpreterCallerContext)
@ -606,13 +641,10 @@ impl<'a, 'b> Runtime<'a, 'b> {
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
let block_hi = context.value_stack.pop_as::<i32>()? as u32;
let block_lo = context.value_stack.pop_as::<i32>()? as u32;
let block_num = context.value_stack.pop_as::<i64>()? as u64;
self.charge(|schedule| schedule.blockhash_gas as u64)?;
let block_num = (block_hi as u64) << 32 | block_lo as u64;
trace!("Requesting block hash for block #{}", block_num);
let hash = self.ext.blockhash(&U256::from(block_num));
@ -694,14 +726,14 @@ impl<'a, 'b> Runtime<'a, 'b> {
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let timestamp = self.ext.env_info().timestamp as i64;
self.return_i64(timestamp)
Ok(Some(timestamp.into()))
}
fn block_number(&mut self, _context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let block_number: u64 = self.ext.env_info().number.into();
self.return_i64(block_number as i64)
let block_number = self.ext.env_info().number as i64;
Ok(Some(block_number.into()))
}
fn difficulty(&mut self, context: InterpreterCallerContext)
@ -726,25 +758,6 @@ impl<'a, 'b> Runtime<'a, 'b> {
Ok(None)
}
fn return_i64(&mut self, val: i64) -> Result<Option<interpreter::RuntimeValue>, InterpreterError> {
self.charge(|schedule| schedule.wasm.static_u64 as u64)?;
let uval = val as u64;
let hi = (uval >> 32) as i32;
let lo = (uval << 32 >> 32) as i32;
let target = self.instance.module("contract").ok_or(UserTrap::Other)?;
target.execute_export(
"setTempRet0",
self.execution_params().add_argument(
interpreter::RuntimeValue::I32(hi).into()
),
)?;
Ok(Some(
(lo).into()
))
}
pub fn execution_params(&mut self) -> interpreter::ExecutionParams<UserTrap> {
use super::env;
@ -812,10 +825,10 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
match name {
"_malloc" => {
"_ext_malloc" => {
self.malloc(context)
},
"_free" => {
"_ext_free" => {
// Since it is arena allocator, free does nothing
// todo: update if changed
self.user_noop(context)
@ -853,6 +866,15 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
"_emscripten_memcpy_big" => {
self.mem_copy(context)
},
"_ext_memcpy" => {
self.mem_copy(context)
},
"_ext_memmove" => {
self.mem_move(context)
},
"_ext_memset" => {
self.mem_set(context)
},
"_llvm_bswap_i64" => {
self.bitswap_i64(context)
},

View File

@ -60,7 +60,7 @@ fn empty() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(99_976));
assert_eq!(gas_left, U256::from(99_982));
}
// This test checks if the contract deserializes payload header properly.
@ -89,7 +89,6 @@ fn logger() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(15_177));
let address_val: H256 = address.into();
assert_eq!(
ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"),
@ -113,6 +112,7 @@ fn logger() {
U256::from(1_000_000_000),
"Logger sets 0x04 key to the trasferred value"
);
assert_eq!(gas_left, U256::from(19_143));
}
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
@ -142,13 +142,12 @@ fn identity() {
}
};
assert_eq!(gas_left, U256::from(99_695));
assert_eq!(
Address::from_slice(&result),
sender,
"Idenity test contract does not return the sender passed"
);
assert_eq!(gas_left, U256::from(99_844));
}
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
@ -176,12 +175,12 @@ fn dispersion() {
}
};
assert_eq!(gas_left, U256::from(96_543));
assert_eq!(
result,
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
);
assert_eq!(gas_left, U256::from(99_469));
}
#[test]
@ -205,12 +204,11 @@ fn suicide_not() {
}
};
assert_eq!(gas_left, U256::from(96_822));
assert_eq!(
result,
vec![0u8]
);
assert_eq!(gas_left, U256::from(99_724));
}
#[test]
@ -241,8 +239,8 @@ fn suicide() {
}
};
assert_eq!(gas_left, U256::from(96_580));
assert!(ext.suicides.contains(&refund));
assert_eq!(gas_left, U256::from(99_663));
}
#[test]
@ -272,7 +270,7 @@ fn create() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Create,
gas: U256::from(62_324),
gas: U256::from(65_903),
sender_address: None,
receive_address: None,
value: Some(1_000_000_000.into()),
@ -280,7 +278,7 @@ fn create() {
code_address: None,
}
));
assert_eq!(gas_left, U256::from(62_289));
assert_eq!(gas_left, U256::from(65_896));
}
@ -314,7 +312,7 @@ fn call_code() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(95_585),
gas: U256::from(98_709),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
@ -322,11 +320,11 @@ fn call_code() {
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(90_665));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614);
assert_eq!(gas_left, U256::from(93_851));
}
#[test]
@ -359,7 +357,7 @@ fn call_static() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(95_585),
gas: U256::from(98_709),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
@ -367,11 +365,12 @@ fn call_static() {
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(90_665));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590);
assert_eq!(gas_left, U256::from(93_851));
}
// Realloc test
@ -393,8 +392,8 @@ fn realloc() {
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(gas_left, U256::from(96_811));
assert_eq!(result, vec![0u8; 2]);
assert_eq!(gas_left, U256::from(99_787));
}
// Tests that contract's ability to read from a storage
@ -419,8 +418,8 @@ fn storage_read() {
}
};
assert_eq!(gas_left, U256::from(96_645));
assert_eq!(Address::from(&result[12..32]), address);
assert_eq!(gas_left, U256::from(99_702));
}
// Tests keccak calculation
@ -446,9 +445,97 @@ fn keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(80_452));
assert_eq!(gas_left, U256::from(84_520));
}
// memcpy test.
#[test]
fn memcpy() {
::ethcore_logger::init_log();
let code = load_sample!("mem.wasm");
let mut test_payload = Vec::with_capacity(8192);
for i in 0..8192 {
test_payload.push((i % 255) as u8);
}
let mut data = vec![0u8];
data.extend(&test_payload);
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(data);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("mem should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, test_payload);
assert_eq!(gas_left, U256::from(75_324));
}
// memmove test.
#[test]
fn memmove() {
::ethcore_logger::init_log();
let code = load_sample!("mem.wasm");
let mut test_payload = Vec::with_capacity(8192);
for i in 0..8192 {
test_payload.push((i % 255) as u8);
}
let mut data = vec![1u8];
data.extend(&test_payload);
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(data);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("mem should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, test_payload);
assert_eq!(gas_left, U256::from(75_324));
}
// memset test
#[test]
fn memset() {
::ethcore_logger::init_log();
let code = load_sample!("mem.wasm");
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(vec![2u8, 228u8]);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("mem should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, vec![228u8; 8192]);
assert_eq!(gas_left, U256::from(75_324));
}
macro_rules! reqrep_test {
($name: expr, $input: expr) => {
@ -500,11 +587,11 @@ fn math_add() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(94_666));
assert_eq!(
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(98_576));
}
// multiplication
@ -522,11 +609,11 @@ fn math_mul() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(93_719));
assert_eq!(
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(97_726));
}
// subtraction
@ -544,11 +631,11 @@ fn math_sub() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(94_718));
assert_eq!(
U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(98_568));
}
// subtraction with overflow
@ -566,7 +653,10 @@ fn math_sub_with_overflow() {
}
);
assert_eq!(result, Err(vm::Error::Wasm("Wasm runtime error: User(Panic(\"arithmetic operation overflow\"))".into())));
match result {
Err(vm::Error::Wasm(_)) => {},
_ => panic!("Unexpected result {:?}", result),
}
}
#[test]
@ -583,11 +673,11 @@ fn math_div() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(86_996));
assert_eq!(
U256::from_dec_str("1125000").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(91_564));
}
// This test checks the ability of wasm contract to invoke
@ -675,7 +765,7 @@ fn externs() {
"Gas limit requested and returned does not match"
);
assert_eq!(gas_left, U256::from(91_857));
assert_eq!(gas_left, U256::from(97_740));
}
#[test]
@ -701,7 +791,7 @@ fn embedded_keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(80_452));
assert_eq!(gas_left, U256::from(84_520));
}
/// This test checks the correctness of log extern
@ -736,5 +826,5 @@ fn events() {
assert_eq!(&log_entry.data, b"gnihtemos");
assert_eq!(&result, b"gnihtemos");
assert_eq!(gas_left, U256::from(78039));
}
assert_eq!(gas_left, U256::from(82_721));
}

View File

@ -209,8 +209,8 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
let secret = args.arg_secret.parse().map_err(|_| ethstore::Error::InvalidSecret)?;
let password = load_password(&args.arg_password)?;
let vault_ref = open_args_vault(&store, &args)?;
let address = store.insert_account(vault_ref, secret, &password)?;
Ok(format!("0x{:?}", address))
let account_ref = store.insert_account(vault_ref, secret, &password)?;
Ok(format!("0x{:?}", account_ref.address))
} else if args.cmd_change_pwd {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let old_pwd = load_password(&args.arg_old_pwd)?;
@ -237,8 +237,8 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
let password = load_password(&args.arg_password)?;
let kp = wallet.decrypt(&password)?;
let vault_ref = open_args_vault(&store, &args)?;
let address = store.insert_account(vault_ref, kp.secret().clone(), &password)?;
Ok(format!("0x{:?}", address))
let account_ref = store.insert_account(vault_ref, kp.secret().clone(), &password)?;
Ok(format!("0x{:?}", account_ref.address))
} else if args.cmd_remove {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;

View File

@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::iter::repeat;
use std::str;
use ethkey::Secret;
use {json, Error, crypto};
@ -90,9 +89,7 @@ impl Crypto {
// preallocated (on-stack in case of `Secret`) buffer to hold cipher
// length = length(plain) as we are using CTR-approach
let plain_len = plain.len();
let mut ciphertext: SmallVec<[u8; 32]> = SmallVec::new();
ciphertext.grow(plain_len);
ciphertext.extend(repeat(0).take(plain_len));
let mut ciphertext: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; plain_len]);
// aes-128-ctr with initial vector of iv
crypto::aes::encrypt(&derived_left_bits, &iv, plain, &mut *ciphertext);
@ -143,9 +140,7 @@ impl Crypto {
return Err(Error::InvalidPassword);
}
let mut plain: SmallVec<[u8; 32]> = SmallVec::new();
plain.grow(expected_len);
plain.extend(repeat(0).take(expected_len));
let mut plain: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; expected_len]);
match self.cipher {
Cipher::Aes128Ctr(ref params) => {

View File

@ -7,11 +7,10 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ethcore = { path = "../ethcore" }
ethcore-util = { path = "../util" }
ethcore-bigint = { path = "../util/bigint" }
ethcore-bytes = { path = "../util/bytes" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.8" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.8" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.9" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.9" }
rlp = { path = "../util/rlp" }
cid = "0.2"
multihash = "0.6"

View File

@ -20,7 +20,6 @@ extern crate unicase;
extern crate rlp;
extern crate ethcore;
extern crate ethcore_util as util;
extern crate ethcore_bigint as bigint;
extern crate ethcore_bytes as bytes;
extern crate jsonrpc_core as core;

5325
js-old/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "parity.js",
"version": "1.8.18",
"name": "@parity/dapp-v1",
"version": "1.9.99",
"main": "release/index.js",
"jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>",
@ -27,42 +27,17 @@
],
"scripts": {
"install": "napa",
"analize": "npm run analize:lib && npm run analize:dll && npm run analize:app",
"analize:app": "WPANALIZE=1 webpack --config webpack/app --json > .build/analize.app.json && cat .build/analize.app.json | webpack-bundle-size-analyzer",
"analize:lib": "WPANALIZE=1 webpack --config webpack/libraries --json > .build/analize.lib.json && cat .build/analize.lib.json | webpack-bundle-size-analyzer",
"analize:dll": "WPANALIZE=1 webpack --config webpack/vendor --json > .build/analize.dll.json && cat .build/analize.dll.json | webpack-bundle-size-analyzer",
"build": "npm run build:lib && npm run build:dll && npm run build:app && npm run build:embed",
"build": "npm run build:lib && npm run build:dll && npm run build:app",
"build:app": "webpack --config webpack/app",
"build:lib": "webpack --config webpack/libraries",
"build:dll": "webpack --config webpack/vendor",
"build:markdown": "babel-node ./scripts/build-rpc-markdown.js",
"build:json": "babel-node ./scripts/build-rpc-json.js",
"build:embed": "EMBED=1 node webpack/embed",
"build:i18n": "npm run clean && npm run build && babel-node ./scripts/build-i18n.js",
"ci:build": "npm run ci:build:lib && npm run ci:build:dll && npm run ci:build:app && npm run ci:build:embed",
"ci:build:app": "NODE_ENV=production webpack --config webpack/app",
"ci:build:lib": "NODE_ENV=production webpack --config webpack/libraries",
"ci:build:dll": "NODE_ENV=production webpack --config webpack/vendor",
"ci:build:npm": "NODE_ENV=production webpack --config webpack/npm",
"ci:build:jsonrpc": "babel-node ./scripts/build-rpc-json.js --output .npmjs/jsonrpc",
"ci:build:embed": "NODE_ENV=production EMBED=1 node webpack/embed",
"start": "npm run clean && npm install && npm run build:lib && npm run build:dll && npm run start:app",
"start:app": "node webpack/dev.server",
"clean": "rm -rf ./.build ./.coverage ./.happypack ./.npmjs ./build ./node_modules/.cache ./node_modules/@parity",
"coveralls": "npm run testCoverage && coveralls < coverage/lcov.info",
"ci:build": "cross-env NODE_ENV=production npm run build",
"clean": "rimraf ./.build ./.coverage ./.happypack ./.npmjs ./build ./node_modules/.cache",
"lint": "npm run lint:css && npm run lint:js",
"lint:cached": "npm run lint:css && npm run lint:js:cached",
"lint:css": "stylelint ./src/**/*.css",
"lint:fix": "npm run lint:js:fix",
"lint:i18n": "babel-node ./scripts/lint-i18n.js",
"lint:js": "eslint --ignore-path .gitignore ./src/",
"lint:js:cached": "eslint --cache --ignore-path .gitignore ./src/",
"lint:js:fix": "eslint --fix --ignore-path .gitignore ./src/",
"test": "NODE_ENV=test mocha --compilers ejs:ejsify 'src/**/*.spec.js'",
"test:coverage": "NODE_ENV=test istanbul cover _mocha -- --compilers ejs:ejsify 'src/**/*.spec.js'",
"test:e2e": "NODE_ENV=test mocha 'src/**/*.e2e.js'",
"test:npm": "(cd .npmjs && npm i) && node test/npmParity && node test/npmJsonRpc && (rm -rf .npmjs/node_modules)",
"prepush": "npm run lint:cached"
"watch": "webpack --watch --config webpack/app"
},
"napa": {
"qrcode-generator": "kazuhikoarase/qrcode-generator"
@ -98,6 +73,7 @@
"copy-webpack-plugin": "4.0.1",
"core-js": "2.4.1",
"coveralls": "2.11.16",
"cross-env": "5.1.1",
"css-loader": "0.26.1",
"ejs-loader": "0.3.0",
"ejsify": "1.0.0",
@ -118,9 +94,7 @@
"html-loader": "0.4.4",
"html-webpack-plugin": "2.28.0",
"http-proxy-middleware": "0.17.3",
"husky": "0.13.1",
"ignore-styles": "5.0.1",
"image-webpack-loader": "3.2.0",
"istanbul": "1.0.0-alpha.2",
"jsdom": "9.11.0",
"json-loader": "0.5.4",
@ -140,6 +114,7 @@
"react-addons-test-utils": "15.4.2",
"react-hot-loader": "3.0.0-beta.6",
"react-intl-aggregate-webpack-plugin": "0.0.1",
"rimraf": "2.6.2",
"rucksack-css": "0.9.1",
"script-ext-html-webpack-plugin": "1.7.1",
"serviceworker-webpack-plugin": "0.2.0",
@ -160,9 +135,8 @@
"yargs": "6.6.0"
},
"dependencies": {
"@parity/wordlist": "1.0.1",
"arraybuffer-loader": "0.2.2",
"babel-runtime": "6.23.0",
"@parity/api": "2.1.x",
"@parity/wordlist": "1.1.x",
"base32.js": "0.1.0",
"bignumber.js": "3.0.1",
"blockies": "0.0.2",
@ -234,7 +208,6 @@
"web3": "0.17.0-beta",
"whatwg-fetch": "2.0.1",
"worker-loader": "^0.8.0",
"yarn": "^0.21.3",
"zxcvbn": "4.4.1"
}
}

View File

@ -0,0 +1,53 @@
#!/bin/bash
set -e
# variables
UTCDATE=`date -u "+%Y%m%d-%H%M%S"`
PRECOMPILED_BRANCH="v1"
GIT_JS_PRECOMPILED="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/js-precompiled.git"
BASEDIR=`dirname $0`
GITLOG=./.git/.git-release.log
# setup the git user defaults for the current repo
function setup_git_user {
git config push.default simple
git config merge.ours.driver true
git config user.email "$GITHUB_EMAIL"
git config user.name "GitLab Build Bot"
}
# change into the build directory
pushd $BASEDIR
cd ../.dist
# add local files and send it up
echo "*** [v1 precompiled] Setting up GitHub config for js-precompiled"
rm -rf ./.git
git init
setup_git_user
echo "*** [v1 precompiled] Checking out $PRECOMPILED_BRANCH branch"
git remote add origin $GIT_JS_PRECOMPILED
git fetch origin 2>$GITLOG
git checkout -b $PRECOMPILED_BRANCH
echo "*** [v1 precompiled] Committing compiled files for $UTCDATE"
mv build ../build.new
git add .
git commit -m "$UTCDATE [update]"
git merge origin/$PRECOMPILED_BRANCH -X ours --commit -m "$UTCDATE [merge]"
git rm -r build
rm -rf build
git commit -m "$UTCDATE [cleanup]"
mv ../build.new build
git add .
git commit -m "$UTCDATE [release]"
echo "*** [v1 precompiled] Merging remote"
git push origin HEAD:refs/heads/$PRECOMPILED_BRANCH 2>$GITLOG
# move to root
popd
# exit with exit code
exit 0

View File

@ -1,79 +0,0 @@
#!/bin/bash
set -e
# variables
UTCDATE=`date -u "+%Y%m%d-%H%M%S"`
PACKAGES=( "parity" "etherscan" "shapeshift" "jsonrpc" )
BRANCH="v1"
GIT_JS_PRECOMPILED="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/js-precompiled.git"
GIT_PARITY="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/parity.git"
# setup the git user defaults for the current repo
function setup_git_user {
git config push.default simple
git config merge.ours.driver true
git config user.email "$GITHUB_EMAIL"
git config user.name "GitLab Build Bot"
}
# change into the build directory
BASEDIR=`dirname $0`
GITLOG=./.git/gitcommand.log
pushd $BASEDIR
cd ../.dist
# add local files and send it up
echo "*** Setting up GitHub config for js-precompiled"
rm -rf ./.git
git init
setup_git_user
echo "*** Checking out $BRANCH branch"
git remote add origin $GIT_JS_PRECOMPILED
git fetch origin 2>$GITLOG
git checkout -b $BRANCH
echo "*** Committing compiled files for $UTCDATE"
mv build ../build.new
git add .
git commit -m "$UTCDATE [update]"
git merge origin/$BRANCH -X ours --commit -m "$UTCDATE [merge]"
git rm -r build
rm -rf build
git commit -m "$UTCDATE [cleanup]"
mv ../build.new build
git add .
git commit -m "$UTCDATE [release]"
echo "*** Merging remote"
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
PRECOMPILED_HASH=`git rev-parse HEAD`
# move to root
cd ../..
echo "*** Setting up GitHub config for parity"
setup_git_user
git remote set-url origin $GIT_PARITY
git reset --hard origin/$BRANCH 2>$GITLOG
echo "*** Updating cargo parity-ui-old-precompiled#$PRECOMPILED_HASH"
git submodule update
# Not needed since $BRANCH is hardcoded
# sed -i "/^parity-ui-old-precompiled/ { s/branch = \".*\"/branch = \"$BRANCH\"/g; }" dapps/ui/Cargo.toml
cargo update -p parity-ui-old-precompiled
# --precise "$PRECOMPILED_HASH"
echo "*** Committing updated files"
git add js
git add dapps/ui/Cargo.toml
git add Cargo.lock
git commit -m "[ci skip] js-precompiled $UTCDATE"
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
# back to root
echo "*** Release completed"
popd
# exit with exit code
exit 0

View File

@ -1 +1 @@
// test script 10
// test script 14

View File

@ -33,6 +33,7 @@
<div id="container">
<div class="loading">Loading</div>
</div>
<script src="/parity-utils/inject.js"></script>
<script src="vendor.js"></script>
</body>
</html>

View File

@ -25,9 +25,9 @@ import { AppContainer } from 'react-hot-loader';
import injectTapEventPlugin from 'react-tap-event-plugin';
import { hashHistory } from 'react-router';
import qs from 'querystring';
import SecureApi from './secureApi';
import Api from '@parity/api';
import ContractInstances from '~/contracts';
import { initStore } from './redux';
@ -45,23 +45,7 @@ import '../assets/fonts/RobotoMono/font.css';
injectTapEventPlugin();
if (process.env.NODE_ENV === 'development') {
// Expose the React Performance Tools on the`window` object
const Perf = require('react-addons-perf');
window.Perf = Perf;
}
const AUTH_HASH = '#/auth?';
let token = null;
if (window.location.hash && window.location.hash.indexOf(AUTH_HASH) === 0) {
token = qs.parse(window.location.hash.substr(AUTH_HASH.length)).token;
}
const uiUrl = window.location.host;
const api = new SecureApi(uiUrl, token);
const api = new Api(window.ethereum);
patchApi(api);
loadSender(api);
@ -72,8 +56,6 @@ const store = initStore(api, hashHistory);
store.dispatch({ type: 'initAll', api });
store.dispatch(setApi(api));
window.secureApi = api;
ReactDOM.render(
<AppContainer>
<ContextProvider api={ api } muiTheme={ muiTheme } store={ store }>

View File

@ -40,10 +40,10 @@ impl WebApp for App {
fn info(&self) -> Info {
Info {
name: "Parity Wallet v1",
name: "Parity Wallet",
version: env!("CARGO_PKG_VERSION"),
author: "Parity <admin@parity.io>",
description: "Deprecated version of Parity Wallet.",
description: "Parity Wallet and Account management tools",
icon_url: "icon.png",
}
}

7
js-old/src/manifest.json Normal file
View File

@ -0,0 +1,7 @@
{
"name": "Parity Wallet",
"version": "development",
"author": "Parity <admin@parity.io>",
"description": "Parity Wallet and Account management tools",
"icon_url": "icon.png",
}

View File

@ -17,35 +17,35 @@
import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { walletSourceURL } from '~/contracts/code/wallet';
// import { walletSourceURL } from '~/contracts/code/wallet';
import { RadioButtons } from '~/ui';
const TYPES = [
{
label: (
<FormattedMessage
id='createWallet.type.multisig.label'
defaultMessage='Multi-Sig wallet'
/>
),
key: 'MULTISIG',
description: (
<FormattedMessage
id='createWallet.type.multisig.description'
defaultMessage='Create/Deploy a {link} Wallet'
values={ {
link: (
<a href={ walletSourceURL } target='_blank'>
<FormattedMessage
id='createWallet.type.multisig.link'
defaultMessage='standard multi-signature'
/>
</a>
)
} }
/>
)
},
// {
// label: (
// <FormattedMessage
// id='createWallet.type.multisig.label'
// defaultMessage='Multi-Sig wallet'
// />
// ),
// key: 'MULTISIG',
// description: (
// <FormattedMessage
// id='createWallet.type.multisig.description'
// defaultMessage='Create/Deploy a {link} Wallet'
// values={ {
// link: (
// <a href={ walletSourceURL } target='_blank'>
// <FormattedMessage
// id='createWallet.type.multisig.link'
// defaultMessage='standard multi-signature'
// />
// </a>
// )
// } }
// />
// )
// },
{
label: (
<FormattedMessage
@ -57,7 +57,7 @@ const TYPES = [
description: (
<FormattedMessage
id='createWallet.type.watch.description'
defaultMessage='Add an existing wallet to your accounts'
defaultMessage='Add an existing multisig wallet to your accounts'
/>
)
}

View File

@ -59,7 +59,7 @@ const STEPS = {
export default class CreateWalletStore {
@observable step = null;
@observable txhash = null;
@observable walletType = 'MULTISIG';
@observable walletType = 'WATCH'; // 'MULTISIG';
@observable wallet = {
account: '',

View File

@ -133,8 +133,8 @@ export default class TransferStore {
}
@action handleClose = () => {
this.stage = 0;
this.onClose();
this.stage = 0;
}
@action onUpdateDetails = (type, value) => {
@ -169,7 +169,6 @@ export default class TransferStore {
}
@action onSend = () => {
this.onNext();
this.sending = true;
this

View File

@ -16,7 +16,7 @@
import { handleActions } from 'redux-actions';
const initialState = {};
const initialState = null;
export default handleActions({
setApi (state, action) {

View File

@ -16,12 +16,11 @@
import { throttle } from 'lodash';
import { fetchBalances, fetchTokensBalances, queryTokensFilter } from './balancesActions';
import { loadTokens, fetchTokens } from './tokensActions';
import { padRight } from '~/api/util/format';
import { LOG_KEYS, getLogger } from '~/config';
import Contracts from '~/contracts';
import { fetchBalances, queryTokensFilter, updateTokensFilter } from './balancesActions';
const log = getLogger(LOG_KEYS.Balances);
let instance = null;
export default class Balances {
@ -29,40 +28,20 @@ export default class Balances {
this._api = api;
this._store = store;
this._tokenreg = null;
this._tokenregSID = null;
this._tokenMetaSID = null;
this._apiSubs = [];
this._blockNumberSID = null;
this._accountsInfoSID = null;
// Throtthled load tokens (no more than once
// every minute)
this.loadTokens = throttle(
this._loadTokens,
60 * 1000,
{ leading: true, trailing: true }
);
// Throttled `_fetchBalances` function
// Throttled `_fetchEthBalances` function
// that gets called max once every 40s
this.longThrottledFetch = throttle(
this._fetchBalances,
this._fetchEthBalances,
40 * 1000,
{ leading: false, trailing: true }
{ leading: true, trailing: false }
);
this.shortThrottledFetch = throttle(
this._fetchBalances,
this._fetchEthBalances,
2 * 1000,
{ leading: false, trailing: true }
);
// Fetch all tokens every 2 minutes
this.throttledTokensFetch = throttle(
this._fetchTokens,
2 * 60 * 1000,
{ leading: false, trailing: true }
{ leading: true, trailing: false }
);
// Unsubscribe previous instance if it exists
@ -71,17 +50,19 @@ export default class Balances {
}
}
static get (store = {}) {
static get (store) {
if (!instance && store) {
const { api } = store.getState();
return Balances.instantiate(store, api);
return Balances.init(store);
} else if (!instance) {
throw new Error('The Balances Provider has not been initialized yet');
}
return instance;
}
static instantiate (store, api) {
static init (store) {
const { api } = store.getState();
if (!instance) {
instance = new Balances(store, api);
}
@ -91,15 +72,13 @@ export default class Balances {
static start () {
if (!instance) {
return Promise.reject('BalancesProvider has not been intiated yet');
return Promise.reject('BalancesProvider has not been initiated yet');
}
const self = instance;
// Unsubscribe from previous subscriptions
return Balances
.stop()
.then(() => self.loadTokens())
return Balances.stop()
.then(() => {
const promises = [
self.subscribeBlockNumber(),
@ -107,7 +86,8 @@ export default class Balances {
];
return Promise.all(promises);
});
})
.then(() => self.fetchEthBalances());
}
static stop () {
@ -116,71 +96,35 @@ export default class Balances {
}
const self = instance;
const promises = [];
const promises = self._apiSubs.map((subId) => self._api.unsubscribe(subId));
if (self._blockNumberSID) {
const p = self._api
.unsubscribe(self._blockNumberSID)
.then(() => {
self._blockNumberSID = null;
});
promises.push(p);
}
if (self._accountsInfoSID) {
const p = self._api
.unsubscribe(self._accountsInfoSID)
.then(() => {
self._accountsInfoSID = null;
});
promises.push(p);
}
// Unsubscribe without adding the promises
// to the result, since it would have to wait for a
// reconnection to resolve if the Node is disconnected
if (self._tokenreg) {
if (self._tokenregSID) {
const tokenregSID = self._tokenregSID;
self._tokenreg
.unsubscribe(tokenregSID)
.then(() => {
if (self._tokenregSID === tokenregSID) {
self._tokenregSID = null;
}
});
}
if (self._tokenMetaSID) {
const tokenMetaSID = self._tokenMetaSID;
self._tokenreg
.unsubscribe(tokenMetaSID)
.then(() => {
if (self._tokenMetaSID === tokenMetaSID) {
self._tokenMetaSID = null;
}
});
}
}
return Promise.all(promises);
return Promise.all(promises)
.then(() => {
self._apiSubs = [];
});
}
subscribeAccountsInfo () {
// Don't trigger the balances updates on first call (when the
// subscriptions are setup)
let firstcall = true;
return this._api
.subscribe('parity_allAccountsInfo', (error, accountsInfo) => {
if (error) {
return console.warn('balances::subscribeAccountsInfo', error);
}
if (firstcall) {
firstcall = false;
return;
}
this.fetchAllBalances();
this._store.dispatch(updateTokensFilter());
this.fetchEthBalances();
})
.then((accountsInfoSID) => {
this._accountsInfoSID = accountsInfoSID;
.then((subId) => {
this._apiSubs.push(subId);
})
.catch((error) => {
console.warn('_subscribeAccountsInfo', error);
@ -188,161 +132,57 @@ export default class Balances {
}
subscribeBlockNumber () {
// Don't trigger the balances updates on first call (when the
// subscriptions are setup)
let firstcall = true;
return this._api
.subscribe('eth_blockNumber', (error) => {
.subscribe('eth_blockNumber', (error, block) => {
if (error) {
return console.warn('_subscribeBlockNumber', error);
return console.warn('balances::subscribeBlockNumber', error);
}
if (firstcall) {
firstcall = false;
return;
}
this._store.dispatch(queryTokensFilter());
return this.fetchAllBalances();
return this.fetchEthBalances();
})
.then((blockNumberSID) => {
this._blockNumberSID = blockNumberSID;
.then((subId) => {
this._apiSubs.push(subId);
})
.catch((error) => {
console.warn('_subscribeBlockNumber', error);
});
}
fetchAllBalances (options = {}) {
// If it's a network change, reload the tokens
// ( and then fetch the tokens balances ) and fetch
// the accounts balances
if (options.changedNetwork) {
this.loadTokens({ skipNotifications: true });
this.loadTokens.flush();
fetchEthBalances (options = {}) {
log.debug('fetching eth balances (throttled)...');
this.fetchBalances({
force: true,
skipNotifications: true
});
return;
}
this.fetchTokensBalances(options);
this.fetchBalances(options);
}
fetchTokensBalances (options) {
const { skipNotifications = false, force = false } = options;
this.throttledTokensFetch(skipNotifications);
if (force) {
this.throttledTokensFetch.flush();
}
}
fetchBalances (options) {
const { skipNotifications = false, force = false } = options;
const { syncing } = this._store.getState().nodeStatus;
if (options.force) {
return this._fetchEthBalances();
}
// If syncing, only retrieve balances once every
// few seconds
if (syncing || syncing === null) {
this.shortThrottledFetch.cancel();
this.longThrottledFetch(skipNotifications);
if (force) {
this.longThrottledFetch.flush();
}
return;
return this.longThrottledFetch();
}
this.longThrottledFetch.cancel();
this.shortThrottledFetch(skipNotifications);
if (force) {
this.shortThrottledFetch.flush();
}
return this.shortThrottledFetch();
}
_fetchBalances (skipNotifications = false) {
this._store.dispatch(fetchBalances(null, skipNotifications));
}
_fetchEthBalances (skipNotifications = false) {
log.debug('fetching eth balances (real)...');
_fetchTokens (skipNotifications = false) {
this._store.dispatch(fetchTokensBalances(null, null, skipNotifications));
}
const { dispatch, getState } = this._store;
getTokenRegistry () {
return Contracts.get().tokenReg.getContract();
}
_loadTokens (options = {}) {
return this
.getTokenRegistry()
.then((tokenreg) => {
this._tokenreg = tokenreg;
this._store.dispatch(loadTokens(options));
return this.attachToTokens(tokenreg);
})
.catch((error) => {
console.warn('balances::loadTokens', error);
});
}
attachToTokens (tokenreg) {
return Promise
.all([
this.attachToTokenMetaChange(tokenreg),
this.attachToNewToken(tokenreg)
]);
}
attachToNewToken (tokenreg) {
if (this._tokenregSID) {
return Promise.resolve();
}
return tokenreg.instance.Registered
.subscribe({
fromBlock: 0,
toBlock: 'latest',
skipInitFetch: true
}, (error, logs) => {
if (error) {
return console.error('balances::attachToNewToken', 'failed to attach to tokenreg Registered', error.toString(), error.stack);
}
this.handleTokensLogs(logs);
})
.then((tokenregSID) => {
this._tokenregSID = tokenregSID;
});
}
attachToTokenMetaChange (tokenreg) {
if (this._tokenMetaSID) {
return Promise.resolve();
}
return tokenreg.instance.MetaChanged
.subscribe({
fromBlock: 0,
toBlock: 'latest',
topics: [ null, padRight(this._api.util.asciiToHex('IMG'), 32) ],
skipInitFetch: true
}, (error, logs) => {
if (error) {
return console.error('balances::attachToTokenMetaChange', 'failed to attach to tokenreg MetaChanged', error.toString(), error.stack);
}
this.handleTokensLogs(logs);
})
.then((tokenMetaSID) => {
this._tokenMetaSID = tokenMetaSID;
});
}
handleTokensLogs (logs) {
const tokenIds = logs.map((log) => log.params.id.value.toNumber());
this._store.dispatch(fetchTokens(tokenIds));
return fetchBalances(null, skipNotifications)(dispatch, getState);
}
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { uniq, isEqual } from 'lodash';
import { difference, uniq } from 'lodash';
import { push } from 'react-router-redux';
import { notifyTransaction } from '~/util/notifications';
@ -22,11 +22,16 @@ import { ETH_TOKEN, fetchAccountsBalances } from '~/util/tokens';
import { LOG_KEYS, getLogger } from '~/config';
import { sha3 } from '~/api/util/sha3';
import { fetchTokens } from './tokensActions';
const TRANSFER_SIGNATURE = sha3('Transfer(address,address,uint256)');
const log = getLogger(LOG_KEYS.Balances);
let tokensFilter = {};
let tokensFilter = {
tokenAddresses: [],
addresses: []
};
function _setBalances (balances) {
return {
@ -63,13 +68,10 @@ function setBalances (updates, skipNotifications = false) {
dispatch(notifyBalanceChange(who, prevTokenValue, nextTokenValue, token));
}
// Add the token if it's native ETH or if it has a value
if (token.native || nextTokenValue.gt(0)) {
nextBalances[who] = {
...(nextBalances[who] || {}),
[tokenId]: nextTokenValue
};
}
nextBalances[who] = {
...(nextBalances[who] || {}),
[tokenId]: nextTokenValue
};
});
});
@ -100,41 +102,92 @@ function notifyBalanceChange (who, fromValue, toValue, token) {
}
// TODO: fetch txCount when needed
export function fetchBalances (_addresses, skipNotifications = false) {
return fetchTokensBalances(_addresses, [ ETH_TOKEN ], skipNotifications);
export function fetchBalances (addresses, skipNotifications = false) {
return (dispatch, getState) => {
const { personal } = getState();
const { visibleAccounts, accounts } = personal;
const addressesToFetch = addresses || uniq(visibleAccounts.concat(Object.keys(accounts)));
const updates = addressesToFetch.reduce((updates, who) => {
updates[who] = [ ETH_TOKEN.id ];
return updates;
}, {});
return fetchTokensBalances(updates, skipNotifications)(dispatch, getState);
};
}
export function updateTokensFilter (_addresses, _tokens, options = {}) {
export function updateTokensFilter (options = {}) {
return (dispatch, getState) => {
const { api, personal, tokens } = getState();
const { visibleAccounts, accounts } = personal;
const addressesToFetch = uniq(visibleAccounts.concat(Object.keys(accounts)));
const addresses = uniq(_addresses || addressesToFetch || []).sort();
const addresses = uniq(visibleAccounts.concat(Object.keys(accounts)));
const tokensToUpdate = Object.values(tokens);
const tokensAddressMap = Object.values(tokens).reduce((map, token) => {
map[token.address] = token;
return map;
}, {});
const tokensToUpdate = _tokens || Object.values(tokens);
const tokenAddresses = tokensToUpdate
.map((t) => t.address)
.filter((address) => address)
.sort();
.filter((address) => address && !/^(0x)?0*$/.test(address));
// Token Addresses that are not in the current filter
const newTokenAddresses = difference(tokenAddresses, tokensFilter.tokenAddresses);
// Addresses that are not in the current filter (omit those
// that the filter includes)
const newAddresses = difference(addresses, tokensFilter.addresses);
if (tokensFilter.filterFromId || tokensFilter.filterToId) {
// Has the tokens addresses changed (eg. a network change)
const sameTokens = isEqual(tokenAddresses, tokensFilter.tokenAddresses);
// Addresses that are not in the current filter (omit those
// that the filter includes)
const newAddresses = addresses.filter((address) => !tokensFilter.addresses.includes(address));
// If no new addresses and the same tokens, don't change the filter
if (sameTokens && newAddresses.length === 0) {
if (newTokenAddresses.length === 0 && newAddresses.length === 0) {
log.debug('no need to update token filter', addresses, tokenAddresses, tokensFilter);
return queryTokensFilter(tokensFilter)(dispatch, getState);
return;
}
}
log.debug('updating the token filter', addresses, tokenAddresses);
const promises = [];
const updates = {};
const allTokenIds = tokensToUpdate.map((token) => token.id);
const newTokenIds = newTokenAddresses.map((address) => tokensAddressMap[address].id);
newAddresses.forEach((newAddress) => {
updates[newAddress] = allTokenIds;
});
difference(addresses, newAddresses).forEach((oldAddress) => {
updates[oldAddress] = newTokenIds;
});
log.debug('updating the token filter', addresses, tokenAddresses);
const topicsFrom = [ TRANSFER_SIGNATURE, addresses, null ];
const topicsTo = [ TRANSFER_SIGNATURE, null, addresses ];
const filterOptions = {
fromBlock: 'latest',
toBlock: 'latest',
address: tokenAddresses
};
const optionsFrom = {
...filterOptions,
topics: topicsFrom
};
const optionsTo = {
...filterOptions,
topics: topicsTo
};
promises.push(
api.eth.newFilter(optionsFrom),
api.eth.newFilter(optionsTo)
);
if (tokensFilter.filterFromId) {
promises.push(api.eth.uninstallFilter(tokensFilter.filterFromId));
@ -144,48 +197,16 @@ export function updateTokensFilter (_addresses, _tokens, options = {}) {
promises.push(api.eth.uninstallFilter(tokensFilter.filterToId));
}
Promise
.all([
api.eth.blockNumber()
].concat(promises))
.then(([ block ]) => {
const topicsFrom = [ TRANSFER_SIGNATURE, addresses, null ];
const topicsTo = [ TRANSFER_SIGNATURE, null, addresses ];
const filterOptions = {
fromBlock: block,
toBlock: 'pending',
address: tokenAddresses
};
const optionsFrom = {
...filterOptions,
topics: topicsFrom
};
const optionsTo = {
...filterOptions,
topics: topicsTo
};
const newFilters = Promise.all([
api.eth.newFilter(optionsFrom),
api.eth.newFilter(optionsTo)
]);
return newFilters;
})
return Promise.all(promises)
.then(([ filterFromId, filterToId ]) => {
const nextTokensFilter = {
filterFromId, filterToId,
addresses, tokenAddresses
};
const { skipNotifications } = options;
tokensFilter = nextTokensFilter;
fetchTokensBalances(addresses, tokensToUpdate, skipNotifications)(dispatch, getState);
})
.then(() => fetchTokensBalances(updates)(dispatch, getState))
.catch((error) => {
console.warn('balances::updateTokensFilter', error);
});
@ -194,12 +215,7 @@ export function updateTokensFilter (_addresses, _tokens, options = {}) {
export function queryTokensFilter () {
return (dispatch, getState) => {
const { api, personal, tokens } = getState();
const { visibleAccounts, accounts } = personal;
const allAddresses = visibleAccounts.concat(Object.keys(accounts));
const addressesToFetch = uniq(allAddresses);
const lcAddresses = addressesToFetch.map((a) => a.toLowerCase());
const { api } = getState();
Promise
.all([
@ -207,67 +223,107 @@ export function queryTokensFilter () {
api.eth.getFilterChanges(tokensFilter.filterToId)
])
.then(([ logsFrom, logsTo ]) => {
const addresses = [];
const tokenAddresses = [];
const logs = logsFrom.concat(logsTo);
const logs = [].concat(logsFrom, logsTo);
if (logs.length > 0) {
if (logs.length === 0) {
return;
} else {
log.debug('got tokens filter logs', logs);
}
const { personal, tokens } = getState();
const { visibleAccounts, accounts } = personal;
const addressesToFetch = uniq(visibleAccounts.concat(Object.keys(accounts)));
const lcAddresses = addressesToFetch.map((a) => a.toLowerCase());
const lcTokensMap = Object.values(tokens).reduce((map, token) => {
map[token.address.toLowerCase()] = token;
return map;
});
// The keys are the account addresses,
// and the value is an Array of the tokens addresses
// to update
const updates = {};
logs
.forEach((log) => {
const tokenAddress = log.address;
.forEach((log, index) => {
const tokenAddress = log.address.toLowerCase();
const token = lcTokensMap[tokenAddress];
const fromAddress = '0x' + log.topics[1].slice(-40);
const toAddress = '0x' + log.topics[2].slice(-40);
// logs = [ ...logsFrom, ...logsTo ]
const topicIdx = index < logsFrom.length ? 1 : 2;
const address = ('0x' + log.topics[topicIdx].slice(-40)).toLowerCase();
const addressIndex = lcAddresses.indexOf(address);
const fromAddressIndex = lcAddresses.indexOf(fromAddress);
const toAddressIndex = lcAddresses.indexOf(toAddress);
if (addressIndex > -1) {
const who = addressesToFetch[addressIndex];
if (fromAddressIndex > -1) {
addresses.push(addressesToFetch[fromAddressIndex]);
updates[who] = [].concat(updates[who] || [], token.id);
}
if (toAddressIndex > -1) {
addresses.push(addressesToFetch[toAddressIndex]);
}
tokenAddresses.push(tokenAddress);
});
if (addresses.length === 0) {
// No accounts to update
if (Object.keys(updates).length === 0) {
return;
}
const tokensToUpdate = Object.values(tokens)
.filter((t) => tokenAddresses.includes(t.address));
Object.keys(updates).forEach((who) => {
// Keep non-empty token addresses
updates[who] = uniq(updates[who]);
});
fetchTokensBalances(uniq(addresses), tokensToUpdate)(dispatch, getState);
fetchTokensBalances(updates)(dispatch, getState);
});
};
}
export function fetchTokensBalances (_addresses = null, _tokens = null, skipNotifications = false) {
export function fetchTokensBalances (updates, skipNotifications = false) {
return (dispatch, getState) => {
const { api, personal, tokens } = getState();
const { visibleAccounts, accounts } = personal;
const allTokens = Object.values(tokens);
const addressesToFetch = uniq(visibleAccounts.concat(Object.keys(accounts)));
const addresses = _addresses || addressesToFetch;
const tokensToUpdate = _tokens || allTokens;
if (!updates) {
const { visibleAccounts, accounts } = personal;
const addressesToFetch = uniq(visibleAccounts.concat(Object.keys(accounts)));
if (addresses.length === 0) {
return Promise.resolve();
updates = addressesToFetch.reduce((updates, who) => {
updates[who] = allTokens.map((token) => token.id);
return updates;
}, {});
}
const updates = addresses.reduce((updates, who) => {
updates[who] = tokensToUpdate.map((token) => token.id);
return updates;
}, {});
let start = Date.now();
return fetchAccountsBalances(api, allTokens, updates)
.then((balances) => {
log.debug('got tokens balances', balances, updates, `(took ${Date.now() - start}ms)`);
// Tokens info might not be fetched yet (to not load
// tokens we don't care about)
const tokenIdsToFetch = Object.values(balances)
.reduce((tokenIds, balance) => {
const nextTokenIds = Object.keys(balance)
.filter((tokenId) => balance[tokenId].gt(0));
return tokenIds.concat(nextTokenIds);
}, []);
const tokenIndexesToFetch = uniq(tokenIdsToFetch)
.filter((tokenId) => tokens[tokenId] && tokens[tokenId].index && !tokens[tokenId].fetched)
.map((tokenId) => tokens[tokenId].index);
if (tokenIndexesToFetch.length === 0) {
return balances;
}
start = Date.now();
return fetchTokens(tokenIndexesToFetch)(dispatch, getState)
.then(() => log.debug('token indexes fetched', tokenIndexesToFetch, `(took ${Date.now() - start}ms)`))
.then(() => balances);
})
.then((balances) => {
dispatch(setBalances(balances, skipNotifications));
})

View File

@ -14,14 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export const fetchCertifiers = () => ({
type: 'fetchCertifiers'
});
export const fetchCertifications = (address) => ({
type: 'fetchCertifications', address
});
export const addCertification = (address, id, name, title, icon) => ({
type: 'addCertification', address, id, name, title, icon
});

View File

@ -0,0 +1,343 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { range } from 'lodash';
import { addCertification, removeCertification } from './actions';
import { getLogger, LOG_KEYS } from '~/config';
import Contract from '~/api/contract';
import { bytesToHex, hexToAscii } from '~/api/util/format';
import Contracts from '~/contracts';
import CertifierABI from '~/contracts/abi/certifier.json';
import { querier } from './enhanced-querier';
const log = getLogger(LOG_KEYS.CertificationsMiddleware);
let self = null;
export default class CertifiersMonitor {
constructor (api, store) {
this._api = api;
this._name = 'Certifiers';
this._store = store;
this._contract = new Contract(this.api, CertifierABI);
this._contractEvents = [ 'Confirmed', 'Revoked' ]
.map((name) => this.contract.events.find((e) => e.name === name));
this.certifiers = {};
this.fetchedAccounts = {};
this.load();
}
static get () {
if (self) {
return self;
}
self = new CertifiersMonitor();
return self;
}
static init (api, store) {
if (!self) {
self = new CertifiersMonitor(api, store);
}
}
get api () {
return this._api;
}
get contract () {
return this._contract;
}
get contractEvents () {
return this._contractEvents;
}
get name () {
return this._name;
}
get store () {
return this._store;
}
get registry () {
return this._registry;
}
get registryEvents () {
return this._registryEvents;
}
checkFilters () {
this.checkCertifiersFilter();
this.checkRegistryFilter();
}
checkCertifiersFilter () {
if (!this.certifiersFilter) {
return;
}
this.api.eth.getFilterChanges(this.certifiersFilter)
.then((logs) => {
if (logs.length === 0) {
return;
}
const parsedLogs = this.contract.parseEventLogs(logs).filter((log) => log.params);
log.debug('received certifiers logs', parsedLogs);
const promises = parsedLogs.map((log) => {
const account = log.params.who.value;
const certifier = Object.values(this.certifiers).find((c) => c.address === log.address);
if (!certifier) {
log.warn('could not find the certifier', { certifiers: this.certifiers, log });
return Promise.resolve();
}
return this.fetchAccount(account, { ids: [ certifier.id ] });
});
return Promise.all(promises);
})
.catch((error) => {
console.error(error);
});
}
checkRegistryFilter () {
if (!this.registryFilter) {
return;
}
this.api.eth.getFilterChanges(this.registryFilter)
.then((logs) => {
if (logs.length === 0) {
return;
}
const parsedLogs = this.contract.parseEventLogs(logs).filter((log) => log.params);
const indexes = parsedLogs.map((log) => log.params && log.params.id.value.toNumber());
log.debug('received registry logs', parsedLogs);
return this.fetchElements(indexes);
})
.catch((error) => {
console.error(error);
});
}
/**
* Initial load of the Monitor.
* Fetch the contract from the Registry, and
* load the elements addresses
*/
load () {
const badgeReg = Contracts.get().badgeReg;
log.debug(`loading the ${this.name} monitor...`);
return badgeReg.getContract()
.then((registryContract) => {
this._registry = registryContract;
this._registryEvents = [ 'Registered', 'Unregistered', 'MetaChanged', 'AddressChanged' ]
.map((name) => this.registry.events.find((e) => e.name === name));
return this.registry.instance.badgeCount.call({});
})
.then((count) => {
log.debug(`found ${count.toFormat()} registered contracts for ${this.name}`);
return this.fetchElements(range(count.toNumber()));
})
.then(() => {
return this.setRegistryFilter();
})
.then(() => {
// Listen for new blocks
return this.api.subscribe('eth_blockNumber', (err) => {
if (err) {
return;
}
this.checkFilters();
});
})
.then(() => {
log.debug(`loaded the ${this.name} monitor!`, this.certifiers);
})
.catch((error) => {
log.error(error);
});
}
/**
* Fetch the given registered element
*/
fetchElements (indexes) {
const badgeReg = Contracts.get().badgeReg;
const { instance } = this.registry;
const sorted = indexes.sort();
const from = sorted[0];
const last = sorted[sorted.length - 1];
const limit = last - from + 1;
// Fetch the address, name and owner in one batch
return querier(this.api, { address: instance.address, from, limit }, instance.badge)
.then((results) => {
const certifiers = results
.map(([ address, name, owner ], index) => ({
address, owner,
id: index + from,
name: hexToAscii(bytesToHex(name).replace(/(00)+$/, ''))
}))
.reduce((certifiers, certifier) => {
const { id } = certifier;
if (!/^(0x)?0+$/.test(certifier.address)) {
certifiers[id] = certifier;
} else if (certifiers[id]) {
delete certifiers[id];
}
return certifiers;
}, {});
// Fetch the meta-data in serie
return Object.values(certifiers).reduce((promise, certifier) => {
return promise.then(() => badgeReg.fetchMeta(certifier.id))
.then((meta) => {
this.certifiers[certifier.id] = { ...certifier, ...meta };
});
}, Promise.resolve());
})
.then(() => log.debug('fetched certifiers', { certifiers: this.certifiers }))
// Fetch the know accounts in case it's an update of the certifiers
.then(() => this.fetchAccounts(Object.keys(this.fetchedAccounts), { ids: indexes, force: true }));
}
fetchAccounts (addresses, { ids = null, force = false } = {}) {
const newAddresses = force
? addresses
: addresses.filter((address) => !this.fetchedAccounts[address]);
if (newAddresses.length === 0) {
return Promise.resolve();
}
log.debug(`fetching values for "${addresses.join(' ; ')}" in ${this.name}...`);
return newAddresses
.reduce((promise, address) => {
return promise.then(() => this.fetchAccount(address, { ids }));
}, Promise.resolve())
.then(() => {
log.debug(`fetched values for "${addresses.join(' ; ')}" in ${this.name}!`);
})
.then(() => this.setCertifiersFilter());
}
fetchAccount (address, { ids = null } = {}) {
let certifiers = Object.values(this.certifiers);
// Only fetch values for the givens ids, if any
if (ids) {
certifiers = certifiers.filter((certifier) => ids.includes(certifier.id));
}
certifiers
.reduce((promise, certifier) => {
return promise
.then(() => {
return this.contract.at(certifier.address).instance.certified.call({}, [ address ]);
})
.then((certified) => {
const { id, title, icon, name } = certifier;
if (!certified) {
return this.store.dispatch(removeCertification(address, id));
}
log.debug('seen as certified', { address, id, name, icon });
this.store.dispatch(addCertification(address, id, name, title, icon));
});
}, Promise.resolve())
.then(() => {
this.fetchedAccounts[address] = true;
});
}
setCertifiersFilter () {
const accounts = Object.keys(this.fetchedAccounts);
const addresses = Object.values(this.certifiers).map((c) => c.address);
// The events have as first indexed data the account address
const topics = [
this.contractEvents.map((event) => '0x' + event.signature),
accounts
];
if (accounts.length === 0 || addresses.length === 0) {
return;
}
const promise = this.certifiersFilter
? this.api.eth.uninstallFilter(this.certifiersFilter)
: Promise.resolve();
log.debug('setting up registry filter', { topics, accounts, addresses });
return promise
.then(() => this.api.eth.newFilter({
fromBlock: 'latest',
toBlock: 'latest',
address: addresses,
topics
}))
.then((filterId) => {
this.certifiersFilter = filterId;
})
.catch((error) => {
console.error(error);
});
}
setRegistryFilter () {
const { address } = this.registry.instance;
const topics = [ this.registryEvents.map((event) => '0x' + event.signature) ];
log.debug('setting up registry filter', { topics, address });
return this.api.eth
.newFilter({
fromBlock: 'latest',
toBlock: 'latest',
address, topics
})
.then((filterId) => {
this.registryFilter = filterId;
})
.catch((error) => {
console.error(error);
});
}
}

View File

@ -0,0 +1,96 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { padRight, padLeft } from '~/api/util/format';
/**
* Bytecode of this contract:
*
*
pragma solidity ^0.4.10;
contract Querier {
function Querier
(address addr, bytes32 sign, uint out_size, uint from, uint limit)
public
{
// The size is 32 bytes for each
// value, plus 32 bytes for the count
uint m_size = out_size * limit + 32;
bytes32 p_return;
uint p_in;
uint p_out;
assembly {
p_return := mload(0x40)
mstore(0x40, add(p_return, m_size))
mstore(p_return, limit)
p_in := mload(0x40)
mstore(0x40, add(p_in, 0x24))
mstore(p_in, sign)
p_out := add(p_return, 0x20)
}
for (uint i = from; i < from + limit; i++) {
assembly {
mstore(add(p_in, 0x4), i)
call(gas, addr, 0x0, p_in, 0x24, p_out, out_size)
p_out := add(p_out, out_size)
pop
}
}
assembly {
return (p_return, m_size)
}
}
}
*/
export const bytecode = '0x60606040523415600e57600080fd5b60405160a0806099833981016040528080519190602001805191906020018051919060200180519190602001805191505082810260200160008080806040519350848401604052858452604051602481016040528981529250505060208201855b858701811015609457806004840152878260248560008e5af15090870190600101606f565b8484f300';
export const querier = (api, { address, from, limit }, method) => {
const { outputs, signature } = method;
const outLength = 32 * outputs.length;
const callargs = [
padLeft(address, 32),
padRight(signature, 32),
padLeft(outLength, 32),
padLeft(from, 32),
padLeft(limit, 32)
].map((v) => v.slice(2)).join('');
const calldata = bytecode + callargs;
return api.eth.call({ data: calldata })
.then((result) => {
const data = result.slice(2);
const results = [];
for (let i = 0; i < limit; i++) {
const datum = data.substr(2 * (32 + i * outLength), 2 * outLength);
const decoded = method.decodeOutput('0x' + datum).map((t) => t.value);
results.push(decoded);
}
return results;
});
};

View File

@ -14,222 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { uniq, range, debounce } from 'lodash';
import { addCertification, removeCertification } from './actions';
import { getLogger, LOG_KEYS } from '~/config';
import Contract from '~/api/contract';
import Contracts from '~/contracts';
import CertifierABI from '~/contracts/abi/certifier.json';
const log = getLogger(LOG_KEYS.CertificationsMiddleware);
// TODO: move this to a more general place
const updatableFilter = (api, onFilter) => {
let filter = null;
const update = (address, topics) => {
if (filter) {
filter = filter.then((filterId) => {
api.eth.uninstallFilter(filterId);
});
}
filter = (filter || Promise.resolve())
.then(() => api.eth.newFilter({
fromBlock: 0,
toBlock: 'latest',
address,
topics
}))
.then((filterId) => {
onFilter(filterId);
return filterId;
})
.catch((err) => {
console.error('Failed to create certifications filter:', err);
});
return filter;
};
return update;
};
import Monitor from './certifiers.monitor';
export default class CertificationsMiddleware {
toMiddleware () {
const api = Contracts.get()._api;
const badgeReg = Contracts.get().badgeReg;
const contract = new Contract(api, CertifierABI);
const Confirmed = contract.events.find((e) => e.name === 'Confirmed');
const Revoked = contract.events.find((e) => e.name === 'Revoked');
return (store) => {
let certifiers = [];
let addresses = [];
let filterChanged = false;
let filter = null;
let badgeRegFilter = null;
let fetchCertifiersPromise = null;
const updateFilter = updatableFilter(api, (filterId) => {
filterChanged = true;
filter = filterId;
});
const badgeRegUpdateFilter = updatableFilter(api, (filterId) => {
filterChanged = true;
badgeRegFilter = filterId;
});
badgeReg
.getContract()
.then((badgeRegContract) => {
return badgeRegUpdateFilter(badgeRegContract.address, [ [
badgeRegContract.instance.Registered.signature,
badgeRegContract.instance.Unregistered.signature,
badgeRegContract.instance.MetaChanged.signature,
badgeRegContract.instance.AddressChanged.signature
] ]);
})
.then(() => {
shortFetchChanges();
api.subscribe('eth_blockNumber', (err) => {
if (err) {
return;
}
fetchChanges();
});
});
function onLogs (logs) {
logs = contract.parseEventLogs(logs);
logs.forEach((log) => {
const certifier = certifiers.find((c) => c.address === log.address);
if (!certifier) {
throw new Error(`Could not find certifier at ${log.address}.`);
}
const { id, name, title, icon } = certifier;
if (log.event === 'Revoked') {
store.dispatch(removeCertification(log.params.who.value, id));
} else {
store.dispatch(addCertification(log.params.who.value, id, name, title, icon));
}
});
}
function onBadgeRegLogs (logs) {
return badgeReg.getContract()
.then((badgeRegContract) => {
logs = badgeRegContract.parseEventLogs(logs);
const ids = logs.map((log) => log.params && log.params.id.value.toNumber());
return fetchCertifiers(uniq(ids));
});
}
function _fetchChanges () {
const method = filterChanged
? 'getFilterLogs'
: 'getFilterChanges';
filterChanged = false;
api.eth[method](badgeRegFilter)
.then(onBadgeRegLogs)
.catch((err) => {
console.error('Failed to fetch badge reg events:', err);
})
.then(() => api.eth[method](filter))
.then(onLogs)
.catch((err) => {
console.error('Failed to fetch new certifier events:', err);
});
}
const shortFetchChanges = debounce(_fetchChanges, 0.5 * 1000, { leading: true });
const fetchChanges = debounce(shortFetchChanges, 10 * 1000, { leading: true });
function fetchConfirmedEvents () {
return updateFilter(certifiers.map((c) => c.address), [
[ Confirmed.signature, Revoked.signature ],
addresses
]).then(() => shortFetchChanges());
}
function fetchCertifiers (ids = []) {
if (fetchCertifiersPromise) {
return fetchCertifiersPromise;
}
let fetchEvents = false;
const idsPromise = (certifiers.length === 0)
? badgeReg.certifierCount().then((count) => {
return range(count);
})
: Promise.resolve(ids);
fetchCertifiersPromise = idsPromise
.then((ids) => {
const promises = ids.map((id) => {
return badgeReg.fetchCertifier(id)
.then((cert) => {
if (!certifiers.some((c) => c.id === cert.id)) {
certifiers = certifiers.concat(cert);
fetchEvents = true;
}
})
.catch((err) => {
if (/does not exist/.test(err.toString())) {
return log.info(err.toString());
}
log.warn(`Could not fetch certifier ${id}:`, err);
});
});
return Promise
.all(promises)
.then(() => {
fetchCertifiersPromise = null;
if (fetchEvents) {
return fetchConfirmedEvents();
}
});
});
return fetchCertifiersPromise;
}
Monitor.init(api, store);
return (next) => (action) => {
switch (action.type) {
case 'fetchCertifiers':
fetchConfirmedEvents();
break;
case 'fetchCertifications':
const { address } = action;
if (!addresses.includes(address)) {
addresses = addresses.concat(address);
fetchConfirmedEvents();
}
break;
case 'setVisibleAccounts':
const _addresses = action.addresses || [];
const { addresses = [] } = action;
addresses = uniq(addresses.concat(_addresses));
fetchConfirmedEvents();
Monitor.get().fetchAccounts(addresses);
next(action);
break;

View File

@ -20,24 +20,32 @@ export default (state = initialState, action) => {
if (action.type === 'addCertification') {
const { address, id, name, icon, title } = action;
const certifications = state[address] || [];
const certifierIndex = certifications.findIndex((c) => c.id === id);
const data = { id, name, icon, title };
const nextCertifications = certifications.slice();
if (certifications.some((c) => c.id === id)) {
return state;
if (certifierIndex >= 0) {
nextCertifications[certifierIndex] = data;
} else {
nextCertifications.push(data);
}
const newCertifications = certifications.concat({
id, name, icon, title
});
return { ...state, [address]: newCertifications };
return { ...state, [address]: nextCertifications };
}
if (action.type === 'removeCertification') {
const { address, id } = action;
const certifications = state[address] || [];
const certifierIndex = certifications.findIndex((c) => c.id === id);
const newCertifications = certifications.filter((c) => c.id !== id);
// Don't remove if not there
if (certifierIndex < 0) {
return state;
}
const newCertifications = certifications.slice();
newCertifications.splice(certifierIndex, 1);
return { ...state, [address]: newCertifications };
}

View File

@ -18,6 +18,7 @@ export Balances from './balances';
export Personal from './personal';
export Signer from './signer';
export Status from './status';
export Tokens from './tokens';
export apiReducer from './apiReducer';
export balancesReducer from './balancesReducer';

View File

@ -16,37 +16,117 @@
import { personalAccountsInfo } from './personalActions';
let instance;
export default class Personal {
constructor (store, api) {
this._api = api;
this._store = store;
}
start () {
this._removeDeleted();
this._subscribeAccountsInfo();
static get (store) {
if (!instance && store) {
return Personal.init(store);
}
return instance;
}
static init (store) {
const { api } = store.getState();
if (!instance) {
instance = new Personal(store, api);
} else if (!instance) {
throw new Error('The Personal Provider has not been initialized yet');
}
return instance;
}
static start () {
const self = instance;
return Personal.stop()
.then(() => Promise.all([
self._removeDeleted(),
self._subscribeAccountsInfo()
]));
}
static stop () {
if (!instance) {
return Promise.resolve();
}
const self = instance;
return self._unsubscribeAccountsInfo();
}
_subscribeAccountsInfo () {
this._api
.subscribe('parity_allAccountsInfo', (error, accountsInfo) => {
if (error) {
console.error('parity_allAccountsInfo', error);
return;
}
let resolved = false;
// Add the address to each accounts
Object.keys(accountsInfo)
.forEach((address) => {
accountsInfo[address].address = address;
});
// The Promise will be resolved when the first
// accounts are loaded
return new Promise((resolve, reject) => {
this._api
.subscribe('parity_allAccountsInfo', (error, accountsInfo) => {
if (error) {
console.error('parity_allAccountsInfo', error);
this._store.dispatch(personalAccountsInfo(accountsInfo));
});
if (!resolved) {
resolved = true;
return reject(error);
}
return;
}
// Add the address to each accounts
Object.keys(accountsInfo)
.forEach((address) => {
accountsInfo[address].address = address;
});
const { dispatch, getState } = this._store;
personalAccountsInfo(accountsInfo)(dispatch, getState)
.then(() => {
if (!resolved) {
resolved = true;
return resolve();
}
})
.catch((error) => {
if (!resolved) {
resolved = true;
return reject(error);
}
});
})
.then((subId) => {
this.subscriptionId = subId;
});
});
}
_unsubscribeAccountsInfo () {
// Unsubscribe to any previous
// subscriptions
if (this.subscriptionId) {
return this._api
.unsubscribe(this.subscriptionId)
.then(() => {
this.subscriptionId = null;
});
}
return Promise.resolve();
}
_removeDeleted () {
this._api.parity
return this._api.parity
.allAccountsInfo()
.then((accountsInfo) => {
return Promise.all(

View File

@ -17,6 +17,7 @@
import { isEqual, intersection } from 'lodash';
import BalancesProvider from './balances';
import TokensProvider from './tokens';
import { updateTokensFilter } from './balancesActions';
import { attachWallets } from './walletActions';
@ -70,7 +71,7 @@ export function personalAccountsInfo (accountsInfo) {
return WalletsUtils.fetchOwners(walletContract.at(wallet.address));
});
Promise
return Promise
.all(_fetchOwners)
.then((walletsOwners) => {
return Object
@ -135,10 +136,6 @@ export function personalAccountsInfo (accountsInfo) {
hardware
}));
dispatch(attachWallets(wallets));
BalancesProvider.get().fetchAllBalances({
force: true
});
})
.catch((error) => {
console.warn('personalAccountsInfo', error);
@ -176,12 +173,17 @@ export function setVisibleAccounts (addresses) {
return;
}
// Update the Tokens filter to take into account the new
// addresses
dispatch(updateTokensFilter());
const promises = [];
BalancesProvider.get().fetchBalances({
force: true
});
// Update the Tokens filter to take into account the new
// addresses if it is not loading (it fetches the
// balances automatically after loading)
if (!TokensProvider.get().loading) {
promises.push(updateTokensFilter()(dispatch, getState));
}
promises.push(BalancesProvider.get().fetchEthBalances({ force: true }));
return Promise.all(promises);
};
}

View File

@ -23,12 +23,19 @@ import SavedRequests from '~/views/Application/Requests/savedRequests';
const savedRequests = new SavedRequests();
export const init = (api) => (dispatch) => {
api.subscribe('parity_postTransaction', (error, request) => {
api.subscribe('signer_requestsToConfirm', (error, pending) => {
if (error) {
return console.error(error);
return;
}
dispatch(watchRequest(request));
const requests = pending
.filter((p) => p.payload && p.payload.sendTransaction)
.map((p) => ({
requestId: '0x' + p.id.toString(16),
transaction: p.payload.sendTransaction
}));
requests.forEach((request) => dispatch(watchRequest(request)));
});
api.once('connected', () => {
@ -47,13 +54,24 @@ export const watchRequest = (request) => (dispatch, getState) => {
dispatch(trackRequest(requestId, request));
};
export const trackRequest = (requestId, { transactionHash = null } = {}) => (dispatch, getState) => {
export const trackRequest = (requestId, { transactionHash = null, retries = 0 } = {}) => (dispatch, getState) => {
const { api } = getState();
trackRequestUtil(api, { requestId, transactionHash }, (error, _data = {}) => {
const data = { ..._data };
if (error) {
// Retry in 500ms if request not found, max 5 times
if (error.type === 'REQUEST_NOT_FOUND') {
if (retries > 5) {
return dispatch(deleteRequest(requestId));
}
return setTimeout(() => {
trackRequest(requestId, { transactionHash, retries: retries + 1 })(dispatch, getState);
}, 500);
}
console.error(error);
return dispatch(setRequest(requestId, { error }));
}
@ -65,8 +83,9 @@ export const trackRequest = (requestId, { transactionHash = null } = {}) => (dis
const requestData = requests[requestId];
let blockSubscriptionId = -1;
// Set the block height to 0 at the beggining
data.blockHeight = new BigNumber(0);
// Set the block height to 1 at the beginning (transaction mined,
// thus one confirmation)
data.blockHeight = new BigNumber(1);
// If the request was a contract deployment,
// then add the contract with the saved metadata to the account

View File

@ -48,6 +48,12 @@ let store;
function createApi () {
api = {
transport: {
on: sinon.stub()
},
pubsub: {
subscribeAndGetResult: sinon.stub().returns(Promise.reject(new Error('not connected')))
},
net: {
version: sinon.stub().resolves('2')
},

View File

@ -14,12 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { isEqual } from 'lodash';
import { isEqual, debounce } from 'lodash';
import { LOG_KEYS, getLogger } from '~/config';
import UpgradeStore from '~/modals/UpgradeParity/store';
// import UpgradeStore from '~/modals/UpgradeParity/store';
import BalancesProvider from './balances';
import { statusBlockNumber, statusCollection } from './statusActions';
const log = getLogger(LOG_KEYS.Signer);
@ -31,7 +30,6 @@ const STATUS_BAD = 'bad';
export default class Status {
_apiStatus = {};
_status = {};
_longStatus = {};
_minerSettings = {};
_timeoutIds = {};
@ -41,21 +39,14 @@ export default class Status {
constructor (store, api) {
this._api = api;
this._store = store;
this._upgradeStore = UpgradeStore.get(api);
// On connecting, stop all subscriptions
api.on('connecting', this.stop, this);
// On connected, start the subscriptions
api.on('connected', this.start, this);
// On disconnected, stop all subscriptions
api.on('disconnected', this.stop, this);
// this._upgradeStore = UpgradeStore.get(api);
this.updateApiStatus();
}
static instantiate (store, api) {
static init (store) {
const { api } = store.getState();
if (!instance) {
instance = new Status(store, api);
}
@ -63,59 +54,61 @@ export default class Status {
return instance;
}
static get () {
if (!instance) {
static get (store) {
if (!instance && store) {
return Status.init(store);
} else if (!instance) {
throw new Error('The Status Provider has not been initialized yet');
}
return instance;
}
start () {
static start () {
const self = instance;
log.debug('status::start');
Promise
.all([
this._subscribeBlockNumber(),
const promises = [
self._subscribeBlockNumber(),
self._subscribeNetPeers(),
self._subscribeEthSyncing(),
self._subscribeNodeHealth(),
self._pollLongStatus(),
self._pollApiStatus()
];
this._pollLongStatus(),
this._pollStatus()
])
.then(() => {
return BalancesProvider.start();
});
return Status.stop()
.then(() => Promise.all(promises));
}
stop () {
log.debug('status::stop');
const promises = [];
if (this._blockNumberSubscriptionId) {
const promise = this._api
.unsubscribe(this._blockNumberSubscriptionId)
.then(() => {
this._blockNumberSubscriptionId = null;
});
promises.push(promise);
static stop () {
if (!instance) {
return Promise.resolve();
}
Object.values(this._timeoutIds).forEach((timeoutId) => {
clearTimeout(timeoutId);
});
const self = instance;
const promise = BalancesProvider.stop();
log.debug('status::stop');
promises.push(promise);
self._clearTimeouts();
return Promise.all(promises)
.then(() => true)
return self._unsubscribeBlockNumber()
.catch((error) => {
console.error('status::stop', error);
return true;
})
.then(() => this.updateApiStatus());
.then(() => self.updateApiStatus());
}
getApiStatus = () => {
const { isConnected, isConnecting, needsToken, secureToken } = this._api;
return {
isConnected,
isConnecting,
needsToken,
secureToken
};
}
updateApiStatus () {
@ -129,6 +122,33 @@ export default class Status {
}
}
_clearTimeouts () {
Object.values(this._timeoutIds).forEach((timeoutId) => {
clearTimeout(timeoutId);
});
}
_overallStatus (health) {
const allWithTime = [health.peers, health.sync, health.time].filter(x => x);
const all = [health.peers, health.sync].filter(x => x);
const statuses = all.map(x => x.status);
const bad = statuses.find(x => x === STATUS_BAD);
const needsAttention = statuses.find(x => x === STATUS_WARN);
const message = allWithTime.map(x => x.message).filter(x => x);
if (all.length) {
return {
status: bad || needsAttention || STATUS_OK,
message
};
}
return {
status: STATUS_BAD,
message: ['Unable to fetch node health.']
};
}
_subscribeBlockNumber = () => {
return this._api
.subscribe('eth_blockNumber', (error, blockNumber) => {
@ -159,92 +179,81 @@ export default class Status {
});
}
_pollTraceMode = () => {
return this._api.trace
.block()
.then(blockTraces => {
// Assumes not in Trace Mode if no transactions
// in latest block...
return blockTraces.length > 0;
})
.catch(() => false);
_updateStatus = debounce(status => {
this._store.dispatch(statusCollection(status));
}, 2500, {
maxWait: 5000
});
_subscribeEthSyncing = () => {
return this._api.pubsub
.eth
.syncing((error, syncing) => {
if (error) {
return;
}
this._updateStatus({ syncing });
});
}
getApiStatus = () => {
const { isConnected, isConnecting, needsToken, secureToken } = this._api;
_subscribeNetPeers = () => {
return this._api.pubsub
.parity
.netPeers((error, netPeers) => {
if (error || !netPeers) {
return;
}
return {
isConnected,
isConnecting,
needsToken,
secureToken
};
this._store.dispatch(statusCollection({ netPeers }));
});
}
_pollStatus = () => {
const nextTimeout = (timeout = 1000) => {
if (this._timeoutIds.status) {
clearTimeout(this._timeoutIds.status);
}
this._timeoutIds.status = setTimeout(() => this._pollStatus(), timeout);
};
this.updateApiStatus();
if (!this._api.isConnected) {
nextTimeout(250);
return Promise.resolve();
}
const statusPromises = [
this._api.eth.syncing(),
this._api.parity.netPeers(),
this._api.parity.nodeHealth()
];
return Promise
.all(statusPromises)
.then(([ syncing, netPeers, health ]) => {
const status = { netPeers, syncing, health };
_subscribeNodeHealth = () => {
return this._api.pubsub
.parity
.nodeHealth((error, health) => {
if (error || !health) {
return;
}
health.overall = this._overallStatus(health);
health.peers = health.peers || {};
health.sync = health.sync || {};
health.time = health.time || {};
if (!isEqual(status, this._status)) {
this._store.dispatch(statusCollection(status));
this._status = status;
}
})
.catch((error) => {
console.error('_pollStatus', error);
})
.then(() => {
nextTimeout();
this._store.dispatch(statusCollection({ health }));
});
}
_overallStatus = (health) => {
const allWithTime = [health.peers, health.sync, health.time].filter(x => x);
const all = [health.peers, health.sync].filter(x => x);
const statuses = all.map(x => x.status);
const bad = statuses.find(x => x === STATUS_BAD);
const needsAttention = statuses.find(x => x === STATUS_WARN);
const message = allWithTime.map(x => x.message).filter(x => x);
if (all.length) {
return {
status: bad || needsAttention || STATUS_OK,
message
};
_unsubscribeBlockNumber () {
if (this._blockNumberSubscriptionId) {
return this._api
.unsubscribe(this._blockNumberSubscriptionId)
.then(() => {
this._blockNumberSubscriptionId = null;
});
}
return {
status: STATUS_BAD,
message: ['Unable to fetch node health.']
return Promise.resolve();
}
_pollApiStatus = () => {
const nextTimeout = (timeout = 1000) => {
if (this._timeoutIds.status) {
clearTimeout(this._timeoutIds.status);
}
this._timeoutIds.status = setTimeout(() => this._pollApiStatus(), timeout);
};
this.updateApiStatus();
if (!this._api.isConnected) {
nextTimeout(250);
} else {
nextTimeout();
}
}
/**
@ -259,7 +268,7 @@ export default class Status {
}
const { nodeKindFull } = this._store.getState().nodeStatus;
const defaultTimeout = (nodeKindFull === false ? 240 : 30) * 1000;
const defaultTimeout = (nodeKindFull === false ? 240 : 60) * 1000;
const nextTimeout = (timeout = defaultTimeout) => {
if (this._timeoutIds.longStatus) {
@ -271,19 +280,18 @@ export default class Status {
const statusPromises = [
this._api.parity.nodeKind(),
this._api.parity.netPeers(),
this._api.web3.clientVersion(),
this._api.net.version(),
this._api.parity.netChain()
];
if (nodeKindFull) {
statusPromises.push(this._upgradeStore.checkUpgrade());
}
// if (nodeKindFull) {
// statusPromises.push(this._upgradeStore.checkUpgrade());
// }
return Promise
.all(statusPromises)
.then(([nodeKind, netPeers, clientVersion, netVersion, netChain]) => {
.then(([nodeKind, clientVersion, netVersion, netChain]) => {
const isTest = [
'2', // morden
'3', // ropsten,
@ -298,7 +306,6 @@ export default class Status {
const longStatus = {
nodeKind,
nodeKindFull,
netPeers,
clientVersion,
netChain,
netVersion,
@ -310,11 +317,12 @@ export default class Status {
this._longStatus = longStatus;
}
})
.then(() => {
nextTimeout();
})
.catch((error) => {
console.error('_pollLongStatus', error);
})
.then(() => {
nextTimeout(60000);
nextTimeout(30000);
});
}
}

View File

@ -0,0 +1,166 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { updateTokensFilter } from './balancesActions';
import { loadTokens, fetchTokens } from './tokensActions';
import { padRight } from '~/api/util/format';
import { LOG_KEYS, getLogger } from '~/config';
import Contracts from '~/contracts';
const log = getLogger(LOG_KEYS.Balances);
let instance = null;
export default class Tokens {
constructor (store, api) {
this._api = api;
this._store = store;
this._tokenreg = null;
this._tokenregSubs = [];
this._loading = false;
}
get loading () {
return this._loading;
}
static get (store) {
if (!instance && store) {
return Tokens.init(store);
} else if (!instance) {
throw new Error('The Tokens Provider has not been initialized yet');
}
return instance;
}
static init (store) {
const { api } = store.getState();
if (!instance) {
instance = new Tokens(store, api);
}
return instance;
}
static start () {
if (!instance) {
return Promise.reject('Tokens Provider has not been initiated yet');
}
const self = instance;
self._loading = true;
// Unsubscribe from previous subscriptions
return Tokens.stop()
.then(() => self.loadTokens())
.then(() => {
self._loading = false;
});
}
static stop () {
if (!instance) {
return Promise.resolve();
}
const self = instance;
// Unsubscribe without adding the promises
// to the result, since it would have to wait for a
// reconnection to resolve if the Node is disconnected
if (self._tokenreg) {
const tokenregPromises = self._tokenregSubs
.map((tokenregSID) => self._tokenreg.unsubscribe(tokenregSID));
Promise.all(tokenregPromises)
.then(() => {
self._tokenregSubs = [];
});
}
return Promise.resolve();
}
attachToTokensEvents (tokenreg) {
const metaTopics = [ null, padRight(this._api.util.asciiToHex('IMG'), 32) ];
return Promise
.all([
this._attachToTokenregEvents(tokenreg, 'Registered'),
this._attachToTokenregEvents(tokenreg, 'MetaChanged', metaTopics)
]);
}
getTokenRegistry () {
return Contracts.get().tokenReg.getContract();
}
loadTokens (options = {}) {
const { dispatch, getState } = this._store;
return this
.getTokenRegistry()
.then((tokenreg) => {
this._tokenreg = tokenreg;
return loadTokens(options)(dispatch, getState);
})
.then(() => updateTokensFilter()(dispatch, getState))
.then(() => this.attachToTokensEvents(this._tokenreg))
.catch((error) => {
console.warn('balances::loadTokens', error);
});
}
_attachToTokenregEvents (tokenreg, event, topics = []) {
if (this._tokenregSID) {
return Promise.resolve();
}
return tokenreg.instance[event]
.subscribe({
fromBlock: 'latest',
toBlock: 'latest',
topics: topics,
skipInitFetch: true
}, (error, logs) => {
if (error) {
return console.error('balances::attachToNewToken', 'failed to attach to tokenreg Registered', error.toString(), error.stack);
}
this._handleTokensLogs(logs);
})
.then((tokenregSID) => {
this._tokenregSubs.push(tokenregSID);
});
}
_handleTokensLogs (logs) {
const { dispatch, getState } = this._store;
const tokenIds = logs.map((log) => log.params.id.value.toNumber());
log.debug('got TokenRegistry logs', logs, tokenIds);
return fetchTokens(tokenIds)(dispatch, getState)
.then(() => updateTokensFilter()(dispatch, getState));
}
}

View File

@ -14,56 +14,223 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { uniq } from 'lodash';
import { chunk, uniq } from 'lodash';
import store from 'store';
import Contracts from '~/contracts';
import { LOG_KEYS, getLogger } from '~/config';
import { fetchTokenIds, fetchTokenInfo } from '~/util/tokens';
import { fetchTokenIds, fetchTokensBasics, fetchTokensInfo, fetchTokensImages } from '~/util/tokens';
import { updateTokensFilter } from './balancesActions';
import { setAddressImage } from './imagesActions';
const TOKENS_CACHE_LS_KEY_PREFIX = '_parity::tokens::';
const log = getLogger(LOG_KEYS.Balances);
export function setTokens (tokens) {
function _setTokens (tokens) {
return {
type: 'setTokens',
tokens
};
}
export function setTokens (nextTokens) {
return (dispatch, getState) => {
const { nodeStatus, tokens: prevTokens } = getState();
const { tokenReg } = Contracts.get();
const tokens = {
...prevTokens,
...nextTokens
};
return tokenReg.getContract()
.then((tokenRegContract) => {
const lsKey = TOKENS_CACHE_LS_KEY_PREFIX + nodeStatus.netChain;
store.set(lsKey, {
tokenreg: tokenRegContract.address,
tokens
});
})
.catch((error) => {
console.error(error);
})
.then(() => {
dispatch(_setTokens(nextTokens));
});
};
}
function loadCachedTokens (tokenRegContract) {
return (dispatch, getState) => {
const { nodeStatus } = getState();
const lsKey = TOKENS_CACHE_LS_KEY_PREFIX + nodeStatus.netChain;
const cached = store.get(lsKey);
if (cached) {
// Check if we have data from the right contract
if (cached.tokenreg === tokenRegContract.address && cached.tokens) {
log.debug('found cached tokens', cached.tokens);
// Fetch all the tokens images on load
// (it's the only thing that might have changed)
const tokenIndexes = Object.values(cached.tokens)
.filter((t) => t && t.fetched)
.map((t) => t.index);
fetchTokensData(tokenRegContract, tokenIndexes)(dispatch, getState);
} else {
store.remove(lsKey);
}
}
};
}
export function loadTokens (options = {}) {
log.debug('loading tokens', Object.keys(options).length ? options : '');
return (dispatch, getState) => {
const { tokenReg } = Contracts.get();
tokenReg.getInstance()
.then((tokenRegInstance) => {
return fetchTokenIds(tokenRegInstance);
return tokenReg.getContract()
.then((tokenRegContract) => {
loadCachedTokens(tokenRegContract)(dispatch, getState);
return fetchTokenIds(tokenRegContract.instance);
})
.then((tokenIndexes) => dispatch(fetchTokens(tokenIndexes, options)))
.then((tokenIndexes) => loadTokensBasics(tokenIndexes, options)(dispatch, getState))
.catch((error) => {
console.warn('tokens::loadTokens', error);
});
};
}
export function fetchTokens (_tokenIndexes, options = {}) {
const tokenIndexes = uniq(_tokenIndexes || []);
export function loadTokensBasics (tokenIndexes, options) {
const limit = 64;
return (dispatch, getState) => {
const { api } = getState();
const { tokenReg } = Contracts.get();
const nextTokens = {};
const count = tokenIndexes.length;
log.debug('loading basic tokens', tokenIndexes);
if (count === 0) {
return Promise.resolve();
}
return tokenReg.getContract()
.then((tokenRegContract) => {
let promise = Promise.resolve();
const first = tokenIndexes[0];
const last = tokenIndexes[tokenIndexes.length - 1];
for (let from = first; from <= last; from += limit) {
// No need to fetch `limit` elements
const lowerLimit = Math.min(limit, last - from + 1);
promise = promise
.then(() => fetchTokensBasics(api, tokenRegContract, from, lowerLimit))
.then((results) => {
results
.forEach((token) => {
nextTokens[token.id] = token;
});
});
}
return promise;
})
.then(() => {
log.debug('fetched tokens basic info', nextTokens);
dispatch(setTokens(nextTokens));
})
.catch((error) => {
console.warn('tokens::fetchTokens', error);
});
};
}
export function fetchTokens (_tokenIndexes) {
const tokenIndexes = uniq(_tokenIndexes || []);
const tokenChunks = chunk(tokenIndexes, 64);
return (dispatch, getState) => {
const { api, images } = getState();
const { tokenReg } = Contracts.get();
return tokenReg.getInstance()
.then((tokenRegInstance) => {
const promises = tokenIndexes.map((id) => fetchTokenInfo(api, tokenRegInstance, id));
return tokenReg.getContract()
.then((tokenRegContract) => {
let promise = Promise.resolve();
return Promise.all(promises);
tokenChunks.forEach((tokenChunk) => {
promise = promise
.then(() => fetchTokensData(tokenRegContract, tokenChunk)(dispatch, getState));
});
return promise;
})
.then((results) => {
const tokens = results
.then(() => {
log.debug('fetched token', getState().tokens);
})
.catch((error) => {
console.warn('tokens::fetchTokens', error);
});
};
}
/**
* Split the given token indexes between those for whom
* we already have some info, and thus just need to fetch
* the image, and those for whom we don't have anything and
* need to fetch all the info.
*/
function fetchTokensData (tokenRegContract, tokenIndexes) {
return (dispatch, getState) => {
const { api, tokens, images } = getState();
const allTokens = Object.values(tokens);
const tokensIndexesMap = allTokens
.reduce((map, token) => {
map[token.index] = token;
return map;
}, {});
const fetchedTokenIndexes = allTokens
.filter((token) => token.fetched)
.map((token) => token.index);
const fullIndexes = [];
const partialIndexes = [];
tokenIndexes.forEach((tokenIndex) => {
if (fetchedTokenIndexes.includes(tokenIndex)) {
partialIndexes.push(tokenIndex);
} else {
fullIndexes.push(tokenIndex);
}
});
log.debug('need to fully fetch', fullIndexes);
log.debug('need to partially fetch', partialIndexes);
const fullPromise = fetchTokensInfo(api, tokenRegContract, fullIndexes);
const partialPromise = fetchTokensImages(api, tokenRegContract, partialIndexes)
.then((imagesResult) => {
return imagesResult.map((image, index) => {
const tokenIndex = partialIndexes[index];
const token = tokensIndexesMap[tokenIndex];
return { ...token, image };
});
});
return Promise.all([ fullPromise, partialPromise ])
.then(([ fullResults, partialResults ]) => {
log.debug('fetched', { fullResults, partialResults });
return [].concat(fullResults, partialResults)
.filter(({ address }) => !/0x0*$/.test(address))
.reduce((tokens, token) => {
const { id, image, address } = token;
@ -75,14 +242,9 @@ export function fetchTokens (_tokenIndexes, options = {}) {
tokens[id] = token;
return tokens;
}, {});
log.debug('fetched token', tokens);
dispatch(setTokens(tokens));
dispatch(updateTokensFilter(null, null, options));
})
.catch((error) => {
console.warn('tokens::fetchTokens', error);
.then((tokens) => {
dispatch(setTokens(tokens));
});
};
}

View File

@ -25,10 +25,15 @@ const initialState = {
export default handleActions({
setTokens (state, action) {
const { tokens } = action;
const nextTokens = { ...state };
return {
...state,
...tokens
};
Object.keys(tokens).forEach((tokenId) => {
nextTokens[tokenId] = {
...(nextTokens[tokenId]),
...tokens[tokenId]
};
});
return nextTokens;
}
}, initialState);

View File

@ -22,12 +22,14 @@ import initReducers from './reducers';
import { load as loadWallet } from './providers/walletActions';
import { init as initRequests } from './providers/requestsActions';
import { setupWorker } from './providers/workerWrapper';
import { setApi } from './providers/apiActions';
import {
Balances as BalancesProvider,
Personal as PersonalProvider,
Signer as SignerProvider,
Status as StatusProvider
Status as StatusProvider,
Tokens as TokensProvider
} from './providers';
const storeCreation = window.devToolsExtension
@ -39,14 +41,59 @@ export default function (api, browserHistory, forEmbed = false) {
const middleware = initMiddleware(api, browserHistory, forEmbed);
const store = applyMiddleware(...middleware)(storeCreation)(reducers);
BalancesProvider.instantiate(store, api);
StatusProvider.instantiate(store, api);
new PersonalProvider(store, api).start();
// Add the `api` to the Redux Store
store.dispatch({ type: 'initAll', api });
store.dispatch(setApi(api));
// Initialise the Store Providers
BalancesProvider.init(store);
PersonalProvider.init(store);
StatusProvider.init(store);
TokensProvider.init(store);
new SignerProvider(store, api).start();
store.dispatch(loadWallet(api));
store.dispatch(initRequests(api));
setupWorker(store);
const start = () => {
return Promise
.resolve()
.then(() => console.log('v1: starting Status Provider...'))
.then(() => StatusProvider.start())
.then(() => console.log('v1: started Status Provider'))
.then(() => console.log('v1: starting Personal Provider...'))
.then(() => PersonalProvider.start())
.then(() => console.log('v1: started Personal Provider'))
.then(() => console.log('v1: starting Balances Provider...'))
.then(() => BalancesProvider.start())
.then(() => console.log('v1: started Balances Provider'))
.then(() => console.log('v1: starting Tokens Provider...'))
.then(() => TokensProvider.start())
.then(() => console.log('v1: started Tokens Provider'));
};
const stop = () => {
return StatusProvider
.stop()
.then(() => PersonalProvider.stop())
.then(() => TokensProvider.stop())
.then(() => BalancesProvider.stop());
};
// On connected, start the subscriptions
api.on('connected', start);
// On disconnected, stop all subscriptions
api.on('disconnected', stop);
if (api.isConnected) {
start();
}
return store;
}

View File

@ -17,12 +17,12 @@
import Push from 'push.js';
import BigNumber from 'bignumber.js';
import unkownIcon from '~/../assets/images/contracts/unknown-64x64.png';
import unknownIcon from '~/../assets/images/contracts/unknown-64x64.png';
export function notifyTransaction (account, token, _value, onClick) {
const name = account.name || account.address;
const value = _value.div(new BigNumber(token.format || 1));
const icon = token.image || unkownIcon;
const icon = token.image || unknownIcon;
let _notification = null;

View File

@ -1,133 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { range } from 'lodash';
import BigNumber from 'bignumber.js';
import { hashToImageUrl } from '~/redux/util';
import { sha3 } from '~/api/util/sha3';
import imagesEthereum from '~/../assets/images/contracts/ethereum-black-64x64.png';
const BALANCEOF_SIGNATURE = sha3('balanceOf(address)');
const ADDRESS_PADDING = range(24).map(() => '0').join('');
export const ETH_TOKEN = {
address: '',
format: new BigNumber(10).pow(18),
id: sha3('eth_native_token').slice(0, 10),
image: imagesEthereum,
name: 'Ethereum',
native: true,
tag: 'ETH'
};
export function fetchTokenIds (tokenregInstance) {
return tokenregInstance.tokenCount
.call()
.then((numTokens) => {
const tokenIndexes = range(numTokens.toNumber());
return tokenIndexes;
});
}
export function fetchTokenInfo (api, tokenregInstace, tokenIndex) {
return Promise
.all([
tokenregInstace.token.call({}, [tokenIndex]),
tokenregInstace.meta.call({}, [tokenIndex, 'IMG'])
])
.then(([ tokenData, image ]) => {
const [ address, tag, format, name ] = tokenData;
const token = {
format: format.toString(),
index: tokenIndex,
image: hashToImageUrl(image),
id: sha3(address + tokenIndex).slice(0, 10),
address,
name,
tag
};
return token;
});
}
/**
* `updates` should be in the shape:
* {
* [ who ]: [ tokenId ] // Array of tokens to updates
* }
*
* Returns a Promise resolved witht the balances in the shape:
* {
* [ who ]: { [ tokenId ]: BigNumber } // The balances of `who`
* }
*/
export function fetchAccountsBalances (api, tokens, updates) {
const addresses = Object.keys(updates);
const promises = addresses
.map((who) => {
const tokensIds = updates[who];
const tokensToUpdate = tokensIds.map((tokenId) => tokens.find((t) => t.id === tokenId));
return fetchAccountBalances(api, tokensToUpdate, who);
});
return Promise.all(promises)
.then((results) => {
return results.reduce((balances, accountBalances, index) => {
balances[addresses[index]] = accountBalances;
return balances;
}, {});
});
}
/**
* Returns a Promise resolved with the balances in the shape:
* {
* [ tokenId ]: BigNumber // Token balance value
* }
*/
export function fetchAccountBalances (api, tokens, who) {
const calldata = '0x' + BALANCEOF_SIGNATURE.slice(2, 10) + ADDRESS_PADDING + who.slice(2);
const promises = tokens.map((token) => fetchTokenBalance(api, token, { who, calldata }));
return Promise.all(promises)
.then((results) => {
return results.reduce((balances, value, index) => {
const token = tokens[index];
balances[token.id] = value;
return balances;
}, {});
});
}
export function fetchTokenBalance (api, token, { who, calldata }) {
if (token.native) {
return api.eth.getBalance(who);
}
return api.eth
.call({ data: calldata, to: token.address })
.then((result) => {
const cleanResult = result.replace(/^0x/, '');
return new BigNumber(`0x${cleanResult || 0}`);
});
}

View File

@ -0,0 +1,23 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
// build from : https://raw.githubusercontent.com/paritytech/contracts/4c8501e908166aab7ff4d2ebb05db61b5d017024/TokenCalls.sol
// metadata (include build version and options):
// {"compiler":{"version":"0.4.16+commit.d7661dd9"},"language":"Solidity","output":{"abi":[{"inputs":[{"name":"tokenRegAddress","type":"address"},{"name":"start","type":"uint256"},{"name":"limit","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"methods":{}},"userdoc":{"methods":{}}},"settings":{"compilationTarget":{"":"Tokens"},"libraries":{},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"sources":{"":{"keccak256":"0x4790e490f418d1a5884c27ffe9684914dab2d55bd1d23b99cff7aa2ca289e2d3","urls":["bzzr://bb200beae6849f1f5bb97b36c57cd493be52877ec0b55ee9969fa5f8159cf37b"]}},"version":1}
// {"compiler":{"version":"0.4.16+commit.d7661dd9"},"language":"Solidity","output":{"abi":[{"inputs":[{"name":"who","type":"address[]"},{"name":"tokens","type":"address[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"methods":{}},"userdoc":{"methods":{}}},"settings":{"compilationTarget":{"":"TokensBalances"},"libraries":{},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"sources":{"":{"keccak256":"0x4790e490f418d1a5884c27ffe9684914dab2d55bd1d23b99cff7aa2ca289e2d3","urls":["bzzr://bb200beae6849f1f5bb97b36c57cd493be52877ec0b55ee9969fa5f8159cf37b"]}},"version":1}
export const tokenAddresses = '0x6060604052341561000f57600080fd5b6040516060806102528339810160405280805191906020018051919060200180519150505b6000806000806100426101fc565b600088955085600160a060020a0316639f181b5e6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156100a657600080fd5b6102c65a03f115156100b757600080fd5b50505060405180519550508688018890116100ce57fe5b8785116100de57600093506100f6565b8487890111156100f25787850393506100f6565b8693505b5b83602002602001925060405191508282016040528382528790505b8388018110156101ea5785600160a060020a031663044215c682600060405160a001526040517c010000000000000000000000000000000000000000000000000000000063ffffffff8416028152600481019190915260240160a060405180830381600087803b151561018457600080fd5b6102c65a03f1151561019557600080fd5b50505060405180519060200180519060200180519060200180519060200180515086935050508a84039050815181106101ca57fe5b600160a060020a039092166020928302909101909101525b600101610112565b8282f35b50505050505050505061020e565b60206040519081016040526000815290565b60368061021c6000396000f30060606040525b600080fd00a165627a7a72305820a9a09f013393cf3c6398ce0f8175073fe363b6f594f9bd569261d0bb94aa84d40029';
export const tokensBalances = '0x6060604052341561000f57600080fd5b60405161018b38038061018b8339810160405280805182019190602001805190910190505b6000806000610041610135565b60008060008060008060008c518c51029a506020808c020199507f70a0823100000000000000000000000000000000000000000000000000000000985060405197508988016040528a8852604051965060248701604052888752879550866004019450600093505b8c5184101561011f57600092505b8b51831015610113578c84815181106100cc57fe5b9060200190602002015191508b83815181106100e457fe5b90602001906020020151905060208601955081855260208660248960008561fffff1505b6001909201916100b7565b5b6001909301926100a9565b8988f35b50505050505050505050505050610147565b60206040519081016040526000815290565b6036806101556000396000f30060606040525b600080fd00a165627a7a723058203cfc17c394936aa87b7db79e4f082a7cfdcefef54acd3124d17525b56c92e7950029';

View File

@ -81,12 +81,11 @@ export function getTxOptions (api, func, _options, values = []) {
options.to = options.to || func.contract.address;
}
if (!address) {
return Promise.resolve({ func, options, values });
}
const promise = (!address)
? Promise.resolve(false)
: WalletsUtils.isWallet(api, address);
return WalletsUtils
.isWallet(api, address)
return promise
.then((isWallet) => {
if (!isWallet) {
return { func, options, values };

View File

@ -78,13 +78,39 @@ export default class WalletsUtils {
.delegateCall(api, walletContract.address, 'fetchTransactions', [ walletContract ])
.then((transactions) => {
return transactions.sort((txA, txB) => {
const comp = txB.blockNumber.comparedTo(txA.blockNumber);
const bnA = txA.blockNumber;
const bnB = txB.blockNumber;
if (!bnA) {
console.warn('could not find block number in transaction', txA);
return 1;
}
if (!bnB) {
console.warn('could not find block number in transaction', txB);
return -1;
}
const comp = bnA.comparedTo(bnB);
if (comp !== 0) {
return comp;
}
return txB.transactionIndex.comparedTo(txA.transactionIndex);
const txIdxA = txA.transactionIndex;
const txIdxB = txB.transactionIndex;
if (!txIdxA) {
console.warn('could not find transaction index in transaction', txA);
return 1;
}
if (!txIdxB) {
console.warn('could not find transaction index in transaction', txB);
return -1;
}
return txIdxA.comparedTo(txIdxB);
});
});
}

View File

@ -212,6 +212,7 @@ export default class ConsensysWalletUtils {
const transaction = {
transactionHash: log.transactionHash,
transactionIndex: log.transactionIndex,
blockNumber: log.blockNumber
};

View File

@ -130,27 +130,67 @@ export default class FoundationWalletUtils {
.ConfirmationNeeded
.getAllLogs()
.then((logs) => {
return logs.map((log) => ({
initiator: log.params.initiator.value,
to: log.params.to.value,
data: log.params.data.value,
value: log.params.value.value,
operation: bytesToHex(log.params.operation.value),
transactionIndex: log.transactionIndex,
transactionHash: log.transactionHash,
blockNumber: log.blockNumber,
confirmedBy: []
}));
return logs
.filter((log) => {
if (!log.blockNumber) {
console.warn('got a log without blockNumber', log);
return false;
}
if (!log.transactionIndex) {
console.warn('got a log without transactionIndex', log);
return false;
}
return true;
})
.map((log) => ({
initiator: log.params.initiator.value,
to: log.params.to.value,
data: log.params.data.value,
value: log.params.value.value,
operation: bytesToHex(log.params.operation.value),
transactionIndex: log.transactionIndex,
transactionHash: log.transactionHash,
blockNumber: log.blockNumber,
confirmedBy: []
}));
})
.then((logs) => {
return logs.sort((logA, logB) => {
const comp = logA.blockNumber.comparedTo(logB.blockNumber);
const bnA = logA.blockNumber;
const bnB = logA.blockNumber;
if (!bnA) {
console.warn('could not find block number in log', logA);
return 1;
}
if (!bnB) {
console.warn('could not find block number in log', logB);
return -1;
}
const comp = bnA.comparedTo(bnB);
if (comp !== 0) {
return comp;
}
return logA.transactionIndex.comparedTo(logB.transactionIndex);
const txIdxA = logA.transactionIndex;
const txIdxB = logB.transactionIndex;
if (!txIdxA) {
console.warn('could not find transaction index in log', logA);
return 1;
}
if (!txIdxB) {
console.warn('could not find transaction index in log', logB);
return -1;
}
return txIdxA.comparedTo(txIdxB);
});
})
.then((pendingTxs) => {
@ -205,40 +245,48 @@ export default class FoundationWalletUtils {
] ]
})
.then((logs) => {
const transactions = logs.map((log) => {
const signature = toHex(log.topics[0]);
const transactions = logs
.map((log) => {
const signature = toHex(log.topics[0]);
const value = log.params.value.value;
const from = signature === WalletSignatures.Deposit
? log.params['_from'].value
: walletContract.address;
const value = log.params.value.value;
const from = signature === WalletSignatures.Deposit
? log.params['_from'].value
: walletContract.address;
const to = signature === WalletSignatures.Deposit
? walletContract.address
: log.params.to.value;
const to = signature === WalletSignatures.Deposit
? walletContract.address
: log.params.to.value;
const transaction = {
transactionHash: log.transactionHash,
blockNumber: log.blockNumber,
from, to, value
};
const transaction = {
transactionHash: log.transactionHash,
transactionIndex: log.transactionIndex,
blockNumber: log.blockNumber,
from, to, value
};
if (log.params.created && log.params.created.value && !/^(0x)?0*$/.test(log.params.created.value)) {
transaction.creates = log.params.created.value;
delete transaction.to;
}
if (!transaction.blockNumber) {
console.warn('log without block number', log);
return null;
}
if (log.params.operation) {
transaction.operation = bytesToHex(log.params.operation.value);
checkPendingOperation(api, log, transaction.operation);
}
if (log.params.created && log.params.created.value && !/^(0x)?0*$/.test(log.params.created.value)) {
transaction.creates = log.params.created.value;
delete transaction.to;
}
if (log.params.data) {
transaction.data = log.params.data.value;
}
if (log.params.operation) {
transaction.operation = bytesToHex(log.params.operation.value);
checkPendingOperation(api, log, transaction.operation);
}
return transaction;
});
if (log.params.data) {
transaction.data = log.params.data.value;
}
return transaction;
})
.filter((tx) => tx);
return transactions;
});

View File

@ -26,7 +26,6 @@ import HardwareStore from '~/mobx/hardwareStore';
import ExportStore from '~/modals/ExportAccount/exportStore';
import { DeleteAccount, EditMeta, Faucet, PasswordManager, Shapeshift, Transfer, Verification } from '~/modals';
import { setVisibleAccounts } from '~/redux/providers/personalActions';
import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions';
import { Actionbar, Button, ConfirmDialog, Input, Page, Portal } from '~/ui';
import { DeleteIcon, DialIcon, EditIcon, LockedIcon, SendIcon, VerifyIcon, FileDownloadIcon } from '~/ui/Icons';
@ -45,8 +44,6 @@ class Account extends Component {
static propTypes = {
accounts: PropTypes.object.isRequired,
fetchCertifiers: PropTypes.func.isRequired,
fetchCertifications: PropTypes.func.isRequired,
setVisibleAccounts: PropTypes.func.isRequired,
account: PropTypes.object,
@ -67,7 +64,6 @@ class Account extends Component {
}
componentDidMount () {
this.props.fetchCertifiers();
this.setVisibleAccounts();
}
@ -90,11 +86,10 @@ class Account extends Component {
}
setVisibleAccounts (props = this.props) {
const { params, setVisibleAccounts, fetchCertifications } = props;
const { params, setVisibleAccounts } = props;
const addresses = [params.address];
setVisibleAccounts(addresses);
fetchCertifications(params.address);
}
render () {
@ -370,14 +365,14 @@ class Account extends Component {
onDeny={ this.exportClose }
title={
<FormattedMessage
id='export.account.title'
id='account.export.title'
defaultMessage='Export Account'
/>
}
>
<div className={ styles.textbox }>
<FormattedMessage
id='export.account.info'
id='account.export.info'
defaultMessage='Export your account as a JSON file. Please enter the password linked with this account.'
/>
</div>
@ -388,13 +383,13 @@ class Account extends Component {
type='password'
hint={
<FormattedMessage
id='export.account.password.hint'
id='account.export.password.hint'
defaultMessage='The password specified when creating this account'
/>
}
label={
<FormattedMessage
id='export.account.password.label'
id='account.export.password.label'
defaultMessage='Account password'
/>
}
@ -524,8 +519,6 @@ function mapStateToProps (state, props) {
function mapDispatchToProps (dispatch) {
return bindActionCreators({
fetchCertifiers,
fetchCertifications,
newError,
setVisibleAccounts
}, dispatch);

View File

@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import sinon from 'sinon';
import { shallow } from 'enzyme';
import React from 'react';
@ -34,7 +35,15 @@ function render (props) {
/>,
{
context: {
store: createRedux()
store: createRedux(),
api: {
transport: {
on: sinon.stub()
},
pubsub: {
subscribeAndGetResult: sinon.stub()
}
}
}
}
).find('Account').shallow();

View File

@ -17,10 +17,8 @@
import { pick } from 'lodash';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Container, SectionList } from '~/ui';
import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions';
import { ETH_TOKEN } from '~/util/tokens';
import Summary from '../Summary';
@ -38,20 +36,9 @@ class List extends Component {
orderFallback: PropTypes.string,
search: PropTypes.array,
fetchCertifiers: PropTypes.func.isRequired,
fetchCertifications: PropTypes.func.isRequired,
handleAddSearchToken: PropTypes.func
};
componentWillMount () {
const { accounts, fetchCertifiers, fetchCertifications } = this.props;
fetchCertifiers();
for (let address in accounts) {
fetchCertifications(address);
}
}
render () {
const { accounts, disabled, empty } = this.props;
@ -264,14 +251,7 @@ function mapStateToProps (state, props) {
return { balances, certifications };
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({
fetchCertifiers,
fetchCertifications
}, dispatch);
}
export default connect(
mapStateToProps,
mapDispatchToProps
null
)(List);

View File

@ -27,7 +27,11 @@ let instance;
let redux;
function createApi () {
api = {};
api = {
pubsub: {
subscribeAndGetResult: sinon.stub().returns(Promise.reject(new Error('uninitialized')))
}
};
return api;
}

View File

@ -16,8 +16,7 @@
import React, { Component, PropTypes } from 'react';
import { FirstRun, UpgradeParity } from '~/modals';
import { Errors, ParityBackground, Tooltips } from '~/ui';
import { Errors, ParityBackground } from '~/ui';
import styles from '../application.css';
@ -25,24 +24,17 @@ export default class Container extends Component {
static propTypes = {
children: PropTypes.node.isRequired,
onCloseFirstRun: PropTypes.func,
showFirstRun: PropTypes.bool,
upgradeStore: PropTypes.object.isRequired
showFirstRun: PropTypes.bool
};
render () {
const { children, onCloseFirstRun, showFirstRun, upgradeStore } = this.props;
const { children } = this.props;
return (
<ParityBackground
attachDocument
className={ styles.container }
>
<FirstRun
onClose={ onCloseFirstRun }
visible={ showFirstRun }
/>
<Tooltips />
<UpgradeParity store={ upgradeStore } />
<Errors />
{ children }
</ParityBackground>

View File

@ -15,13 +15,12 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import { Toolbar, ToolbarGroup } from 'material-ui/Toolbar';
import { isEqual } from 'lodash';
import { Tooltip, StatusIndicator } from '~/ui';
import { StatusIndicator } from '~/ui';
import Tab from './Tab';
import styles from './tabBar.css';
@ -66,15 +65,6 @@ class TabBar extends Component {
</div>
</Link>
{ this.renderTabItems() }
<Tooltip
className={ styles.tabbarTooltip }
text={
<FormattedMessage
id='tabBar.tooltip.overview'
defaultMessage='navigate between the different parts and views of the application, switching between an account view, token view and decentralized application view'
/>
}
/>
</div>
<ToolbarGroup className={ styles.last }>
<div />

View File

@ -18,27 +18,14 @@ import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import UpgradeStore from '~/modals/UpgradeParity/store';
import Connection from '../Connection';
import ParityBar from '../ParityBar';
import SyncWarning, { showSyncWarning } from '../SyncWarning';
import Snackbar from './Snackbar';
import Container from './Container';
import DappContainer from './DappContainer';
import Extension from './Extension';
import FrameError from './FrameError';
import Status from './Status';
import Store from './store';
import TabBar from './TabBar';
import Requests from './Requests';
import styles from './application.css';
const inFrame = window.parent !== window && window.parent.frames.length !== 0;
const doShowSyncWarning = showSyncWarning();
@observer
class Application extends Component {
static contextTypes = {
@ -53,11 +40,9 @@ class Application extends Component {
}
store = new Store(this.context.api);
upgradeStore = UpgradeStore.get(this.context.api);
render () {
const [root] = (window.location.hash || '').replace('#/', '').split('/');
const isMinimized = root === 'app' || root === 'web';
if (process.env.NODE_ENV !== 'production' && root === 'playground') {
return (
@ -69,47 +54,20 @@ class Application extends Component {
return (
<div>
{
inFrame
? <FrameError />
: null
}
{
isMinimized
? this.renderMinimized()
: this.renderApp()
}
{
doShowSyncWarning
? (<SyncWarning />)
: null
}
<Connection />
<Requests />
<ParityBar dapp={ isMinimized } />
{ this.renderApp() }
</div>
);
}
renderApp () {
const { blockNumber, children, pending } = this.props;
const { children, pending } = this.props;
return (
<Container
upgradeStore={ this.upgradeStore }
onCloseFirstRun={ this.store.closeFirstrun }
showFirstRun={ this.store.firstrunVisible }
>
<Container>
<TabBar pending={ pending } />
<div className={ styles.content }>
{ children }
</div>
{
blockNumber
? <Status upgradeStore={ this.upgradeStore } />
: null
}
<Extension />
<Snackbar />
</Container>
);

View File

@ -17,7 +17,7 @@
import React from 'react';
import imagesEthcoreBlock from '~/../assets/images/parity-logo-white-no-text.svg';
import { AccountsIcon, AddressesIcon, AppsIcon, ContactsIcon, FingerprintIcon, SettingsIcon } from '~/ui/Icons';
import { AccountsIcon, AddressesIcon, ContactsIcon, FingerprintIcon, SettingsIcon } from '~/ui/Icons';
import styles from './views.css';
@ -50,13 +50,6 @@ const defaultViews = {
value: 'address'
},
apps: {
active: true,
icon: <AppsIcon />,
route: '/apps',
value: 'app'
},
contracts: {
active: false,
onlyPersonal: true,

View File

@ -91,17 +91,6 @@ class Views extends Component {
/>
)
}
{
this.renderView('apps',
<FormattedMessage
id='settings.views.apps.label'
/>,
<FormattedMessage
id='settings.views.apps.description'
defaultMessage='Decentralized applications that interact with the underlying network. Add applications, manage you application portfolio and interact with application from around the network.'
/>
)
}
{
this.renderView('contracts',
<FormattedMessage

View File

@ -48,8 +48,9 @@ const entry = isEmbed
module.exports = {
cache: !isProd,
devtool: isProd ? '#hidden-source-map' : '#source-map',
devtool: isProd
? false
: '#source-map',
context: path.join(__dirname, '../src'),
entry: entry,
output: {
@ -67,7 +68,7 @@ module.exports = {
},
{
test: /\.js$/,
include: /node_modules\/(material-chip-input|ethereumjs-tx|@parity\/wordlist)/,
include: /(material-chip-input|ethereumjs-tx)/,
use: 'babel-loader'
},
{
@ -214,6 +215,7 @@ module.exports = {
new CopyWebpackPlugin([
{ from: './error_pages.css', to: 'styles.css' },
{ from: './manifest.json', to: 'manifest.json' },
{ from: 'dapps/static' }
], {})
);

View File

@ -62,7 +62,7 @@ module.exports = {
},
{
test: /\.js$/,
include: /node_modules\/(ethereumjs-tx|@parity\/wordlist)/,
include: /(ethereumjs-tx|wordlist)/,
use: 'babel-loader'
},
{

View File

@ -65,7 +65,7 @@ module.exports = {
},
{
test: /\.js$/,
include: /node_modules\/(ethereumjs-tx|@parity\/wordlist)/,
include: /(ethereumjs-tx|wordlist)/,
use: 'babel-loader'
}
]

File diff suppressed because it is too large Load Diff

3466
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "Parity",
"version": "1.9.5",
"version": "1.9.10",
"main": "src/index.parity.js",
"jsnext:main": "src/index.parity.js",
"author": "Parity Team <admin@parity.io>",
@ -21,13 +21,13 @@
"Parity"
],
"scripts": {
"build": "npm run build:lib && npm run build:app && npm run build:embed",
"build:app": "webpack --progress --config webpack/app",
"build:lib": "webpack --progress --config webpack/libraries",
"build": "npm run build:inject && npm run build:app && npm run build:embed",
"build:app": "webpack --config webpack/app",
"build:inject": "webpack --config webpack/inject",
"build:embed": "cross-env EMBED=1 node webpack/embed",
"build:i18n": "npm run clean && npm run build && babel-node ./scripts/build-i18n.js",
"ci:build": "cross-env NODE_ENV=production npm run build",
"clean": "rimraf ./.build ./.coverage ./.happypack ./build ./node_modules/.cache",
"clean": "rimraf ./.build ./.coverage ./.happypack ./build",
"coveralls": "npm run testCoverage && coveralls < coverage/lcov.info",
"lint": "npm run lint:css && npm run lint:js",
"lint:cached": "npm run lint:css && npm run lint:js:cached",
@ -37,14 +37,11 @@
"lint:js": "eslint --ignore-path .gitignore ./src/",
"lint:js:cached": "eslint --cache --ignore-path .gitignore ./src/",
"lint:js:fix": "eslint --fix --ignore-path .gitignore ./src/",
"start": "npm run clean && npm install && npm run build:lib && npm run start:app",
"start": "npm run clean && npm install && npm run build:inject && npm run start:app",
"start:app": "node webpack/dev.server",
"start:electron": "npm run build:app && electron .build/",
"test": "cross-env NODE_ENV=test mocha --compilers ejs:ejsify 'src/**/*.spec.js'",
"test:coverage": "cross-env NODE_ENV=test istanbul cover _mocha -- --compilers ejs:ejsify 'src/**/*.spec.js'",
"test:e2e": "cross-env NODE_ENV=test mocha 'src/**/*.e2e.js'",
"test:npm": "(cd .npmjs && npm i) && node test/npmParity && node test/npmJsonRpc && (rimraf .npmjs/node_modules)",
"prepush": "npm run lint:cached"
"test:coverage": "cross-env NODE_ENV=test istanbul cover _mocha -- --compilers ejs:ejsify 'src/**/*.spec.js'"
},
"devDependencies": {
"babel-cli": "6.26.0",
@ -94,9 +91,7 @@
"html-loader": "0.4.4",
"html-webpack-plugin": "2.30.1",
"http-proxy-middleware": "0.17.3",
"husky": "0.13.1",
"ignore-styles": "5.0.1",
"image-webpack-loader": "3.2.0",
"istanbul": "1.0.0-alpha.2",
"jsdom": "9.11.0",
"json-loader": "0.5.4",
@ -135,50 +130,33 @@
"yargs": "6.6.0"
},
"dependencies": {
"@parity/abi": "^2",
"@parity/api": "^2",
"@parity/jsonrpc": "^2",
"@parity/etherscan": "^2",
"@parity/ledger": "^2",
"@parity/shapeshift": "^2",
"@parity/shared": "^2",
"@parity/ui": "^2",
"@parity/plugin-signer-account": "paritytech/plugin-signer-account",
"@parity/plugin-signer-default": "paritytech/plugin-signer-default",
"@parity/plugin-signer-hardware": "paritytech/plugin-signer-hardware",
"@parity/plugin-signer-qr": "paritytech/plugin-signer-qr",
"@parity/dapp-account": "paritytech/dapp-account",
"@parity/api": "2.1.x",
"@parity/dapp-accounts": "paritytech/dapp-accounts",
"@parity/dapp-address": "paritytech/dapp-address",
"@parity/dapp-addresses": "paritytech/dapp-addresses",
"@parity/dapp-chaindeploy": "paritytech/dapp-chaindeploy",
"@parity/dapp-contract": "paritytech/dapp-contract",
"@parity/dapp-contracts": "paritytech/dapp-contracts",
"@parity/dapp-console": "paritytech/dapp-console",
"@parity/dapp-dapp-accounts": "paritytech/dapp-dapp-accounts",
"@parity/dapp-dapp-methods": "paritytech/dapp-dapp-methods",
"@parity/dapp-dapp-visible": "paritytech/dapp-dapp-visible",
"@parity/dapp-dappreg": "paritytech/dapp-dappreg",
"@parity/dapp-develop": "paritytech/dapp-develop",
"@parity/dapp-githubhint": "paritytech/dapp-githubhint",
"@parity/dapp-home": "paritytech/dapp-home",
"@parity/dapp-localtx": "paritytech/dapp-localtx",
"@parity/dapp-playground": "paritytech/dapp-playground",
"@parity/dapp-registry": "paritytech/dapp-registry",
"@parity/dapp-settings": "paritytech/dapp-settings",
"@parity/dapp-signaturereg": "paritytech/dapp-signaturereg",
"@parity/dapp-signer": "paritytech/dapp-signer",
"@parity/dapp-status": "paritytech/dapp-status",
"@parity/dapp-tokendeploy": "paritytech/dapp-tokendeploy",
"@parity/dapp-tokenreg": "paritytech/dapp-tokenreg",
"@parity/dapp-vaults": "paritytech/dapp-vaults",
"@parity/dapp-wallet": "paritytech/dapp-wallet",
"@parity/dapp-web": "paritytech/dapp-web",
"isomorphic-fetch": "2.2.1",
"@parity/plugin-signer-account": "paritytech/plugin-signer-account",
"@parity/plugin-signer-default": "paritytech/plugin-signer-default",
"@parity/plugin-signer-hardware": "paritytech/plugin-signer-hardware",
"@parity/plugin-signer-qr": "paritytech/plugin-signer-qr",
"@parity/shared": "2.2.x",
"@parity/ui": "2.2.x",
"keythereum": "1.0.2",
"lodash.flatten": "4.4.0",
"lodash.omitby": "4.6.0",
"lodash.throttle": "4.1.1",
"lodash.uniq": "4.5.0",
"oo7": "paritytech/oo7#34fdb5991f4e59b2cf84260cab48cec9a57d88c0",
"material-ui": "0.16.5",
"prop-types": "15.5.10",
"react": "15.6.1",
"react-dom": "15.6.1",
@ -189,7 +167,6 @@
"redux": "3.6.0",
"solc": "ngotchac/solc-js",
"store": "1.3.20",
"web3": "0.17.0-beta",
"whatwg-fetch": "2.0.1"
"web3": "0.17.0-beta"
}
}

48
js/scripts/push-cargo.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/bash
set -e
# variables
UTCDATE=`date -u "+%Y%m%d-%H%M%S"`
BRANCH=$CI_BUILD_REF_NAME
GIT_PARITY="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/parity.git"
GITLOG=./.git/.git-release.log
# setup the git user defaults for the current repo
function setup_git_user {
git config push.default simple
git config merge.ours.driver true
git config user.email "$GITHUB_EMAIL"
git config user.name "GitLab Build Bot"
}
echo "*** [cargo] Setting up GitHub config for parity"
setup_git_user
git remote set-url origin $GIT_PARITY
git reset --hard origin/$BRANCH 2>$GITLOG
git submodule update
if [ "$BRANCH" == "master" ]; then
cd js
echo "*** [cargo] Bumping package.json patch version"
npm --no-git-tag-version version
npm version patch
cd ..
git add js
fi
echo "*** [cargo] Updating cargo parity-ui-precompiled"
sed -i "/^parity-ui-precompiled/ { s/branch = \".*\"/branch = \"$BRANCH\"/g; }" dapps/ui/Cargo.toml
cargo update -p parity-ui-precompiled
cargo update -p parity-ui-old-precompiled
echo "*** [cargo] Committing updated files"
git add dapps/ui/Cargo.toml
git add Cargo.lock
git commit -m "[ci skip] js-precompiled $UTCDATE"
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
# exit with exit code
exit 0

52
js/scripts/push-precompiled.sh Executable file
View File

@ -0,0 +1,52 @@
#!/bin/bash
set -e
# variables
UTCDATE=`date -u "+%Y%m%d-%H%M%S"`
BRANCH=$CI_BUILD_REF_NAME
GIT_JS_PRECOMPILED="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/js-precompiled.git"
BASEDIR=`dirname $0`
GITLOG=./.git/.git-release.log
# setup the git user defaults for the current repo
function setup_git_user {
git config push.default simple
git config merge.ours.driver true
git config user.email "$GITHUB_EMAIL"
git config user.name "GitLab Build Bot"
}
# change into the build directory
pushd $BASEDIR
cd ../.dist
# add local files and send it up
echo "*** [v2 precompiled] Setting up GitHub config"
rm -rf ./.git
git init
setup_git_user
echo "*** [v2 precompiled] Checking out $BRANCH branch"
git remote add origin $GIT_JS_PRECOMPILED
git fetch origin 2>$GITLOG
git checkout -b $BRANCH
echo "*** [v2 precompiled] Committing compiled files for $UTCDATE"
mv build ../build.new
git add .
git commit -m "$UTCDATE [update]"
git merge origin/$BRANCH -X ours --commit -m "$UTCDATE [merge]"
git rm -r build
rm -rf build
git commit -m "$UTCDATE [cleanup]"
mv ../build.new build
git add .
git commit -m "$UTCDATE [release]"
echo "*** [v2 precompiled] Merging remote"
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
popd
# exit with exit code
exit 0

View File

@ -1,103 +0,0 @@
#!/bin/bash
set -e
# variables
UTCDATE=`date -u "+%Y%m%d-%H%M%S"`
PACKAGES=()
BRANCH=$CI_BUILD_REF_NAME
GIT_JS_PRECOMPILED="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/js-precompiled.git"
GIT_PARITY="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/parity.git"
# setup the git user defaults for the current repo
function setup_git_user {
git config push.default simple
git config merge.ours.driver true
git config user.email "$GITHUB_EMAIL"
git config user.name "GitLab Build Bot"
}
# change into the build directory
BASEDIR=`dirname $0`
GITLOG=./.git/gitcommand.log
pushd $BASEDIR
cd ../.dist
# add local files and send it up
echo "*** Setting up GitHub config for js-precompiled"
rm -rf ./.git
git init
setup_git_user
echo "*** Checking out $BRANCH branch"
git remote add origin $GIT_JS_PRECOMPILED
git fetch origin 2>$GITLOG
git checkout -b $BRANCH
echo "*** Committing compiled files for $UTCDATE"
mv build ../build.new
git add .
git commit -m "$UTCDATE [update]"
git merge origin/$BRANCH -X ours --commit -m "$UTCDATE [merge]"
git rm -r build
rm -rf build
git commit -m "$UTCDATE [cleanup]"
mv ../build.new build
git add .
git commit -m "$UTCDATE [release]"
echo "*** Merging remote"
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
PRECOMPILED_HASH=`git rev-parse HEAD`
# move to root
cd ../..
echo "*** Setting up GitHub config for parity"
setup_git_user
git remote set-url origin $GIT_PARITY
git reset --hard origin/$BRANCH 2>$GITLOG
if [ "$BRANCH" == "master" ]; then
cd js
echo "*** Bumping package.json patch version"
npm --no-git-tag-version version
npm version patch
echo "*** Building packages for npmjs"
echo "$NPM_TOKEN" >> ~/.npmrc
for PACKAGE in ${PACKAGES[@]}
do
echo "*** Building $PACKAGE"
LIBRARY=$PACKAGE npm run ci:build:npm
DIRECTORY=.npmjs/$PACKAGE
echo "*** Publishing $PACKAGE from $DIRECTORY"
cd $DIRECTORY
npm publish --access public || true
cd ../..
done
cd ..
fi
echo "*** Updating cargo parity-ui-precompiled#$PRECOMPILED_HASH"
git submodule update
sed -i "/^parity-ui-precompiled/ { s/branch = \".*\"/branch = \"$BRANCH\"/g; }" dapps/ui/Cargo.toml
cargo update -p parity-ui-precompiled
# --precise "$PRECOMPILED_HASH"
echo "*** Committing updated files"
git add js
git add dapps/ui/Cargo.toml
git add Cargo.lock
git commit -m "[ci skip] js-precompiled $UTCDATE"
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
# back to root
echo "*** Release completed"
popd
# exit with exit code
exit 0

View File

@ -1 +1 @@
// test script 14
// test script 19

View File

@ -20,9 +20,9 @@ import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import HardwareStore from '@parity/shared/mobx/hardwareStore';
import UpgradeStore from '@parity/shared/mobx/upgradeParity';
import Errors from '@parity/ui/Errors';
import HardwareStore from '@parity/shared/lib/mobx/hardwareStore';
import UpgradeStore from '@parity/shared/lib/mobx/upgradeParity';
import Errors from '@parity/ui/lib/Errors';
import Connection from '../Connection';
import DappRequests from '../DappRequests';
@ -145,11 +145,9 @@ class Application extends Component {
function mapStateToProps (state) {
const { blockNumber } = state.nodeStatus;
const { hasAccounts } = state.personal;
return {
blockNumber,
hasAccounts
blockNumber
};
}

View File

@ -19,9 +19,9 @@ import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import GradientBg from '@parity/ui/GradientBg';
import Input from '@parity/ui/Form/Input';
import { CompareIcon, ComputerIcon, DashboardIcon, VpnIcon } from '@parity/ui/Icons';
import GradientBg from '@parity/ui/lib/GradientBg';
import Input from '@parity/ui/lib/Form/Input';
import { CompareIcon, ComputerIcon, DashboardIcon, VpnIcon } from '@parity/ui/lib/Icons';
import styles from './connection.css';

View File

@ -20,11 +20,10 @@ import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import Api from '@parity/api';
import builtinDapps from '@parity/shared/config/dappsBuiltin.json';
import viewsDapps from '@parity/shared/config/dappsViews.json';
import DappsStore from '@parity/shared/mobx/dappsStore';
import HistoryStore from '@parity/shared/mobx/historyStore';
// import { Bond } from 'oo7';
import builtinDapps from '@parity/shared/lib/config/dappsBuiltin.json';
import viewsDapps from '@parity/shared/lib/config/dappsViews.json';
import DappsStore from '@parity/shared/lib/mobx/dappsStore';
import HistoryStore from '@parity/shared/lib/mobx/historyStore';
import styles from './dapp.css';
@ -163,6 +162,5 @@ export default class Dapp extends Component {
const frame = document.getElementById('dappFrame');
frame.style.opacity = 1;
// frame.contentWindow.injectedBondCache = Bond.cache;
}
}

View File

@ -18,9 +18,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import Button from '@parity/ui/Button';
import Button from '@parity/ui/lib/Button';
import DappsStore from '@parity/shared/mobx/dappsStore';
import DappsStore from '@parity/shared/lib/mobx/dappsStore';
export default function Request ({ appId, className, approveRequest, denyRequest, queueId, request: { from, method } }) {
const _onApprove = () => approveRequest(queueId, false);

View File

@ -23,8 +23,8 @@ $backgroundTwo: #e57a00;
position: fixed;
left: 0;
right: 0;
top: 2.75em;
z-index: 760; /* sits above requests */
bottom: 0;
z-index: 1001; /* sits above sync warning */
.request {
align-items: center;

View File

@ -17,7 +17,7 @@
import { action, computed, observable } from 'mobx';
import store from 'store';
import { sha3 } from '@parity/api/util/sha3';
import { sha3 } from '@parity/api/lib/util/sha3';
import filteredRequests from './filteredRequests';

View File

@ -21,12 +21,12 @@ import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import DappCard from '@parity/ui/DappCard';
import Checkbox from '@parity/ui/Form/Checkbox';
import Page from '@parity/ui/Page';
import SectionList from '@parity/ui/SectionList';
import DappCard from '@parity/ui/lib/DappCard';
import Checkbox from '@parity/ui/lib/Form/Checkbox';
import Page from '@parity/ui/lib/Page';
import SectionList from '@parity/ui/lib/SectionList';
import DappsStore from '@parity/shared/mobx/dappsStore';
import DappsStore from '@parity/shared/lib/mobx/dappsStore';
import styles from './dapps.css';
@ -85,8 +85,8 @@ class Dapps extends Component {
/>
}
>
{ this.renderList(this.store.visibleViews) }
{ this.renderList(this.store.visibleLocal) }
{ this.renderList(this.store.visibleViews) }
{ this.renderList(this.store.visibleBuiltin) }
{ this.renderList(this.store.visibleNetwork, externalOverlay) }
</Page>

View File

@ -18,10 +18,10 @@ import { observer } from 'mobx-react';
import React, { Component } from 'react';
import { FormattedMessage } from 'react-intl';
import Button from '@parity/ui/Button';
import { CloseIcon, CheckIcon } from '@parity/ui/Icons';
import Button from '@parity/ui/lib/Button';
import { CloseIcon, CheckIcon } from '@parity/ui/lib/Icons';
import Store from '@parity/shared/mobx/extensionStore';
import Store from '@parity/shared/lib/mobx/extensionStore';
import styles from './extension.css';
@observer

View File

@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import ReactMarkdown from 'react-markdown';
import Checkbox from '@parity/ui/Form/Checkbox';
import Checkbox from '@parity/ui/lib/Form/Checkbox';
import styles from '../firstRun.css';

View File

@ -21,11 +21,11 @@ import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { createIdentityImg } from '@parity/api/util/identity';
import { newError } from '@parity/shared/redux/actions';
import Button from '@parity/ui/Button';
import Portal from '@parity/ui/Portal';
import { CheckIcon, DoneIcon, NextIcon, PrintIcon, ReplayIcon } from '@parity/ui/Icons';
import { createIdentityImg } from '@parity/api/lib/util/identity';
import { newError } from '@parity/shared/lib/redux/actions';
import Button from '@parity/ui/lib/Button';
import Portal from '@parity/ui/lib/Portal';
import { CheckIcon, DoneIcon, NextIcon, PrintIcon, ReplayIcon } from '@parity/ui/lib/Icons';
import ParityLogo from '@parity/shared/assets/images/parity-logo-black-no-text.svg';
import { NewAccount, AccountDetails } from '@parity/dapp-accounts/src/CreateAccount';

View File

@ -189,9 +189,9 @@ $modalZ: 10001;
}
.header {
/* height: 2em; */
padding: 0.5em 1em;
border-radius: 4px 4px 0 0;
margin-bottom: 0;
padding: 0.5em 1em;
&::after {
clear: both;

View File

@ -24,16 +24,16 @@ import { Link } from 'react-router';
import { connect } from 'react-redux';
import store from 'store';
import AccountCard from '@parity/ui/AccountCard';
import Button from '@parity/ui/Button';
import ContainerTitle from '@parity/ui/Container/Title';
import IdentityIcon from '@parity/ui/IdentityIcon';
import GradientBg from '@parity/ui/GradientBg';
import SelectionList from '@parity/ui/SelectionList';
import SignerPending from '@parity/ui/SignerPending';
import { CancelIcon } from '@parity/ui/Icons';
import AccountCard from '@parity/ui/lib/AccountCard';
import Button from '@parity/ui/lib/Button';
import ContainerTitle from '@parity/ui/lib/Container/Title';
import IdentityIcon from '@parity/ui/lib/IdentityIcon';
import GradientBg from '@parity/ui/lib/GradientBg';
import SelectionList from '@parity/ui/lib/SelectionList';
import SignerPending from '@parity/ui/lib/SignerPending';
import { CancelIcon } from '@parity/ui/lib/Icons';
import DappsStore from '@parity/shared/mobx/dappsStore';
import DappsStore from '@parity/shared/lib/mobx/dappsStore';
import Signer from '../Signer/Embedded';
import AccountStore from './accountStore';

View File

@ -18,7 +18,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import GradientBg from '@parity/ui/GradientBg';
import GradientBg from '@parity/ui/lib/GradientBg';
import styles from './pinMatrix.css';

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