Update with latest dapps

This commit is contained in:
Jaco Greeff 2017-08-02 17:16:26 +02:00
parent 45f91facf1
commit 696089c479
54 changed files with 314 additions and 4529 deletions

601
js/package-lock.json generated
View File

@ -13,10 +13,10 @@
}
},
"@parity/api": {
"version": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"version": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"requires": {
"@parity/abi": "github:paritytech/js-abi#414765a476d88b6fb9f3398c99a946021957d07a",
"@parity/jsonrpc": "github:paritytech/js-jsonrpc#89a6e441370f55d8fe995e27007f60da29b6672b",
"@parity/jsonrpc": "github:paritytech/js-jsonrpc#e271aa9d158fa90a57cc4e6b4ad2993f9fbb8ad4",
"@parity/wordlist": "1.1.0",
"bignumber.js": "3.0.1",
"blockies": "0.0.2",
@ -47,14 +47,14 @@
"@parity/dapp-account": {
"version": "github:paritytech/dapp-account#be1279faf2ac430ec44ab2d4769ca68eacdac9b6",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-accounts": "github:paritytech/dapp-accounts#235036f3e726e206391b15cf8c3e9d8956bc121d",
"@parity/dapp-address": "github:paritytech/dapp-address#8e1431a2e57d2fe8805fc184848148f8dce34210",
"@parity/dapp-vaults": "github:paritytech/dapp-vaults#de86d2bf21f1d0283b7f9fd7b3159a280e321818",
"@parity/parity.js": "1.8.7",
"@parity/shapeshift": "github:paritytech/js-shapeshift#59d71436b678390a3abdea37d58b5ff06edfd750",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/shapeshift": "github:paritytech/js-shapeshift#9de4790c8f6ac282e10af5738dd0a687a97fc419",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"happypack": "3.1.0",
"lodash": "4.17.2",
"oo7": "0.5.3",
@ -69,10 +69,10 @@
"@parity/dapp-accounts": {
"version": "github:paritytech/dapp-accounts#235036f3e726e206391b15cf8c3e9d8956bc121d",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-vaults": "github:paritytech/dapp-vaults#de86d2bf21f1d0283b7f9fd7b3159a280e321818",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"file-saver": "1.3.3",
"react": "15.6.1",
"react-dom": "15.6.1",
@ -85,29 +85,29 @@
"@parity/dapp-address": {
"version": "github:paritytech/dapp-address#8e1431a2e57d2fe8805fc184848148f8dce34210",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-account": "github:paritytech/dapp-account#be1279faf2ac430ec44ab2d4769ca68eacdac9b6",
"@parity/dapp-addresses": "github:paritytech/dapp-addresses#b1ecac83d0d2921ad882695dc0f4fbfc7e442cf2",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-addresses": {
"version": "github:paritytech/dapp-addresses#b1ecac83d0d2921ad882695dc0f4fbfc7e442cf2",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-accounts": "github:paritytech/dapp-accounts#235036f3e726e206391b15cf8c3e9d8956bc121d",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-chaindeploy": {
"version": "github:paritytech/dapp-chaindeploy#dfb12d38e9c0c8a540be0a51681a36685b812963",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"react": "15.6.1",
"react-dom": "15.6.1"
}
@ -115,51 +115,60 @@
"@parity/dapp-contract": {
"version": "github:paritytech/dapp-contract#311caba0c0ae14ec84c2cb6ea395990dd4af5d60",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-account": "github:paritytech/dapp-account#be1279faf2ac430ec44ab2d4769ca68eacdac9b6",
"@parity/dapp-address": "github:paritytech/dapp-address#8e1431a2e57d2fe8805fc184848148f8dce34210",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-contracts": {
"version": "github:paritytech/dapp-contracts#d96a451a540cb46d4fc1300b90c91ebf1421213d",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-account": "github:paritytech/dapp-account#be1279faf2ac430ec44ab2d4769ca68eacdac9b6",
"@parity/dapp-accounts": "github:paritytech/dapp-accounts#235036f3e726e206391b15cf8c3e9d8956bc121d",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-dapp-accounts": {
"version": "github:paritytech/dapp-dapp-accounts#c2e748cfcbd3e4deb09cdf1bab5634576b961010",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-dapp-methods": {
"version": "github:paritytech/dapp-dapp-methods#c38f3f7ad253fe675f24ec442bf8d763325aa058",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-dappreg": {
"version": "github:paritytech/dapp-dappreg#698d4083d88f4ea83a358bb91aa088a5b270f03c",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-develop": {
"version": "github:paritytech/dapp-develop#899c49dd7d384ebd1ebcbf3c42291acbdc257c10",
"version": "github:paritytech/dapp-develop#0af0cc92d3daf7260d0ea294a9519b809c6f00ac",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-contracts": "github:paritytech/dapp-contracts#d96a451a540cb46d4fc1300b90c91ebf1421213d",
"@parity/parity.js": "1.8.7",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"oo7": "0.5.3",
"oo7-parity": "0.6.8",
"oo7-react": "0.4.5",
@ -168,210 +177,162 @@
}
},
"@parity/dapp-githubhint": {
"version": "github:paritytech/dapp-githubhint#10b394b8cd4f90bc83b9b0da7dfbe034f8cd9f33",
"version": "github:paritytech/dapp-githubhint#bcc95b587d428f3dd7ea329f4dae5b2eb904f07f",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/shared": "github:paritytech/js-shared#9bb1d291d8752a827613889498e380fcd3afa8da",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"moment": "2.17.0",
"react": "15.6.1",
"react-dom": "15.6.1",
"react-tap-event-plugin": "2.0.1"
}
},
"@parity/dapp-home": {
"version": "github:paritytech/dapp-home#f4f7f0044f68641f710d96bee244c0f41f780e80",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-web": "github:paritytech/dapp-web#a431e9d4177a4a19d85fc1adc1539368f3808a8b",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"react-markdown": "2.4.4",
"recharts": "0.15.2"
},
"dependencies": {
"@parity/api": {
"version": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"react-markdown": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-2.4.4.tgz",
"integrity": "sha1-JtglQ40pLnym4pL+diAeHb8s/u4=",
"requires": {
"@parity/abi": "github:paritytech/js-abi#414765a476d88b6fb9f3398c99a946021957d07a",
"@parity/jsonrpc": "github:paritytech/js-jsonrpc#89a6e441370f55d8fe995e27007f60da29b6672b",
"@parity/wordlist": "1.1.0",
"bignumber.js": "3.0.1",
"blockies": "0.0.2",
"es6-error": "4.0.0",
"ethereumjs-tx": "1.3.3",
"eventemitter3": "2.0.3",
"isomorphic-fetch": "2.2.1",
"js-sha3": "0.5.5",
"keythereum": "0.4.6",
"lodash": "4.17.4",
"node-fetch": "1.6.3",
"secp256k1": "3.2.5",
"store": "2.0.12"
"commonmark": "0.24.0",
"commonmark-react-renderer": "4.3.3",
"in-publish": "2.0.0"
}
},
"@parity/ledger": {
"version": "github:paritytech/js-ledger#c363adfb9192aa56b7b498b0ad90bc4032bcd6ab",
"requires": {
"u2f-api": "0.0.9",
"u2f-api-polyfill": "0.4.3"
}
},
"@parity/shared": {
"version": "github:paritytech/js-shared#9bb1d291d8752a827613889498e380fcd3afa8da",
"requires": {
"@parity/ledger": "github:paritytech/js-ledger#c363adfb9192aa56b7b498b0ad90bc4032bcd6ab",
"loglevel": "1.4.1",
"mobx": "2.6.4",
"mobx-react": "4.0.3",
"promise-worker": "1.1.1",
"push.js": "0.0.11",
"react-redux": "4.4.6",
"redux": "3.6.0",
"redux-actions": "1.1.0",
"redux-thunk": "2.1.0",
"scryptsy": "2.0.0",
"serviceworker-webpack-plugin": "0.2.0",
"solc": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818",
"worker-loader": "0.8.1",
"yargs": "6.6.0"
}
},
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
},
"store": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz",
"integrity": "sha1-jFNOKguDH3K3X8XxEZhXxE711ZM="
}
}
},
"@parity/dapp-localtx": {
"version": "github:paritytech/dapp-localtx#6d20868fadb820aff210097fac110e50cb966dc5",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-playground": {
"version": "github:paritytech/dapp-playground#a43f3b3bfe8faa83ae00b67bf5b0eee26924f2f3",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-registry": {
"version": "github:paritytech/dapp-registry#2426ae6a1c447a18dfa7cc3c6504904426cd41ae",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"material-ui": "0.16.5",
"recharts": "0.15.2"
}
},
"@parity/dapp-settings": {
"version": "github:paritytech/dapp-settings#b5e2877825401f73945b8e82f7a383d118adadd6",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-signaturereg": {
"version": "github:paritytech/dapp-signaturereg#79b17073c1034b2c7f515833475bc374a8c84692",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"moment": "2.17.0",
"react": "15.6.1",
"react-dom": "15.6.1",
"react-tap-event-plugin": "2.0.1"
}
},
"@parity/dapp-signer": {
"version": "github:paritytech/dapp-signer#2ea607e6c994513d8dbe72dc9934cdb360f8c269",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-status": {
"version": "github:paritytech/dapp-status#2f2d8de2d86d1fff693795a1897e40876397ed8b",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"bytes": "2.4.0",
"format-number": "2.0.1",
"recharts": "0.15.2"
}
},
"@parity/dapp-tokendeploy": {
"version": "github:paritytech/dapp-tokendeploy#cc83829402471eba78e5c6d46394feedee3ea619",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-tokenreg": {
"version": "github:paritytech/dapp-tokenreg#67f6dfb798e68593f688b67935e1a4b223fa4c63",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"material-ui": "0.16.5",
"react": "15.6.1",
"react-dom": "15.6.1",
"react-tap-event-plugin": "2.0.1",
"recharts": "0.15.2"
}
},
"@parity/dapp-vaults": {
"version": "github:paritytech/dapp-vaults#de86d2bf21f1d0283b7f9fd7b3159a280e321818",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/shared": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"@parity/ui": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-wallet": {
"version": "github:paritytech/dapp-wallet#711f4381cef112e8d11f0cd6cbfa15d87eea0b54",
"version": "github:paritytech/dapp-wallet#22315cb2dae87d34be1f7cb3b3bf26ca8d7e2dab",
"requires": {
"@parity/api": "github:paritytech/js-api#ade4a6750292a2918676039ea53eea20c4c728bc",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/dapp-account": "github:paritytech/dapp-account#be1279faf2ac430ec44ab2d4769ca68eacdac9b6",
"@parity/dapp-address": "github:paritytech/dapp-address#8e1431a2e57d2fe8805fc184848148f8dce34210",
"@parity/shared": "github:paritytech/js-shared#9bb1d291d8752a827613889498e380fcd3afa8da",
"@parity/ui": "github:paritytech/js-ui#037782bd16e8abf1c169143aa61749a44b94489b",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"recharts": "0.15.2"
}
},
"@parity/dapp-web": {
"version": "github:paritytech/dapp-web#a431e9d4177a4a19d85fc1adc1539368f3808a8b",
"requires": {
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"@parity/ui": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"base32.js": "0.1.0",
"recharts": "0.15.2"
},
"dependencies": {
"@parity/shared": {
"version": "github:paritytech/js-shared#9bb1d291d8752a827613889498e380fcd3afa8da",
"requires": {
"@parity/ledger": "github:paritytech/js-ledger#c363adfb9192aa56b7b498b0ad90bc4032bcd6ab",
"loglevel": "1.4.1",
"mobx": "2.6.4",
"mobx-react": "4.0.3",
"promise-worker": "1.1.1",
"push.js": "0.0.11",
"react-redux": "4.4.6",
"redux": "3.6.0",
"redux-actions": "1.1.0",
"redux-thunk": "2.1.0",
"scryptsy": "2.0.0",
"serviceworker-webpack-plugin": "0.2.0",
"solc": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818",
"worker-loader": "0.8.1",
"yargs": "6.6.0"
}
},
"@parity/ui": {
"version": "github:paritytech/js-ui#037782bd16e8abf1c169143aa61749a44b94489b",
"requires": {
"@parity/api": "github:paritytech/js-api#1c7cc5561c4e8db0d0b58f22d8bc8baa243909a5",
"@parity/etherscan": "github:paritytech/js-etherscan#efe859ac7d2a8a3cc05e01c689b7fa58f47f8b87",
"@parity/shared": "github:paritytech/js-shared#a83c71946d30d5b3bf976860a676add29c48ee24",
"bignumber.js": "3.0.1",
"brace": "0.9.0",
"date-difference": "1.0.0",
"eventemitter3": "2.0.3",
"file-saver": "1.3.3",
"geopattern": "1.2.3",
"js-sha3": "0.5.5",
"keycode": "2.1.9",
"lodash": "4.17.2",
"mobx": "2.6.4",
"mobx-react": "4.0.3",
"moment": "2.17.0",
"qrcode-generator": "1.2.0",
"react": "15.6.1",
"react-ace": "4.1.0",
"react-copy-to-clipboard": "4.2.3",
"react-datetime": "2.8.10",
"react-dom": "15.6.1",
"react-dropzone": "3.7.3",
"react-event-listener": "0.4.5",
"react-intl": "2.1.5",
"react-portal": "3.0.0",
"react-qr-reader": "1.1.3",
"react-router": "3.0.0",
"react-router-redux": "4.0.7",
"react-tap-event-plugin": "2.0.1",
"react-tooltip": "3.2.2",
"recharts": "0.15.2",
"redux": "3.6.0",
"semantic-ui-css": "2.2.11",
"semantic-ui-react": "0.71.2",
"zxcvbn": "4.4.1"
},
"dependencies": {
"@parity/api": {
"version": "github:paritytech/js-api#1c7cc5561c4e8db0d0b58f22d8bc8baa243909a5",
"requires": {
"@parity/abi": "github:paritytech/js-abi#414765a476d88b6fb9f3398c99a946021957d07a",
"@parity/jsonrpc": "github:paritytech/js-jsonrpc#89a6e441370f55d8fe995e27007f60da29b6672b",
"@parity/wordlist": "1.1.0",
"bignumber.js": "3.0.1",
"blockies": "0.0.2",
"es6-error": "4.0.0",
"ethereumjs-tx": "1.3.3",
"eventemitter3": "2.0.3",
"isomorphic-fetch": "2.2.1",
"js-sha3": "0.5.5",
"keythereum": "0.4.6",
"lodash": "4.17.4",
"node-fetch": "1.6.3",
"secp256k1": "3.2.5",
"store": "2.0.12"
},
"dependencies": {
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
}
}
},
"@parity/shared": {
"version": "github:paritytech/js-shared#a83c71946d30d5b3bf976860a676add29c48ee24",
"requires": {
"mobx": "2.6.4",
"mobx-react": "4.0.3",
"push.js": "0.0.11",
"react-redux": "4.4.6",
"redux": "3.6.0",
"redux-actions": "1.1.0",
"redux-thunk": "2.1.0",
"scryptsy": "2.0.0",
"solc": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818",
"yargs": "6.6.0"
}
}
}
},
"store": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz",
"integrity": "sha1-jFNOKguDH3K3X8XxEZhXxE711ZM="
}
}
},
"@parity/etherscan": {
"version": "github:paritytech/js-etherscan#efe859ac7d2a8a3cc05e01c689b7fa58f47f8b87",
"version": "github:paritytech/js-etherscan#12e9ce901609a9ee84907034fe1da34c18e7f358",
"requires": {
"@parity/api": "github:paritytech/js-api#1c7cc5561c4e8db0d0b58f22d8bc8baa243909a5",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"bignumber.js": "3.0.1",
"es6-promise": "4.1.1",
"node-fetch": "1.6.3",
@ -379,41 +340,11 @@
"whatwg-fetch": "2.0.3"
},
"dependencies": {
"@parity/api": {
"version": "github:paritytech/js-api#1c7cc5561c4e8db0d0b58f22d8bc8baa243909a5",
"requires": {
"@parity/abi": "github:paritytech/js-abi#414765a476d88b6fb9f3398c99a946021957d07a",
"@parity/jsonrpc": "github:paritytech/js-jsonrpc#89a6e441370f55d8fe995e27007f60da29b6672b",
"@parity/wordlist": "1.1.0",
"bignumber.js": "3.0.1",
"blockies": "0.0.2",
"es6-error": "4.0.0",
"ethereumjs-tx": "1.3.3",
"eventemitter3": "2.0.3",
"isomorphic-fetch": "2.2.1",
"js-sha3": "0.5.5",
"keythereum": "0.4.6",
"lodash": "4.17.4",
"node-fetch": "1.6.3",
"secp256k1": "3.2.5",
"store": "2.0.12"
}
},
"es6-promise": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz",
"integrity": "sha512-OaU1hHjgJf+b0NzsxCg7NdIYERD6Hy/PEmFLTjw+b65scuisG3Kt4QoTvJ66BBkPZ581gr0kpoVzKnxniM8nng=="
},
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
},
"store": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz",
"integrity": "sha1-jFNOKguDH3K3X8XxEZhXxE711ZM="
},
"whatwg-fetch": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
@ -422,7 +353,7 @@
}
},
"@parity/jsonrpc": {
"version": "github:paritytech/js-jsonrpc#89a6e441370f55d8fe995e27007f60da29b6672b"
"version": "github:paritytech/js-jsonrpc#e271aa9d158fa90a57cc4e6b4ad2993f9fbb8ad4"
},
"@parity/ledger": {
"version": "github:paritytech/js-ledger#c363adfb9192aa56b7b498b0ad90bc4032bcd6ab",
@ -449,15 +380,16 @@
}
},
"@parity/shapeshift": {
"version": "github:paritytech/js-shapeshift#59d71436b678390a3abdea37d58b5ff06edfd750",
"version": "github:paritytech/js-shapeshift#9de4790c8f6ac282e10af5738dd0a687a97fc419",
"requires": {
"node-fetch": "1.6.3"
}
},
"@parity/shared": {
"version": "github:paritytech/js-shared#49f3719ffc732962efc9017daf0e30bd384bfbc2",
"version": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"requires": {
"@parity/ledger": "github:paritytech/js-ledger#c363adfb9192aa56b7b498b0ad90bc4032bcd6ab",
"eventemitter3": "2.0.3",
"loglevel": "1.4.1",
"mobx": "2.6.4",
"mobx-react": "4.0.3",
@ -471,16 +403,17 @@
"serviceworker-webpack-plugin": "0.2.0",
"solc": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818",
"sw-toolbox": "3.6.0",
"useragent.js": "0.5.6",
"worker-loader": "0.8.1",
"yargs": "6.6.0"
}
},
"@parity/ui": {
"version": "github:paritytech/js-ui#7f7235fe696defd547ace030041f2f52c842c7dc",
"version": "github:paritytech/js-ui#82f4c63d6a5eeba95149254accb82f7a54c0104a",
"requires": {
"@parity/api": "github:paritytech/js-api#1c7cc5561c4e8db0d0b58f22d8bc8baa243909a5",
"@parity/etherscan": "github:paritytech/js-etherscan#efe859ac7d2a8a3cc05e01c689b7fa58f47f8b87",
"@parity/shared": "github:paritytech/js-shared#a83c71946d30d5b3bf976860a676add29c48ee24",
"@parity/api": "github:paritytech/js-api#bd566a070313ae35939014219b58bb93f3c3a145",
"@parity/etherscan": "github:paritytech/js-etherscan#12e9ce901609a9ee84907034fe1da34c18e7f358",
"@parity/shared": "github:paritytech/js-shared#1d61c148190a141145b030b2328e2f373c830a2b",
"bignumber.js": "3.0.1",
"brace": "0.9.0",
"date-difference": "1.0.0",
@ -514,55 +447,6 @@
"semantic-ui-css": "2.2.11",
"semantic-ui-react": "0.71.2",
"zxcvbn": "4.4.1"
},
"dependencies": {
"@parity/api": {
"version": "github:paritytech/js-api#1c7cc5561c4e8db0d0b58f22d8bc8baa243909a5",
"requires": {
"@parity/abi": "github:paritytech/js-abi#414765a476d88b6fb9f3398c99a946021957d07a",
"@parity/jsonrpc": "github:paritytech/js-jsonrpc#89a6e441370f55d8fe995e27007f60da29b6672b",
"@parity/wordlist": "1.1.0",
"bignumber.js": "3.0.1",
"blockies": "0.0.2",
"es6-error": "4.0.0",
"ethereumjs-tx": "1.3.3",
"eventemitter3": "2.0.3",
"isomorphic-fetch": "2.2.1",
"js-sha3": "0.5.5",
"keythereum": "0.4.6",
"lodash": "4.17.4",
"node-fetch": "1.6.3",
"secp256k1": "3.2.5",
"store": "2.0.12"
},
"dependencies": {
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
}
}
},
"@parity/shared": {
"version": "github:paritytech/js-shared#a83c71946d30d5b3bf976860a676add29c48ee24",
"requires": {
"mobx": "2.6.4",
"mobx-react": "4.0.3",
"push.js": "0.0.11",
"react-redux": "4.4.6",
"redux": "3.6.0",
"redux-actions": "1.1.0",
"redux-thunk": "2.1.0",
"scryptsy": "2.0.0",
"solc": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818",
"yargs": "6.6.0"
}
},
"store": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz",
"integrity": "sha1-jFNOKguDH3K3X8XxEZhXxE711ZM="
}
}
},
"@parity/wordlist": {
@ -2554,6 +2438,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"base32.js": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz",
"integrity": "sha1-tYLexpPC8R6JPPBk7mrFthMaIgI="
},
"base64-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
@ -2768,6 +2657,11 @@
"hoek": "2.16.3"
}
},
"bowser": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.7.1.tgz",
"integrity": "sha1-pN6PGKGg3JUx6yqSoVIftqm6lqU="
},
"brace": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/brace/-/brace-0.9.0.tgz",
@ -2957,10 +2851,9 @@
"dev": true
},
"bytes": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.5.0.tgz",
"integrity": "sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=",
"dev": true
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
},
"caller-path": {
"version": "0.1.0",
@ -3153,6 +3046,11 @@
"supports-color": "2.0.0"
}
},
"change-emitter": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
"integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
},
"check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
@ -3523,6 +3421,14 @@
"on-headers": "1.0.1",
"safe-buffer": "5.1.1",
"vary": "1.1.1"
},
"dependencies": {
"bytes": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.5.0.tgz",
"integrity": "sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=",
"dev": true
}
}
},
"concat-map": {
@ -4191,7 +4097,7 @@
"create-hmac": "1.1.6",
"diffie-hellman": "5.0.2",
"inherits": "2.0.3",
"pbkdf2": "3.0.12",
"pbkdf2": "3.0.13",
"public-encrypt": "4.0.0",
"randombytes": "2.0.5"
}
@ -8322,6 +8228,11 @@
}
}
},
"hyphenate-style-name": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
"integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es="
},
"iconv-lite": {
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
@ -8586,6 +8497,15 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4="
},
"inline-style-prefixer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz",
"integrity": "sha1-wVPH6I/YT+9cYC6VqBaLJ3BnH+c=",
"requires": {
"bowser": "1.7.1",
"hyphenate-style-name": "1.0.2"
}
},
"inquirer": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
@ -10224,8 +10144,7 @@
"lodash.merge": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz",
"integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=",
"dev": true
"integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU="
},
"lodash.pick": {
"version": "4.4.0",
@ -10282,6 +10201,11 @@
"lodash._reinterpolate": "3.0.0"
}
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@ -10439,6 +10363,35 @@
"integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=",
"dev": true
},
"material-ui": {
"version": "0.16.5",
"resolved": "https://registry.npmjs.org/material-ui/-/material-ui-0.16.5.tgz",
"integrity": "sha1-u4ZhqsfKyMsiOj529PV+4YpK78E=",
"requires": {
"babel-runtime": "6.25.0",
"inline-style-prefixer": "2.0.5",
"keycode": "2.1.9",
"lodash.merge": "4.6.0",
"lodash.throttle": "4.1.1",
"react-addons-create-fragment": "15.6.0",
"react-addons-transition-group": "15.6.0",
"react-event-listener": "0.4.5",
"recompose": "0.20.2",
"simple-assign": "0.1.0",
"warning": "3.0.0"
},
"dependencies": {
"babel-runtime": {
"version": "6.25.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz",
"integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=",
"requires": {
"core-js": "2.4.1",
"regenerator-runtime": "0.10.5"
}
}
}
},
"math-expression-evaluator": {
"version": "1.2.17",
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
@ -11468,7 +11421,7 @@
"browserify-aes": "1.0.6",
"create-hash": "1.1.3",
"evp_bytestokey": "1.0.0",
"pbkdf2": "3.0.12"
"pbkdf2": "3.0.13"
}
},
"parse-github-repo-url": {
@ -11583,9 +11536,9 @@
}
},
"pbkdf2": {
"version": "3.0.12",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz",
"integrity": "sha1-vjZ4XFBn6kjYBv+SMojF91C2uKI=",
"version": "3.0.13",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.13.tgz",
"integrity": "sha512-+dCHxDH+djNtjgWmvVC/my3SYBAKpKNqKSjLkp+GtWWYe4XPE+e/PSD2aCanlEZZnqPk2uekTKNC/ccbwd2X2Q==",
"dev": true,
"requires": {
"create-hash": "1.1.3",
@ -12879,6 +12832,16 @@
}
}
},
"react-addons-create-fragment": {
"version": "15.6.0",
"resolved": "https://registry.npmjs.org/react-addons-create-fragment/-/react-addons-create-fragment-15.6.0.tgz",
"integrity": "sha1-r5GiKx+wld0B8a+6Q7/Q71idiyA=",
"requires": {
"fbjs": "0.8.14",
"loose-envify": "1.3.1",
"object-assign": "4.1.1"
}
},
"react-addons-perf": {
"version": "15.4.2",
"resolved": "https://registry.npmjs.org/react-addons-perf/-/react-addons-perf-15.4.2.tgz",
@ -13343,6 +13306,24 @@
"resolve": "1.4.0"
}
},
"recompose": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/recompose/-/recompose-0.20.2.tgz",
"integrity": "sha1-ET1qx+KcpmTP/+wWtoHd3fFSULw=",
"requires": {
"change-emitter": "0.1.6",
"fbjs": "0.8.14",
"hoist-non-react-statics": "1.2.0",
"symbol-observable": "0.2.4"
},
"dependencies": {
"symbol-observable": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz",
"integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A="
}
}
},
"redbox-react": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/redbox-react/-/redbox-react-1.5.0.tgz",
@ -14030,6 +14011,7 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/serviceworker-webpack-plugin/-/serviceworker-webpack-plugin-0.2.0.tgz",
"integrity": "sha1-beneyC7RRMdUxvFbND57h2SsWyg=",
"optional": true,
"requires": {
"minimatch": "3.0.4"
}
@ -14095,6 +14077,11 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"simple-assign": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/simple-assign/-/simple-assign-0.1.0.tgz",
"integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o="
},
"simple-get": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz",

View File

@ -162,10 +162,22 @@
"@parity/dapp-contracts": "paritytech/dapp-contracts",
"@parity/dapp-dapp-accounts": "paritytech/dapp-dapp-accounts",
"@parity/dapp-dapp-methods": "paritytech/dapp-dapp-methods",
"@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",
"@parity/shared": "paritytech/js-shared",
"@parity/ui": "paritytech/js-ui",
"es6-error": "4.0.0",

View File

@ -19,7 +19,7 @@ import { observer } from 'mobx-react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import DappsStore from '../Dapps/dappsStore';
import DappsStore from '@parity/shared/mobx/dappsStore';
import styles from './dapp.css';

View File

@ -20,7 +20,7 @@ import { FormattedMessage } from 'react-intl';
import { Button } from '@parity/ui';
import DappsStore from '../../Dapps/dappsStore';
import DappsStore from '@parity/shared/mobx/dappsStore';
export default function Request ({ appId, className, approveRequest, denyRequest, queueId, request: { from, method } }) {
const _onApprove = () => approveRequest(queueId, false);

View File

@ -20,7 +20,7 @@ import store from 'store';
import { sha3 } from '@parity/api/util/sha3';
import VisibleStore from '../Dapps/dappsStore';
import VisibleStore from '@parity/shared/mobx/dappsStore';
import filteredRequests from './filteredRequests';
const LS_PERMISSIONS = '_parity::dapps::methods';

View File

@ -1,204 +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 BigNumber from 'bignumber.js';
import sinon from 'sinon';
import localStore from 'store';
import Contracts from '@parity/shared/contracts';
import Store, { LS_KEY_DISPLAY } from './dappsStore';
const APPID_DAPPREG = '0x7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03';
const APPID_GHH = '0x058740ee9a5a3fb9f1cfa10752baec87e09cc45cd7027fd54708271aca300c75';
const APPID_LOCALTX = '0xae74ad174b95cdbd01c88ac5b73a296d33e9088fc2a200e76bcedf3a94a7815d';
const APPID_TOKENDEPLOY = '0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f';
let globalContractsGet;
function stubGlobals () {
globalContractsGet = Contracts.get;
Contracts.get = () => {
return {
dappReg: {
at: sinon.stub().resolves([[0, 1, 2, 3], 'appOwner']),
count: sinon.stub().resolves(new BigNumber(1)),
getContract: sinon.stub().resolves({}),
getContent: sinon.stub().resolves([0, 1, 2, 3]),
getImage: sinon.stub().resolves([0, 1, 2, 3]),
getManifest: sinon.stub().resolves([0, 1, 2, 3])
}
};
};
}
function restoreGlobals () {
Contracts.get = globalContractsGet;
}
let api;
let store;
function create () {
api = {
parity: {
dappsList: () => Promise.resolve([])
}
};
store = new Store(api);
return store;
}
describe('Dapps/DappStore', () => {
beforeEach(() => {
stubGlobals();
});
afterEach(() => {
restoreGlobals();
});
describe('@action', () => {
const defaultViews = {
[APPID_TOKENDEPLOY]: { visible: false },
[APPID_DAPPREG]: { visible: true }
};
describe('setDisplayApps', () => {
beforeEach(() => {
create();
store.setDisplayApps(defaultViews);
});
it('sets from empty start', () => {
expect(store.displayApps).to.deep.equal(defaultViews);
});
it('overrides single keys, keeping existing', () => {
store.setDisplayApps({ [APPID_TOKENDEPLOY]: { visible: true } });
expect(store.displayApps).to.deep.equal(
Object.assign({}, defaultViews, { [APPID_TOKENDEPLOY]: { visible: true } })
);
});
it('extends with new keys, keeping existing', () => {
store.setDisplayApps({ 'test': { visible: true } });
expect(store.displayApps).to.deep.equal(
Object.assign({}, defaultViews, { 'test': { visible: true } })
);
});
});
describe('hideApp/showApp', () => {
beforeEach(() => {
localStore.set(LS_KEY_DISPLAY, defaultViews);
create().readDisplayApps();
});
afterEach(() => {
localStore.set(LS_KEY_DISPLAY, {});
});
it('disables visibility', () => {
store.hideApp(APPID_DAPPREG);
expect(store.displayApps[APPID_DAPPREG].visible).to.be.false;
expect(localStore.get(LS_KEY_DISPLAY)).to.deep.equal(
Object.assign({}, defaultViews, { [APPID_DAPPREG]: { visible: false } })
);
});
it('enables visibility', () => {
store.showApp(APPID_TOKENDEPLOY);
expect(store.displayApps[APPID_TOKENDEPLOY].visible).to.be.true;
expect(localStore.get(LS_KEY_DISPLAY)).to.deep.equal(
Object.assign({}, defaultViews, { [APPID_TOKENDEPLOY]: { visible: true } })
);
});
it('keeps visibility state', () => {
store.hideApp(APPID_TOKENDEPLOY);
store.showApp(APPID_DAPPREG);
expect(store.displayApps[APPID_TOKENDEPLOY].visible).to.be.false;
expect(store.displayApps[APPID_DAPPREG].visible).to.be.true;
expect(localStore.get(LS_KEY_DISPLAY)).to.deep.equal(defaultViews);
});
});
describe('readDisplayApps/writeDisplayApps', () => {
beforeEach(() => {
localStore.set(LS_KEY_DISPLAY, defaultViews);
create().readDisplayApps();
});
afterEach(() => {
localStore.set(LS_KEY_DISPLAY, {});
});
it('loads visibility from storage', () => {
expect(store.displayApps).to.deep.equal(defaultViews);
});
it('saves visibility to storage', () => {
store.setDisplayApps({ [APPID_TOKENDEPLOY]: { visible: true } });
store.writeDisplayApps();
expect(localStore.get(LS_KEY_DISPLAY)).to.deep.equal(
Object.assign({}, defaultViews, { [APPID_TOKENDEPLOY]: { visible: true } })
);
});
});
});
describe('saved views', () => {
beforeEach(() => {
localStore.set(LS_KEY_DISPLAY, {
[APPID_TOKENDEPLOY]: { visible: false },
[APPID_DAPPREG]: { visible: true }
});
return create().loadAllApps();
});
afterEach(() => {
localStore.set(LS_KEY_DISPLAY, {});
});
it('disables based on saved keys', () => {
expect(store.displayApps[APPID_TOKENDEPLOY].visible).to.be.false;
});
it('enables based on saved keys', () => {
expect(store.displayApps[APPID_DAPPREG].visible).to.be.true;
});
it('keeps non-sepcified disabled keys', () => {
expect(store.displayApps[APPID_GHH].visible).to.be.false;
});
it('keeps non-specified enabled keys', () => {
expect(store.displayApps[APPID_LOCALTX].visible).to.be.true;
});
});
});

View File

@ -23,7 +23,7 @@ import PropTypes from 'prop-types';
import { Checkbox, DappCard, Page, SectionList } from '@parity/ui';
import DappsStore from './dappsStore';
import DappsStore from '@parity/shared/mobx/dappsStore';
import styles from './dapps.css';

View File

@ -1,306 +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 EventEmitter from 'eventemitter3';
import { action, computed, observable, transaction } from 'mobx';
import store from 'store';
import Contracts from '@parity/shared/contracts';
import { fetchBuiltinApps, fetchLocalApps, fetchRegistryAppIds, fetchRegistryApp, subscribeToChanges } from '@parity/shared/util/dapps';
const LS_KEY_DISPLAY = 'displayApps';
const LS_KEY_EXTERNAL_ACCEPT = 'acceptExternal';
const BUILTIN_APPS_KEY = 'BUILTIN_APPS_KEY';
let instance = null;
export default class DappsStore extends EventEmitter {
@observable apps = [];
@observable displayApps = {};
@observable modalOpen = false;
@observable externalOverlayVisible = true;
_api = null;
_subscriptions = {};
_cachedApps = {};
_manifests = {};
_registryAppsIds = null;
constructor (api) {
super();
this._api = api;
this.readDisplayApps();
this.loadExternalOverlay();
this.subscribeToChanges();
}
static get (api) {
if (!instance) {
instance = new DappsStore(api);
}
return instance;
}
@computed get allApps () {
return this.apps;
}
@computed get sortedBuiltin () {
return this.apps.filter((app) => app.type === 'builtin');
}
@computed get sortedLocal () {
return this.apps.filter((app) => app.type === 'local');
}
@computed get sortedNetwork () {
return this.apps.filter((app) => app.type === 'network');
}
@computed get visibleApps () {
return this.apps.filter((app) => this.displayApps[app.id] && this.displayApps[app.id].visible);
}
@computed get visibleBuiltin () {
return this.visibleApps.filter((app) => !app.noselect && app.type === 'builtin');
}
@computed get visibleLocal () {
return this.visibleApps.filter((app) => app.type === 'local');
}
@computed get visibleNetwork () {
return this.visibleApps.filter((app) => app.type === 'network');
}
@computed get visibleViews () {
return this.visibleApps.filter((app) => !app.noselect && app.type === 'view');
}
/**
* Try to find the app from the local (local or builtin)
* apps, else fetch from the node
*/
loadApp (id) {
const { dappReg } = Contracts.get(this._api);
return this
.loadLocalApps()
.then(() => {
const app = this.apps.find((app) => app.id === id);
if (app) {
return app;
}
return this.fetchRegistryApp(dappReg, id, true);
})
.then((app) => {
this.emit('loaded', app);
return app;
});
}
loadLocalApps () {
return Promise
.all([
this.fetchBuiltinApps().then((apps) => this.addApps(apps)),
this.fetchLocalApps().then((apps) => this.addApps(apps))
]);
}
loadAllApps () {
const { dappReg } = Contracts.get(this._api);
return Promise
.all([
this.loadLocalApps(),
this.fetchRegistryApps(dappReg).then((apps) => this.addApps(apps))
])
.then(this.writeDisplayApps);
}
subscribeToChanges () {
const { dappReg } = Contracts.get(this._api);
// Unsubscribe from previous subscriptions, if any
if (this._subscriptions.block) {
this._api.unsubscribe(this._subscriptions.block);
}
if (this._subscriptions.filter) {
this._api.eth.uninstallFilter(this._subscriptions.filter);
}
// Subscribe to dapps reg changes
subscribeToChanges(this._api, dappReg, (appIds) => {
const updates = appIds.map((appId) => {
return this.fetchRegistryApp(dappReg, appId, true);
});
Promise
.all(updates)
.then((apps) => {
this.addApps(apps);
});
}).then((subscriptions) => {
this._subscriptions = subscriptions;
});
}
fetchBuiltinApps (force = false) {
if (!force && this._cachedApps[BUILTIN_APPS_KEY] !== undefined) {
return Promise.resolve(this._cachedApps[BUILTIN_APPS_KEY]);
}
this._cachedApps[BUILTIN_APPS_KEY] = fetchBuiltinApps(this._api)
.then((apps) => {
this._cachedApps[BUILTIN_APPS_KEY] = apps;
return apps;
});
return Promise.resolve(this._cachedApps[BUILTIN_APPS_KEY]);
}
fetchLocalApps () {
return fetchLocalApps(this._api);
}
fetchRegistryAppIds (force = false) {
if (!force && this._registryAppsIds) {
return Promise.resolve(this._registryAppsIds);
}
this._registryAppsIds = fetchRegistryAppIds(this._api)
.then((appIds) => {
this._registryAppsIds = appIds;
return this._registryAppsIds;
});
return Promise.resolve(this._registryAppsIds);
}
fetchRegistryApp (dappReg, appId, force = false) {
if (!force && this._cachedApps[appId] !== undefined) {
return Promise.resolve(this._cachedApps[appId]);
}
this._cachedApps[appId] = fetchRegistryApp(this._api, dappReg, appId)
.then((dapp) => {
this._cachedApps[appId] = dapp;
return dapp;
});
return Promise.resolve(this._cachedApps[appId]);
}
fetchRegistryApps (dappReg) {
return this
.fetchRegistryAppIds()
.then((appIds) => {
const promises = appIds.map((appId) => {
// Fetch the Dapp and display it ASAP
return this
.fetchRegistryApp(dappReg, appId)
.then((app) => {
if (app) {
this.addApps([ app ]);
}
return app;
});
});
return Promise.all(promises);
});
}
@action openModal = () => {
this.modalOpen = true;
}
@action closeModal = () => {
this.modalOpen = false;
}
@action closeExternalOverlay = () => {
this.externalOverlayVisible = false;
store.set(LS_KEY_EXTERNAL_ACCEPT, true);
}
@action loadExternalOverlay () {
this.externalOverlayVisible = !(store.get(LS_KEY_EXTERNAL_ACCEPT) || false);
}
@action hideApp = (id) => {
this.setDisplayApps({ [id]: { visible: false } });
this.writeDisplayApps();
}
@action showApp = (id) => {
this.setDisplayApps({ [id]: { visible: true } });
this.writeDisplayApps();
}
@action readDisplayApps = () => {
this.displayApps = store.get(LS_KEY_DISPLAY) || {};
}
@action writeDisplayApps = () => {
store.set(LS_KEY_DISPLAY, this.displayApps);
}
@action setDisplayApps = (displayApps) => {
this.displayApps = Object.assign({}, this.displayApps, displayApps);
};
@action addApps = (_apps = []) => {
transaction(() => {
const apps = _apps.filter((app) => app);
// Get new apps IDs if available
const newAppsIds = apps
.map((app) => app.id)
.filter((id) => id);
this.apps = this.apps
.filter((app) => !app.id || !newAppsIds.includes(app.id))
.concat(apps || [])
.sort((a, b) => a.name.localeCompare(b.name));
const visibility = {};
apps.forEach((app) => {
if (!this.displayApps[app.id]) {
visibility[app.id] = { visible: app.visible };
}
});
this.setDisplayApps(visibility);
});
}
getAppById = (id) => {
return this.apps.find((app) => app.id === id);
}
}
export {
LS_KEY_DISPLAY
};

View File

@ -21,7 +21,7 @@ import { FormattedMessage } from 'react-intl';
import { Button } from '@parity/ui';
import { CloseIcon, CheckIcon } from '@parity/ui/Icons';
import Store from './store';
import Store from '@parity/shared/mobx/extensionStore';
import styles from './extension.css';
@observer

View File

@ -1,116 +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/>.
/* global chrome */
import { action, computed, observable } from 'mobx';
import store from 'store';
import browser from 'useragent.js/lib/browser';
import { DOMAIN } from '@parity/shared/util/constants';
const A_DAY = 24 * 60 * 60 * 1000;
const NEXT_DISPLAY = '_parity::extensionWarning::nextDisplay';
// 'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig';
const EXTENSION_PAGE = 'https://chrome.google.com/webstore/detail/himekenlppkgeaoeddcliojfddemadig';
let instance;
export default class Store {
@observable hasExtension = false;
@observable isInstalling = false;
@observable nextDisplay = 0;
@observable shouldInstall = false;
constructor () {
this.nextDisplay = store.get(NEXT_DISPLAY) || 0;
this.testInstall();
}
@computed get showWarning () {
return !this.isInstalling && this.shouldInstall && (Date.now() > this.nextDisplay);
}
@action setExtensionActive = () => {
this.hasExtension = true;
}
@action setInstalling = (isInstalling) => {
this.isInstalling = isInstalling;
}
@action snoozeWarning = (sleep = A_DAY) => {
this.nextDisplay = Date.now() + sleep;
store.set(NEXT_DISPLAY, this.nextDisplay);
}
@action testInstall = () => {
this.shouldInstall = this.readStatus();
}
readStatus = () => {
const hasExtension = Symbol.for('parity.extension') in window;
const ua = browser.analyze(navigator.userAgent || '');
if (hasExtension) {
this.setExtensionActive();
return false;
}
return (ua || {}).name.toLowerCase() === 'chrome';
}
installExtension = () => {
this.setInstalling(true);
if (window.location.hostname.toString().endsWith(DOMAIN)) {
return this.inlineInstall()
.catch((error) => {
console.warn('Unable to perform direct install', error);
window.open(EXTENSION_PAGE, '_blank');
});
}
window.open(EXTENSION_PAGE, '_blank');
return Promise.resolve(true);
}
inlineInstall = () => {
return new Promise((resolve, reject) => {
const link = document.createElement('link');
link.setAttribute('rel', 'chrome-webstore-item');
link.setAttribute('href', EXTENSION_PAGE);
document.querySelector('head').appendChild(link);
if (chrome && chrome.webstore && chrome.webstore.install) {
chrome.webstore.install(EXTENSION_PAGE, resolve, reject);
} else {
reject(new Error('Direct installation failed.'));
}
});
}
static get () {
if (!instance) {
instance = new Store();
}
return instance;
}
}

View File

@ -29,7 +29,7 @@ import { CancelIcon, FingerprintIcon } from '@parity/ui/Icons';
import imagesEthcoreBlock from '@parity/shared/assets/images/parity-logo-white-no-text.svg';
import DappsStore from '../Dapps/dappsStore';
import DappsStore from '@parity/shared/mobx/dappsStore';
import Signer from '../Signer/Embedded';
import AccountStore from './accountStore';

View File

@ -23,10 +23,9 @@ import { bindActionCreators } from 'redux';
import * as RequestsActions from '@parity/shared/redux/providers/signerActions';
import { Container } from '@parity/ui';
import RequestPending from '@parity/ui/Signer/RequestPending';
import Store from '../store';
import RequestPending from '../components/RequestPending';
import Store from '@parity/shared/mobx/signerStore';
import styles from './embedded.css';

View File

@ -1,20 +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/>.
*/
.container {
text-decoration: none;
color: inherit;
}

View File

@ -1,106 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import styles from './accountLink.css';
class AccountLink extends Component {
static propTypes = {
accountAddresses: PropTypes.array.isRequired,
address: PropTypes.string.isRequired,
className: PropTypes.string,
children: PropTypes.node,
externalLink: PropTypes.string.isRequired
}
state = {
link: null
};
componentWillMount () {
const { address, externalLink } = this.props;
this.updateLink(address, externalLink);
}
componentWillReceiveProps (nextProps) {
const { address, externalLink } = nextProps;
this.updateLink(address, externalLink);
}
render () {
const { children, address, className, externalLink } = this.props;
if (externalLink) {
return (
<a
href={ this.state.link }
target='_blank'
className={ `${styles.container} ${className}` }
>
{ children || address }
</a>
);
}
return (
<Link
className={ `${styles.container} ${className}` }
to={ this.state.link }
>
{ children || address }
</Link>
);
}
updateLink (address, externalLink) {
const { accountAddresses } = this.props;
const isAccount = accountAddresses.includes(address);
let link = isAccount
? `/accounts/${address}`
: `/addresses/${address}`;
if (externalLink) {
const path = externalLink.replace(/\/+$/, '');
link = `${path}/#${link}`;
}
this.setState({
link
});
}
}
function mapStateToProps (initState) {
const { accounts } = initState.personal;
const accountAddresses = Object.keys(accounts);
return () => {
return { accountAddresses };
};
}
export default connect(
mapStateToProps,
null
)(AccountLink);

View File

@ -1,17 +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/>.
export default from './accountLink';

View File

@ -1,50 +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/>.
*/
.acc {
text-align: center;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.acc > * {
display: block;
}
.address {
font-family: monospace;
}
.acc img {
width: 28px;
height: 28px;
vertical-align: middle;
margin-right: 3px;
}
.name {
white-space: nowrap;
display: block;
vertical-align: middle;
text-transform: uppercase;
span {
text-overflow: ellipsis;
overflow: hidden;
}
}

View File

@ -1,130 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import { IdentityIcon, IdentityName } from '@parity/ui';
import AccountLink from './AccountLink';
import styles from './account.css';
export default class Account extends Component {
static propTypes = {
address: PropTypes.string.isRequired,
className: PropTypes.string,
disabled: PropTypes.bool,
externalLink: PropTypes.string.isRequired,
netVersion: PropTypes.string.isRequired,
balance: PropTypes.object // eth BigNumber, not required since it mght take time to fetch
};
state = {
balanceDisplay: '?'
};
componentWillMount () {
this.updateBalanceDisplay(this.props.balance);
}
componentWillReceiveProps (nextProps) {
if (nextProps.balance === this.props.balance) {
return;
}
this.updateBalanceDisplay(nextProps.balance);
}
updateBalanceDisplay (balance) {
this.setState({
balanceDisplay: balance ? balance.div(1e18).toFormat(3) : '?'
});
}
render () {
const { address, className, disabled, externalLink, netVersion } = this.props;
return (
<div className={ `${styles.acc} ${className}` }>
<AccountLink
address={ address }
externalLink={ externalLink }
netVersion={ netVersion }
>
<IdentityIcon
center
disabled={ disabled }
address={ address }
/>
</AccountLink>
{ this.renderName() }
{ this.renderBalance() }
</div>
);
}
renderBalance () {
const { balanceDisplay } = this.state;
return (
<span> <strong>{ balanceDisplay }</strong> <small>ETH</small></span>
);
}
renderName () {
const { address, externalLink, netVersion } = this.props;
const name = <IdentityName address={ address } empty />;
if (!name) {
return (
<AccountLink
address={ address }
externalLink={ externalLink }
netVersion={ netVersion }
>
[{ this.shortAddress(address) }]
</AccountLink>
);
}
return (
<AccountLink
address={ address }
externalLink={ externalLink }
netVersion={ netVersion }
>
<span>
<span className={ styles.name }>{ name }</span>
<span className={ styles.address }>[{ this.tinyAddress(address) }]</span>
</span>
</AccountLink>
);
}
tinyAddress () {
const { address } = this.props;
const len = address.length;
return address.slice(2, 4) + '..' + address.slice(len - 2);
}
shortAddress () {
const { address } = this.props;
const len = address.length;
return address.slice(2, 8) + '..' + address.slice(len - 7);
}
}

View File

@ -1,17 +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/>.
export default from './account';

View File

@ -1,185 +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 { observer } from 'mobx-react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import Account from '../Account';
import TransactionPendingForm from '../TransactionPendingForm';
import RequestOrigin from '../RequestOrigin';
import styles from '../SignRequest/signRequest.css';
@observer
class DecryptRequest extends Component {
static contextTypes = {
api: PropTypes.object
};
static propTypes = {
accounts: PropTypes.object.isRequired,
address: PropTypes.string.isRequired,
data: PropTypes.string.isRequired,
id: PropTypes.object.isRequired,
isFinished: PropTypes.bool.isRequired,
netVersion: PropTypes.string.isRequired,
signerStore: PropTypes.object.isRequired,
className: PropTypes.string,
focus: PropTypes.bool,
isSending: PropTypes.bool,
onConfirm: PropTypes.func,
onReject: PropTypes.func,
origin: PropTypes.any,
status: PropTypes.string
};
static defaultProps = {
focus: false,
origin: {
type: 'unknown',
details: ''
}
};
componentWillMount () {
const { address, signerStore } = this.props;
signerStore.fetchBalance(address);
}
render () {
const { className } = this.props;
return (
<div className={ `${styles.container} ${className}` }>
{ this.renderDetails() }
{ this.renderActions() }
</div>
);
}
renderDetails () {
const { api } = this.context;
const { address, data, netVersion, origin, signerStore } = this.props;
const { balances, externalLink } = signerStore;
const balance = balances[address];
if (!balance) {
return <div />;
}
return (
<div className={ styles.signDetails }>
<div className={ styles.address }>
<Account
address={ address }
balance={ balance }
className={ styles.account }
externalLink={ externalLink }
netVersion={ netVersion }
/>
<RequestOrigin origin={ origin } />
</div>
<div className={ styles.info } title={ api.util.sha3(data) }>
<p>
<FormattedMessage
id='signer.decryptRequest.request'
defaultMessage='A request to decrypt data using your account:'
/>
</p>
<div className={ styles.signData }>
<p>{ data }</p>
</div>
</div>
</div>
);
}
renderActions () {
const { accounts, address, focus, isFinished, status, data } = this.props;
const account = accounts[address];
if (isFinished) {
if (status === 'confirmed') {
return (
<div className={ styles.actions }>
<span className={ styles.isConfirmed }>
<FormattedMessage
id='signer.decryptRequest.state.confirmed'
defaultMessage='Confirmed'
/>
</span>
</div>
);
}
return (
<div className={ styles.actions }>
<span className={ styles.isRejected }>
<FormattedMessage
id='signer.decryptRequest.state.rejected'
defaultMessage='Rejected'
/>
</span>
</div>
);
}
return (
<TransactionPendingForm
account={ account }
address={ address }
focus={ focus }
isSending={ this.props.isSending }
netVersion={ this.props.netVersion }
onConfirm={ this.onConfirm }
onReject={ this.onReject }
className={ styles.actions }
dataToSign={ { decrypt: data } }
/>
);
}
onConfirm = (data) => {
const { id } = this.props;
const { password, decrypted, wallet } = data;
this.props.onConfirm({ id, password, decrypted, wallet });
}
onReject = () => {
this.props.onReject(this.props.id);
}
}
function mapStateToProps (state) {
const { accounts } = state.personal;
return {
accounts
};
}
export default connect(
mapStateToProps,
null
)(DecryptRequest);

View File

@ -1,17 +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/>.
export default from './decryptRequest';

View File

@ -1,17 +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/>.
export default from './requestOrigin';

View File

@ -1,43 +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/>.
*/
.container {
text-align: left;
margin: 3em .5em;
opacity: 0.6;
font-size: 0.8em;
.unknown {
color: #e44;
}
.url {
max-width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.hash {
margin-left: .5em;
}
.hash, .url {
margin-bottom: -.2em;
display: inline-block;
}
}

View File

@ -1,171 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import IdentityIcon from '@parity/ui/IdentityIcon';
import styles from './requestOrigin.css';
export default class RequestOrigin extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
};
static propTypes = {
origin: PropTypes.shape({
type: PropTypes.oneOf(['unknown', 'dapp', 'rpc', 'ipc', 'signer']),
details: PropTypes.oneOfType([
PropTypes.string,
PropTypes.shape({
session: PropTypes.string.isRequired
})
]).isRequired
}).isRequired
};
render () {
const { origin } = this.props;
return (
<div className={ styles.container }>
Requested { this.renderOrigin(origin) }
</div>
);
}
renderOrigin (origin) {
if (origin.type === 'unknown') {
return (
<span className={ styles.unknown }>
<FormattedMessage
id='signer.requestOrigin.unknownInterface'
defaultMessage='via unknown interface'
/>
</span>
);
}
if (origin.type === 'dapp') {
return (
<span>
<FormattedMessage
id='signer.requestOrigin.dapp'
defaultMessage='by a dapp at {url}'
values={ {
url: (
<span className={ styles.url }>
{
origin.details || (
<FormattedMessage
id='signer.requestOrigin.unknownUrl'
defaultMessage='unknown URL'
/>
)
}
</span>
)
} }
/>
</span>
);
}
if (origin.type === 'rpc') {
return (
<span>
<FormattedMessage
id='signer.requestOrigin.rpc'
defaultMessage='via RPC {url}'
values={ {
url: (
<span className={ styles.url }>
({
origin.details || (
<FormattedMessage
id='signer.requestOrigin.unknownRpc'
defaultMessage='unidentified'
/>
)
})
</span>
)
} }
/>
</span>
);
}
if (origin.type === 'ipc') {
return (
<span>
<FormattedMessage
id='signer.requestOrigin.ipc'
defaultMessage='via IPC session'
/>
<span
className={ styles.hash }
title={ origin.details }
>
<IdentityIcon
address={ origin.details }
tiny
/>
</span>
</span>
);
}
if (origin.type === 'signer') {
const session = origin.details && origin.details.session || origin.details;
return this.renderSigner(session);
}
}
renderSigner (session) {
if (session.substr(2) === this.context.api.transport.sessionHash) {
return (
<span title={ session }>
<FormattedMessage
id='signer.requestOrigin.signerCurrent'
defaultMessage='via current tab'
/>
</span>
);
}
return (
<span>
<FormattedMessage
id='signer.requestOrigin.signerUI'
defaultMessage='via UI session'
/>
<span
className={ styles.hash }
title={ `UI Session id: ${session}` }
>
<IdentityIcon
address={ session }
tiny
/>
</span>
</span>
);
}
}

View File

@ -1,72 +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 { shallow } from 'enzyme';
import React from 'react';
import RequestOrigin from './';
const context = {
context: {
api: {
transport: {
sessionHash: '1234'
}
}
}
};
describe('views/Signer/components/RequestOrigin', () => {
it('renders unknown', () => {
expect(shallow(
<RequestOrigin origin={ { type: 'unknown', details: '' } } />,
context
).find('FormattedMessage').props().id).to.equal('signer.requestOrigin.unknownInterface');
});
it('renders dapps', () => {
expect(shallow(
<RequestOrigin origin={ { type: 'dapp', details: 'http://parity.io' } } />,
context
).find('FormattedMessage').props().id).to.equal('signer.requestOrigin.dapp');
});
it('renders rpc', () => {
expect(shallow(
<RequestOrigin origin={ { type: 'rpc', details: '' } } />,
context
).find('FormattedMessage').props().id).to.equal('signer.requestOrigin.rpc');
});
it('renders ipc', () => {
expect(shallow(
<RequestOrigin origin={ { type: 'ipc', details: '0x1234' } } />,
context
).find('FormattedMessage').props().id).to.equal('signer.requestOrigin.ipc');
});
it('renders signer', () => {
expect(shallow(
<RequestOrigin origin={ { type: 'signer', details: '0x12345' } } />,
context
).find('FormattedMessage').props().id).to.equal('signer.requestOrigin.signerUI');
expect(shallow(
<RequestOrigin origin={ { type: 'signer', details: '0x1234' } } />,
context
).find('FormattedMessage').props().id).to.equal('signer.requestOrigin.signerCurrent');
});
});

View File

@ -1,17 +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/>.
export default from './requestPending';

View File

@ -1,126 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import DecryptRequest from '../DecryptRequest';
import SignRequest from '../SignRequest';
import TransactionPending from '../TransactionPending';
export default class RequestPending extends Component {
static propTypes = {
className: PropTypes.string,
date: PropTypes.instanceOf(Date).isRequired,
focus: PropTypes.bool,
gasLimit: PropTypes.object.isRequired,
id: PropTypes.object.isRequired,
isSending: PropTypes.bool.isRequired,
netVersion: PropTypes.string.isRequired,
onConfirm: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired,
origin: PropTypes.object.isRequired,
payload: PropTypes.oneOfType([
PropTypes.shape({ decrypt: PropTypes.object.isRequired }),
PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sign: PropTypes.object.isRequired }),
PropTypes.shape({ signTransaction: PropTypes.object.isRequired })
]).isRequired,
signerStore: PropTypes.object.isRequired
};
static defaultProps = {
focus: false,
isSending: false
};
render () {
const { className, date, focus, gasLimit, id, isSending, netVersion, onReject, payload, signerStore, origin } = this.props;
if (payload.sign) {
const { sign } = payload;
return (
<SignRequest
address={ sign.address }
className={ className }
focus={ focus }
data={ sign.data }
id={ id }
isFinished={ false }
isSending={ isSending }
netVersion={ netVersion }
onConfirm={ this.onConfirm }
onReject={ onReject }
origin={ origin }
signerStore={ signerStore }
/>
);
}
if (payload.decrypt) {
const { decrypt } = payload;
return (
<DecryptRequest
address={ decrypt.address }
className={ className }
focus={ focus }
data={ decrypt.msg }
id={ id }
isFinished={ false }
isSending={ isSending }
netVersion={ netVersion }
onConfirm={ this.onConfirm }
onReject={ onReject }
origin={ origin }
signerStore={ signerStore }
/>
);
}
const transaction = payload.sendTransaction || payload.signTransaction;
if (transaction) {
return (
<TransactionPending
className={ className }
date={ date }
focus={ focus }
gasLimit={ gasLimit }
id={ id }
isSending={ isSending }
netVersion={ netVersion }
onConfirm={ this.onConfirm }
onReject={ onReject }
origin={ origin }
signerStore={ signerStore }
transaction={ transaction }
/>
);
}
console.error('RequestPending: Unknown payload', payload);
return null;
}
onConfirm = (data) => {
const { onConfirm, payload } = this.props;
data.payload = payload;
onConfirm(data);
};
}

View File

@ -1,132 +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 BigNumber from 'bignumber.js';
import { shallow } from 'enzyme';
import React from 'react';
import sinon from 'sinon';
import RequestPending from './';
const ADDRESS = '0x1234567890123456789012345678901234567890';
const TRANSACTION = {
from: ADDRESS,
gas: new BigNumber(21000),
gasPrice: new BigNumber(20000000),
value: new BigNumber(1)
};
const PAYLOAD_SENDTX = {
sendTransaction: TRANSACTION
};
const PAYLOAD_SIGN = {
sign: {
address: ADDRESS,
data: 'testing'
}
};
const PAYLOAD_SIGNTX = {
signTransaction: TRANSACTION
};
const PAYLOAD_DECRYPT = {
decrypt: {
address: ADDRESS,
msg: 'testing'
}
};
let component;
let onConfirm;
let onReject;
function render (payload) {
onConfirm = sinon.stub();
onReject = sinon.stub();
component = shallow(
<RequestPending
date={ new Date() }
gasLimit={ new BigNumber(100000) }
id={ new BigNumber(123) }
isSending={ false }
netVersion='42'
onConfirm={ onConfirm }
onReject={ onReject }
origin={ {} }
payload={ payload }
store={ {} }
/>
);
return component;
}
describe('views/Signer/RequestPending', () => {
describe('sendTransaction', () => {
beforeEach(() => {
render(PAYLOAD_SENDTX);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('renders TransactionPending component', () => {
expect(component.find('Connect(TransactionPending)')).to.have.length(1);
});
});
describe('sign', () => {
beforeEach(() => {
render(PAYLOAD_SIGN);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('renders SignRequest component', () => {
expect(component.find('Connect(SignRequest)')).to.have.length(1);
});
});
describe('signTransaction', () => {
beforeEach(() => {
render(PAYLOAD_SIGNTX);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('renders TransactionPending component', () => {
expect(component.find('Connect(TransactionPending)')).to.have.length(1);
});
});
describe('decrypt', () => {
beforeEach(() => {
render(PAYLOAD_DECRYPT);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('renders DecryptRequest component', () => {
expect(component.find('Connect(DecryptRequest)')).to.have.length(1);
});
});
});

View File

@ -1,17 +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/>.
export default from './signRequest';

View File

@ -1,91 +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 '../../_layout.css';
.container {
display: flex;
padding: 1.5em 1em 1.5em 0;
}
.actions, .signDetails {
vertical-align: middle;
min-height: $pendingHeight;
}
.signData {
border: 0.25em solid red;
margin-left: 2em;
padding: 0.5em;
overflow: auto;
max-height: 6em;
max-width: calc(100% - 2em);
}
.signData > p {
color: white;
}
.signDetails {
flex: 1;
overflow: auto;
}
.account img {
display: inline-block;
height: 50px;
margin: 5px;
width: 50px;
}
.address, .info {
box-sizing: border-box;
display: inline-block;
vertical-align: top;
}
.address {
width: 40%;
}
.info {
color: #E53935;
width: 60%;
}
.info p:first-child {
margin-top: 0;
}
/* TODO [todr] copy&paste from transactions */
.isConfirmed {
color: green;
}
.isRejected {
opacity: 0.7;
}
.txHash {
display: block;
word-break: break-all;
}
.actions {
display: inline-block;
min-height: $finishedHeight;
}

View File

@ -1,232 +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 { observer } from 'mobx-react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import HardwareStore from '@parity/shared/mobx/hardwareStore';
import Account from '../Account';
import TransactionPendingForm from '../TransactionPendingForm';
import RequestOrigin from '../RequestOrigin';
import styles from './signRequest.css';
function isAscii (data) {
for (var i = 2; i < data.length; i += 2) {
let n = parseInt(data.substr(i, 2), 16);
if (n < 32 || n >= 128) {
return false;
}
}
return true;
}
@observer
class SignRequest extends Component {
static contextTypes = {
api: PropTypes.object
};
static propTypes = {
accounts: PropTypes.object.isRequired,
address: PropTypes.string.isRequired,
data: PropTypes.string.isRequired,
id: PropTypes.object.isRequired,
isFinished: PropTypes.bool.isRequired,
netVersion: PropTypes.string.isRequired,
signerStore: PropTypes.object.isRequired,
className: PropTypes.string,
focus: PropTypes.bool,
isSending: PropTypes.bool,
onConfirm: PropTypes.func,
onReject: PropTypes.func,
origin: PropTypes.any,
status: PropTypes.string
};
static defaultProps = {
focus: false,
origin: {
type: 'unknown',
details: ''
}
};
hardwareStore = HardwareStore.get(this.context.api);
componentWillMount () {
const { address, signerStore } = this.props;
signerStore.fetchBalance(address);
}
render () {
const { className } = this.props;
return (
<div className={ `${styles.container} ${className}` }>
{ this.renderDetails() }
{ this.renderActions() }
</div>
);
}
renderAsciiDetails (ascii) {
return (
<div className={ styles.signData }>
<p>{ascii}</p>
</div>
);
}
renderBinaryDetails (data) {
return (
<div className={ styles.signData }>
<p>
<FormattedMessage
id='signer.signRequest.unknownBinary'
defaultMessage='(Unknown binary data)'
/>
</p>
</div>
);
}
renderDetails () {
const { api } = this.context;
const { address, data, netVersion, origin, signerStore } = this.props;
const { balances, externalLink } = signerStore;
const balance = balances[address];
if (!balance) {
return <div />;
}
return (
<div className={ styles.signDetails }>
<div className={ styles.address }>
<Account
address={ address }
balance={ balance }
className={ styles.account }
externalLink={ externalLink }
netVersion={ netVersion }
/>
<RequestOrigin origin={ origin } />
</div>
<div className={ styles.info } title={ api.util.sha3(data) }>
<p>
<FormattedMessage
id='signer.signRequest.request'
defaultMessage='A request to sign data using your account:'
/>
</p>
{
isAscii(data)
? this.renderAsciiDetails(api.util.hexToAscii(data))
: this.renderBinaryDetails(data)
}
<p>
<strong>
<FormattedMessage
id='signer.signRequest.warning'
defaultMessage='WARNING: This consequences of doing this may be grave. Confirm the request only if you are sure.'
/>
</strong>
</p>
</div>
</div>
);
}
renderActions () {
const { accounts, address, focus, isFinished, status, data } = this.props;
const account = accounts[address] || {};
const disabled = account.hardware && !this.hardwareStore.isConnected(address);
if (isFinished) {
if (status === 'confirmed') {
return (
<div className={ styles.actions }>
<span className={ styles.isConfirmed }>
<FormattedMessage
id='signer.signRequest.state.confirmed'
defaultMessage='Confirmed'
/>
</span>
</div>
);
}
return (
<div className={ styles.actions }>
<span className={ styles.isRejected }>
<FormattedMessage
id='signer.signRequest.state.rejected'
defaultMessage='Rejected'
/>
</span>
</div>
);
}
return (
<TransactionPendingForm
account={ account }
address={ address }
disabled={ disabled }
focus={ focus }
isSending={ this.props.isSending }
netVersion={ this.props.netVersion }
onConfirm={ this.onConfirm }
onReject={ this.onReject }
className={ styles.actions }
dataToSign={ { data } }
/>
);
}
onConfirm = (data) => {
const { id } = this.props;
const { password, dataSigned, wallet } = data;
this.props.onConfirm({ id, password, dataSigned, wallet });
}
onReject = () => {
this.props.onReject(this.props.id);
}
}
function mapStateToProps (state) {
const { accounts } = state.personal;
return {
accounts
};
}
export default connect(
mapStateToProps,
null
)(SignRequest);

View File

@ -1,72 +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 { shallow } from 'enzyme';
import React from 'react';
import sinon from 'sinon';
import SignRequest from './';
let component;
let reduxStore;
let signerStore;
function createSignerStore () {
return {
balances: {},
fetchBalance: sinon.stub()
};
}
function createReduxStore () {
return {
dispatch: sinon.stub(),
subscribe: sinon.stub(),
getState: () => {
return {
personal: {
accounts: {}
}
};
}
};
}
function render () {
reduxStore = createReduxStore();
signerStore = createSignerStore();
component = shallow(
<SignRequest signerStore={ signerStore } />,
{
context: {
store: reduxStore
}
}
).find('SignRequest').shallow();
return component;
}
describe('views/Signer/components/SignRequest', () => {
beforeEach(() => {
render();
});
it('renders', () => {
expect(component).to.be.ok;
});
});

View File

@ -1,17 +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/>.
export default from './transactionMainDetails';

View File

@ -1,80 +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 '../../_layout.css';
.account {
text-align: center;
}
.contractIcon {
background: #eee;
width: 50px !important;
height: 50px !important;
box-sizing: border-box;
border-radius: 50%;
padding: 13px;
}
.editButtonRow {
text-align: right;
}
.from {
display: inline-block;
width: 40%;
vertical-align: top;
.account {
img {
display: inline-block;
width: 50px;
height: 50px;
margin: 5px;
}
span {
display: block;
}
}
}
.method {
display: inline-block;
width: 60%;
vertical-align: top;
line-height: 1em;
}
.tx {
position: relative;
text-align: center;
margin: 0 -75px;
width: 150px;
top: -20px;
white-space: nowrap;
}
.total {
font-size: 0.6em;
opacity: .5;
}
.transaction {
flex: 1;
overflow: auto;
}

View File

@ -1,202 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import ReactTooltip from 'react-tooltip';
import { Button, MethodDecoding } from '@parity/ui';
import { GasIcon } from '@parity/ui/Icons';
import * as tUtil from '../util/transaction';
import Account from '../Account';
import RequestOrigin from '../RequestOrigin';
import styles from './transactionMainDetails.css';
export default class TransactionMainDetails extends Component {
static propTypes = {
children: PropTypes.node,
disabled: PropTypes.bool,
externalLink: PropTypes.string.isRequired,
from: PropTypes.string.isRequired,
fromBalance: PropTypes.object,
gasStore: PropTypes.object,
id: PropTypes.object.isRequired,
netVersion: PropTypes.string.isRequired,
origin: PropTypes.any,
totalValue: PropTypes.object.isRequired,
transaction: PropTypes.object.isRequired,
value: PropTypes.object.isRequired
};
static defaultProps = {
origin: {
type: 'unknown',
details: ''
}
};
componentWillMount () {
const { totalValue, value } = this.props;
this.updateDisplayValues(value, totalValue);
}
componentWillReceiveProps (nextProps) {
const { totalValue, value } = nextProps;
this.updateDisplayValues(value, totalValue);
}
render () {
const { children, disabled, externalLink, from, fromBalance, gasStore, netVersion, transaction, origin } = this.props;
return (
<div className={ styles.transaction }>
<div className={ styles.from }>
<div className={ styles.account }>
<Account
address={ from }
balance={ fromBalance }
disabled={ disabled }
externalLink={ externalLink }
netVersion={ netVersion }
/>
</div>
<RequestOrigin origin={ origin } />
</div>
<div className={ styles.method }>
<MethodDecoding
address={ from }
historic={ false }
transaction={
gasStore
? gasStore.overrideTransaction(transaction)
: transaction
}
/>
{ this.renderEditTx() }
</div>
{ children }
</div>
);
}
renderEditTx () {
const { gasStore } = this.props;
if (!gasStore) {
return null;
}
return (
<div className={ styles.editButtonRow }>
<Button
icon={ <GasIcon /> }
label={
<FormattedMessage
id='signer.mainDetails.editTx'
defaultMessage='Edit conditions/gas/gasPrice'
/>
}
onClick={ this.toggleGasEditor }
/>
</div>
);
}
renderTotalValue () {
const { id } = this.props;
const { feeEth, totalValueDisplay, totalValueDisplayWei } = this.state;
const labelId = `totalValue${id}`;
return (
<div>
<div
className={ styles.total }
data-effect='solid'
data-for={ labelId }
data-place='bottom'
data-tip
>
{ totalValueDisplay } <small>ETH</small>
</div>
<ReactTooltip id={ labelId }>
<FormattedMessage
id='signer.mainDetails.tooltips.total1'
defaultMessage='The value of the transaction including the mining fee is {total} {type}.'
values={ {
total: <strong>{ totalValueDisplayWei }</strong>,
type: <small>WEI</small>
} }
/>
<br />
<FormattedMessage
id='signer.mainDetails.tooltips.total2'
defaultMessage='(This includes a mining fee of {fee} {token})'
values={ {
fee: <strong>{ feeEth }</strong>,
token: <small>ETH</small>
} }
/>
</ReactTooltip>
</div>
);
}
renderValue () {
const { id } = this.props;
const { valueDisplay, valueDisplayWei } = this.state;
const labelId = `value${id}`;
return (
<div>
<div
data-effect='solid'
data-for={ labelId }
data-tip
>
<strong>{ valueDisplay } </strong>
<small>ETH</small>
</div>
<ReactTooltip id={ labelId }>
<FormattedMessage
id='signer.mainDetails.tooltips.value1'
defaultMessage='The value of the transaction.'
/>
<br />
<strong>{ valueDisplayWei }</strong> <small>WEI</small>
</ReactTooltip>
</div>
);
}
updateDisplayValues (value, totalValue) {
this.setState({
feeEth: tUtil.calcFeeInEth(totalValue, value),
totalValueDisplay: tUtil.getTotalValueDisplay(totalValue),
totalValueDisplayWei: tUtil.getTotalValueDisplayWei(totalValue),
valueDisplay: tUtil.getValueDisplay(value),
valueDisplayWei: tUtil.getValueDisplayWei(value)
});
}
toggleGasEditor = () => {
this.props.gasStore.setEditing(true);
}
}

View File

@ -1,17 +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/>.
export default from './transactionPending';

View File

@ -1,27 +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 '../../_layout.css';
.container {
display: flex;
padding: 1.5em 1em 1.5em 0;
& > * {
vertical-align: middle;
}
}

View File

@ -1,204 +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 { observer } from 'mobx-react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import HardwareStore from '@parity/shared/mobx/hardwareStore';
import { Button, GasPriceEditor } from '@parity/ui';
import TransactionMainDetails from '../TransactionMainDetails';
import TransactionPendingForm from '../TransactionPendingForm';
import styles from './transactionPending.css';
import * as tUtil from '../util/transaction';
@observer
class TransactionPending extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
};
static propTypes = {
accounts: PropTypes.object.isRequired,
className: PropTypes.string,
date: PropTypes.instanceOf(Date).isRequired,
focus: PropTypes.bool,
gasLimit: PropTypes.object,
id: PropTypes.object.isRequired,
isSending: PropTypes.bool.isRequired,
netVersion: PropTypes.string.isRequired,
nonce: PropTypes.number,
onConfirm: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired,
origin: PropTypes.any,
signerStore: PropTypes.object.isRequired,
transaction: PropTypes.shape({
condition: PropTypes.object,
data: PropTypes.string,
from: PropTypes.string.isRequired,
gas: PropTypes.object.isRequired,
gasPrice: PropTypes.object.isRequired,
to: PropTypes.string,
value: PropTypes.object.isRequired
}).isRequired
};
static defaultProps = {
focus: false,
origin: {
type: 'unknown',
details: ''
}
};
gasStore = new GasPriceEditor.Store(this.context.api, {
condition: this.props.transaction.condition,
gas: this.props.transaction.gas.toFixed(),
gasLimit: this.props.gasLimit,
gasPrice: this.props.transaction.gasPrice.toFixed()
});
hardwareStore = HardwareStore.get(this.context.api);
componentWillMount () {
const { signerStore, transaction } = this.props;
const { from, gas, gasPrice, to, value } = transaction;
const fee = tUtil.getFee(gas, gasPrice); // BigNumber object
const gasPriceEthmDisplay = tUtil.getEthmFromWeiDisplay(gasPrice);
const gasToDisplay = tUtil.getGasDisplay(gas);
const totalValue = tUtil.getTotalValue(fee, value);
this.setState({ gasPriceEthmDisplay, totalValue, gasToDisplay });
this.gasStore.setEthValue(value);
signerStore.fetchBalances([from, to]);
}
render () {
return this.gasStore.isEditing
? this.renderTxEditor()
: this.renderTransaction();
}
renderTransaction () {
const transaction = this.gasStore.overrideTransaction(this.props.transaction);
const { accounts, className, focus, id, isSending, netVersion, origin, signerStore } = this.props;
const { totalValue } = this.state;
const { balances, externalLink } = signerStore;
const { from, value } = transaction;
const fromBalance = balances[from];
const account = accounts[from] || {};
const disabled = account.hardware && !this.hardwareStore.isConnected(from);
return (
<div className={ `${styles.container} ${className}` }>
<TransactionMainDetails
className={ styles.transactionDetails }
disabled={ disabled }
externalLink={ externalLink }
from={ from }
fromBalance={ fromBalance }
gasStore={ this.gasStore }
id={ id }
netVersion={ netVersion }
origin={ origin }
totalValue={ totalValue }
transaction={ transaction }
value={ value }
/>
<TransactionPendingForm
account={ account }
address={ from }
disabled={ disabled }
focus={ focus }
isSending={ isSending }
netVersion={ netVersion }
onConfirm={ this.onConfirm }
onReject={ this.onReject }
dataToSign={ { transaction } }
/>
</div>
);
}
renderTxEditor () {
const { className } = this.props;
return (
<div className={ `${styles.container} ${className}` }>
<GasPriceEditor store={ this.gasStore }>
<Button
label={
<FormattedMessage
id='signer.txPending.buttons.viewToggle'
defaultMessage='view transaction'
/>
}
onClick={ this.toggleGasEditor }
/>
</GasPriceEditor>
</div>
);
}
onConfirm = (data) => {
const { id, transaction } = this.props;
const { password, txSigned, wallet } = data;
const { condition, gas, gasPrice } = this.gasStore.overrideTransaction(transaction);
const options = {
gas,
gasPrice,
id,
password,
txSigned,
wallet
};
if (condition && (condition.block || condition.time)) {
options.condition = condition;
}
this.props.onConfirm(options);
}
onReject = () => {
this.props.onReject(this.props.id);
}
toggleGasEditor = () => {
this.gasStore.setEditing(false);
}
}
function mapStateToProps (state) {
const { accounts } = state.personal;
return {
accounts
};
}
export default connect(
mapStateToProps,
null
)(TransactionPending);

View File

@ -1,17 +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/>.
export default from './transactionPendingForm';

View File

@ -1,44 +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 '../../_layout.css';
.container {
box-sizing: border-box;
padding: 1em 0 0 2em;
flex: 0 0 $statusWidth;
}
.rejectToggle {
display: block;
cursor: pointer;
color: #00e;
opacity: .7;
transition: opacity .5s;
}
.rejectToggle:hover {
opacity: 1;
text-decoration: underline;
}
.rejectToggle svg {
position: relative;
width: 18px !important;
height: 18px !important;
top: 3px;
}

View File

@ -1,137 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { PrevIcon } from '@parity/ui/Icons';
import TransactionPendingFormConfirm from '../TransactionPendingFormConfirm';
import TransactionPendingFormReject from '../TransactionPendingFormReject';
import styles from './transactionPendingForm.css';
export default class TransactionPendingForm extends Component {
static propTypes = {
account: PropTypes.object,
address: PropTypes.string.isRequired,
className: PropTypes.string,
disabled: PropTypes.bool,
focus: PropTypes.bool,
netVersion: PropTypes.string.isRequired,
isSending: PropTypes.bool.isRequired,
onConfirm: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired,
dataToSign: PropTypes.oneOfType([
PropTypes.shape({
transaction: PropTypes.object.isRequired
}),
PropTypes.shape({
data: PropTypes.string.isRequired
}),
PropTypes.shape({
decrypt: PropTypes.string.isRequired
})
]).isRequired
};
static defaultProps = {
account: {},
focus: false
};
state = {
isRejectOpen: false
};
render () {
const { className } = this.props;
return (
<div className={ `${styles.container} ${className}` }>
{ this.renderForm() }
{ this.renderRejectToggle() }
</div>
);
}
renderForm () {
const { account, address, disabled, focus, isSending, netVersion, onConfirm, onReject, dataToSign } = this.props;
if (this.state.isRejectOpen) {
return (
<TransactionPendingFormReject onReject={ onReject } />
);
}
return (
<TransactionPendingFormConfirm
address={ address }
account={ account }
disabled={ disabled }
focus={ focus }
netVersion={ netVersion }
isSending={ isSending }
onConfirm={ onConfirm }
dataToSign={ dataToSign }
/>
);
}
renderRejectToggle () {
const { isRejectOpen } = this.state;
let html;
if (!isRejectOpen) {
html = (
<span>
<FormattedMessage
id='signer.txPendingForm.reject'
defaultMessage='reject request'
/>
</span>
);
} else {
html = (
<span>
<PrevIcon />
<FormattedMessage
id='signer.txPendingForm.changedMind'
defaultMessage="I've changed my mind"
/>
</span>
);
}
return (
<a
className={ styles.rejectToggle }
onClick={ this.onToggleReject }
>
{ html }
</a>
);
}
onToggleReject = () => {
const { isRejectOpen } = this.state;
this.setState({
isRejectOpen: !isRejectOpen
});
}
}

View File

@ -1,17 +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/>.
export default from './transactionPendingFormConfirm';

View File

@ -1,48 +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/>.
*/
.confirmForm {
margin-top: -2em;
}
.confirmButton {
display: block !important;
margin-bottom: 10px;
white-space: nowrap;
}
.signerIcon {
vertical-align: middle;
}
.passwordHint {
font-size: 0.75em;
color: rgba(255, 255, 255, 0.5);
margin-bottom: 0.75em;
}
.passwordHint span {
opacity: 0.85;
}
.fileInput input {
top: 22px;
}
.qr {
margin-bottom: 0.5em;
text-align: center;
}

View File

@ -1,580 +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 keycode from 'keycode';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { FormattedMessage } from 'react-intl';
import ReactTooltip from 'react-tooltip';
import { generateTxQr, generateDecryptQr, generateDataQr } from '@parity/shared/util/qrscan';
import { Button, Form, Input, IdentityIcon, QrCode, QrScan } from '@parity/ui';
import styles from './transactionPendingFormConfirm.css';
const QR_VISIBLE = 1;
const QR_SCAN = 2;
const QR_COMPLETED = 3;
export default class TransactionPendingFormConfirm extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
};
static propTypes = {
account: PropTypes.object,
address: PropTypes.string.isRequired,
disabled: PropTypes.bool,
focus: PropTypes.bool,
netVersion: PropTypes.string.isRequired,
isSending: PropTypes.bool.isRequired,
onConfirm: PropTypes.func.isRequired,
dataToSign: PropTypes.object.isRequired
};
static defaultProps = {
account: {},
focus: false
};
id = Math.random(); // for tooltip
state = {
password: '',
qrState: QR_VISIBLE,
qr: {},
wallet: null,
walletError: null
}
componentDidMount () {
this.focus();
}
componentWillMount () {
this.readNonce();
this.subscribeNonce();
}
componentWillUnmount () {
this.unsubscribeNonce();
}
componentWillReceiveProps (nextProps) {
if (!this.props.focus && nextProps.focus) {
this.focus(nextProps);
}
}
focus (props = this.props) {
if (props.focus) {
const textNode = ReactDOM.findDOMNode(this.refs.input);
if (!textNode) {
return;
}
const inputNode = textNode.querySelector('input');
inputNode && inputNode.focus();
}
}
getPasswordHint () {
const { account } = this.props;
const accountHint = account.meta && account.meta.passwordHint;
if (accountHint) {
return accountHint;
}
const { wallet } = this.state;
const walletHint = wallet && wallet.meta && wallet.meta.passwordHint;
return walletHint || null;
}
// TODO: Now that we have 3 types, it would make sense splitting each into their own
// sub-module and having the consistent bits combined (e.g. i18n, layouts)
render () {
const { account, address, disabled, isSending } = this.props;
const { wallet, walletError } = this.state;
const isAccount = account.external || account.hardware || account.uuid;
const isWalletOk = isAccount || (walletError === null && wallet !== null);
const confirmText = this.renderConfirmButton();
const confirmButton = confirmText
? (
<div
data-effect='solid'
data-for={ `transactionConfirmForm${this.id}` }
data-place='bottom'
data-tip
>
<Button
className={ styles.confirmButton }
disabled={ disabled || isSending || !isWalletOk }
fullWidth
icon={
<IdentityIcon
address={ address }
button
className={ styles.signerIcon }
/>
}
label={ confirmText }
onClick={ this.onConfirm }
/>
</div>
)
: null;
return (
<div className={ styles.confirmForm }>
<Form>
{ this.renderKeyInput() }
{ this.renderQrCode() }
{ this.renderQrScanner() }
{ this.renderPassword() }
{ this.renderHint() }
{ confirmButton }
{ this.renderTooltip() }
</Form>
</div>
);
}
renderConfirmButton () {
const { account, isSending } = this.props;
const { qrState } = this.state;
if (account.external) {
switch (qrState) {
case QR_VISIBLE:
return (
<FormattedMessage
id='signer.txPendingConfirm.buttons.scanSigned'
defaultMessage='Scan Signed QR'
/>
);
case QR_SCAN:
case QR_COMPLETED:
return null;
}
}
return isSending
? (
<FormattedMessage
id='signer.txPendingConfirm.buttons.confirmBusy'
defaultMessage='Confirming...'
/>
)
: (
<FormattedMessage
id='signer.txPendingConfirm.buttons.confirmRequest'
defaultMessage='Confirm Request'
/>
);
}
renderPassword () {
const { account } = this.props;
const { password } = this.state;
if (account.hardware || account.external) {
return null;
}
const isAccount = account.uuid;
return (
<Input
hint={
isAccount
? (
<FormattedMessage
id='signer.txPendingConfirm.password.unlock.hint'
defaultMessage='unlock the account'
/>
)
: (
<FormattedMessage
id='signer.txPendingConfirm.password.decrypt.hint'
defaultMessage='decrypt the key'
/>
)
}
label={
isAccount
? (
<FormattedMessage
id='signer.txPendingConfirm.password.unlock.label'
defaultMessage='Account Password'
/>
)
: (
<FormattedMessage
id='signer.txPendingConfirm.password.decrypt.label'
defaultMessage='Key Password'
/>
)
}
onChange={ this.onModifyPassword }
onKeyDown={ this.onKeyDown }
ref='input'
type='password'
value={ password }
/>
);
}
renderHint () {
const { account, disabled, isSending } = this.props;
const { qrState } = this.state;
if (account.external) {
switch (qrState) {
case QR_VISIBLE:
return (
<div className={ styles.passwordHint }>
<FormattedMessage
id='signer.sending.external.scanTx'
defaultMessage='Please scan the transaction QR on your external device'
/>
</div>
);
case QR_SCAN:
return (
<div className={ styles.passwordHint }>
<FormattedMessage
id='signer.sending.external.scanSigned'
defaultMessage='Scan the QR code of the signed transaction from your external device'
/>
</div>
);
case QR_COMPLETED:
return null;
}
}
if (account.hardware) {
if (isSending) {
return (
<div className={ styles.passwordHint }>
<FormattedMessage
id='signer.sending.hardware.confirm'
defaultMessage='Please confirm the transaction on your attached hardware device'
/>
</div>
);
} else if (disabled) {
return (
<div className={ styles.passwordHint }>
<FormattedMessage
id='signer.sending.hardware.connect'
defaultMessage='Please attach your hardware device before confirming the transaction'
/>
</div>
);
}
}
const passwordHint = this.getPasswordHint();
if (!passwordHint) {
return null;
}
return (
<div className={ styles.passwordHint }>
<FormattedMessage
id='signer.txPendingConfirm.passwordHint'
defaultMessage='(hint) {passwordHint}'
values={ {
passwordHint
} }
/>
</div>
);
}
// TODO: Split into sub-scomponent
renderQrCode () {
const { account } = this.props;
const { qrState, qr } = this.state;
if (!account.external || qrState !== QR_VISIBLE || !qr.value) {
return null;
}
return (
<QrCode
className={ styles.qr }
value={ qr.value }
/>
);
}
// TODO: Split into sub-scomponent
renderQrScanner () {
const { account } = this.props;
const { qrState } = this.state;
if (!account.external || qrState !== QR_SCAN) {
return null;
}
return (
<QrScan
className={ styles.camera }
onScan={ this.onScan }
/>
);
}
renderKeyInput () {
const { account } = this.props;
const { walletError } = this.state;
if (account.uuid || account.wallet || account.hardware || account.external) {
return null;
}
return (
<Input
className={ styles.fileInput }
error={ walletError }
hint={
<FormattedMessage
id='signer.txPendingConfirm.selectKey.hint'
defaultMessage='The keyfile to use for this account'
/>
}
label={
<FormattedMessage
id='signer.txPendingConfirm.selectKey.label'
defaultMessage='Select Local Key'
/>
}
onChange={ this.onKeySelect }
type='file'
/>
);
}
renderTooltip () {
const { account } = this.props;
if (this.state.password.length || account.hardware || account.external) {
return null;
}
return (
<ReactTooltip id={ `transactionConfirmForm${this.id}` }>
<FormattedMessage
id='signer.txPendingConfirm.tooltips.password'
defaultMessage='Please provide a password for this account'
/>
</ReactTooltip>
);
}
onScan = (signature) => {
const { chainId, rlp, tx, data, decrypt } = this.state.qr;
if (!signature) {
return;
}
if (signature && signature.substr(0, 2) !== '0x') {
signature = `0x${signature}`;
}
this.setState({ qrState: QR_COMPLETED });
if (tx) {
this.props.onConfirm({
txSigned: {
chainId,
rlp,
signature,
tx
}
});
return;
}
if (decrypt) {
this.props.onConfirm({
decrypted: {
decrypt,
msg: signature
}
});
return;
}
this.props.onConfirm({
dataSigned: {
data,
signature
}
});
}
onKeySelect = (event) => {
// Check that file have been selected
if (event.target.files.length === 0) {
return this.setState({
wallet: null,
walletError: null
});
}
const fileReader = new FileReader();
fileReader.onload = (e) => {
try {
const wallet = JSON.parse(e.target.result);
try {
if (wallet && typeof wallet.meta === 'string') {
wallet.meta = JSON.parse(wallet.meta);
}
} catch (e) {}
this.setState({
wallet,
walletError: null
});
} catch (error) {
this.setState({
wallet: null,
walletError: (
<FormattedMessage
id='signer.txPendingConfirm.errors.invalidWallet'
defaultMessage='Given wallet file is invalid.'
/>
)
});
}
};
fileReader.readAsText(event.target.files[0]);
}
onModifyPassword = (event) => {
const password = event.target.value;
this.setState({
password
});
}
onConfirm = () => {
const { account } = this.props;
const { password, qrState, wallet } = this.state;
if (account.external && qrState === QR_VISIBLE) {
return this.setState({ qrState: QR_SCAN });
}
this.props.onConfirm({
password,
wallet
});
}
generateQr = () => {
const { api } = this.context;
const { netVersion, dataToSign } = this.props;
const { transaction, data, decrypt } = dataToSign;
const setState = qr => {
this.setState({ qr });
};
if (transaction) {
generateTxQr(api, netVersion, transaction).then(setState);
return;
}
if (decrypt) {
generateDecryptQr(decrypt).then(setState);
return;
}
generateDataQr(data).then(setState);
}
onKeyDown = (event) => {
const codeName = keycode(event);
if (codeName !== 'enter') {
return;
}
this.onConfirm();
}
// FIXME: Sadly the API subscription channels currently does not allow for specific values,
// rather it can only do general queries where parameters are not specified. Hence we are
// polling for the nonce here. Since we are moving to node-based subscriptions on the API layer,
// this can be optimised when the subscription mechanism is reworked to conform.
subscribeNonce () {
const nonceTimerId = setInterval(this.readNonce, 1000);
this.setState({ nonceTimerId });
}
unsubscribeNonce () {
const { nonceTimerId } = this.state;
if (!nonceTimerId) {
return;
}
clearInterval(nonceTimerId);
}
readNonce = () => {
const { api } = this.context;
const { account, dataToSign } = this.props;
const { qr } = this.state;
if ((dataToSign.data || dataToSign.decrypt) && qr && !qr.value) {
this.generateQr();
return;
}
if (!account || !account.external || !api.transport.isConnected || !dataToSign.transaction) {
return;
}
return api.parity
.nextNonce(account.address)
.then((newNonce) => {
const { nonce } = this.state.qr;
if (!nonce || !newNonce.eq(nonce)) {
this.generateQr();
}
});
}
}

View File

@ -1,139 +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 { shallow } from 'enzyme';
import React from 'react';
import sinon from 'sinon';
import TransactionPendingFormConfirm from './';
const ADDR_NORMAL = '0x0123456789012345678901234567890123456789';
const ADDR_WALLET = '0x1234567890123456789012345678901234567890';
const ADDR_HARDWARE = '0x2345678901234567890123456789012345678901';
const ADDR_SIGN = '0x3456789012345678901234567890123456789012';
const ACCOUNTS = {
[ADDR_NORMAL]: {
address: ADDR_NORMAL,
uuid: ADDR_NORMAL
},
[ADDR_WALLET]: {
address: ADDR_WALLET,
wallet: true
},
[ADDR_HARDWARE]: {
address: ADDR_HARDWARE,
hardware: true
}
};
let component;
let instance;
let onConfirm;
function render (address) {
onConfirm = sinon.stub();
component = shallow(
<TransactionPendingFormConfirm
account={ ACCOUNTS[address] }
address={ address }
onConfirm={ onConfirm }
isSending={ false }
dataToSign={ {} }
/>
);
instance = component.instance();
return component;
}
describe('views/Signer/TransactionPendingFormConfirm', () => {
describe('normal accounts', () => {
beforeEach(() => {
render(ADDR_NORMAL);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('does not render the key input', () => {
expect(instance.renderKeyInput()).to.be.null;
});
it('renders the password', () => {
expect(instance.renderPassword()).not.to.be.null;
});
});
describe('hardware accounts', () => {
beforeEach(() => {
render(ADDR_HARDWARE);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('does not render the key input', () => {
expect(instance.renderKeyInput()).to.be.null;
});
it('does not render the password', () => {
expect(instance.renderPassword()).to.be.null;
});
});
describe('wallet accounts', () => {
beforeEach(() => {
render(ADDR_WALLET);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('does not render the key input', () => {
expect(instance.renderKeyInput()).to.be.null;
});
it('renders the password', () => {
expect(instance.renderPassword()).not.to.be.null;
});
});
describe('signing accounts', () => {
beforeEach(() => {
render(ADDR_SIGN);
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
it('renders the key input', () => {
expect(instance.renderKeyInput()).not.to.be.null;
});
it('renders the password', () => {
expect(instance.renderPassword()).not.to.be.null;
});
it('renders the hint', () => {
expect(instance.renderHint()).to.be.null;
});
});
});

View File

@ -1,17 +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/>.
export default from './transactionPendingFormReject';

View File

@ -1,26 +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/>.
*/
/* the rejection button itself, once .reject has been pressed */
.rejectButton {
display: block !important;
margin-bottom: 5px;
}
.rejectText {
margin-bottom: 10px;
}

View File

@ -1,63 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { Button } from '@parity/ui';
import styles from './transactionPendingFormReject.css';
export default class TransactionPendingFormReject extends Component {
static propTypes = {
onReject: PropTypes.func.isRequired,
className: PropTypes.string
};
render () {
const { onReject } = this.props;
return (
<div>
<div className={ styles.rejectText }>
<FormattedMessage
id='signer.txPendingReject.info'
defaultMessage='Are you sure you want to reject request?'
/>
<br />
<strong>
<FormattedMessage
id='signer.txPendingReject.undone'
defaultMessage='This cannot be undone'
/>
</strong>
</div>
<Button
onClick={ onReject }
className={ styles.rejectButton }
fullWidth
label={
<FormattedMessage
id='signer.txPendingReject.buttons.reject'
defaultMessage='Reject Request'
/>
}
/>
</div>
);
}
}

View File

@ -1,17 +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/>.
export default from './txHashLink';

View File

@ -1,43 +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 React, { Component } from 'react';
import PropTypes from 'prop-types';
import { txLink } from '@parity/etherscan/links';
export default class TxHashLink extends Component {
static propTypes = {
children: PropTypes.node,
className: PropTypes.string,
netVersion: PropTypes.string.isRequired,
txHash: PropTypes.string.isRequired
}
render () {
const { children, className, netVersion, txHash } = this.props;
return (
<a
className={ className }
href={ txLink(txHash, false, netVersion) }
target='_blank'
>
{ children || txHash }
</a>
);
}
}

View File

@ -1,38 +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/>.
const isLogging = process.env.LOGGING;
export default logger();
function logger () {
return isLogging ? devLogger() : prodLogger();
}
function prodLogger () {
return {
log: noop,
info: noop,
error: noop,
warn: noop
};
}
function devLogger () {
return console;
}
function noop () {}

View File

@ -1,21 +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 { isValidElement } from 'react';
export function isReactComponent (componentOrElem) {
return isValidElement(componentOrElem) && typeof componentOrElem.type === 'function';
}

View File

@ -1,115 +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 BigNumber from 'bignumber.js';
const WEI_TO_ETH_MULTIPLIER = 0.000000000000000001;
const WEI_TO_SZABU_MULTIPLIER = 0.000000000001;
export const getShortData = _getShortData;
// calculations
export const getFee = _getFee;
export const calcFeeInEth = _calcFeeInEth;
export const getTotalValue = _getTotalValue;
// displays
export const getSzaboFromWeiDisplay = _getSzaboFromWeiDisplay;
export const getValueDisplay = _getValueDisplay;
export const getValueDisplayWei = _getValueDisplayWei;
export const getTotalValueDisplay = _getTotalValueDisplay;
export const getTotalValueDisplayWei = _getTotalValueDisplayWei;
export const getEthmFromWeiDisplay = _getEthmFromWeiDisplay;
export const getGasDisplay = _getGasDisplay;
function _getShortData (data) {
if (data.length <= 3) {
return data;
}
return data.substr(0, 3) + '...';
}
/*
* @param {hex string} gas
* @param {wei hex string} gasPrice
* @return {BigNumber} fee in wei
*/
function _getFee (gas, gasPrice) {
gas = new BigNumber(gas);
gasPrice = new BigNumber(gasPrice);
return gasPrice.times(gas);
}
function _calcFeeInEth (totalValue, value) {
let fee = new BigNumber(totalValue).sub(new BigNumber(value));
return fee.times(WEI_TO_ETH_MULTIPLIER).toFormat(7);
}
/*
* @param {wei BigNumber} fee
* @param {wei hex string} value
* @return {BigNumber} total value in wei
*/
function _getTotalValue (fee, value) {
value = new BigNumber(value);
return fee.plus(value);
}
/*
* @param {wei hex string} gasPrice
* @return {string} szabo gas price with unit [szabo] i.e. 21,423 [szabo]
*/
function _getSzaboFromWeiDisplay (gasPrice) {
gasPrice = new BigNumber(gasPrice);
return gasPrice.times(WEI_TO_SZABU_MULTIPLIER).toPrecision(5);
}
/*
* @param {wei hex string} value
* @return {string} value in WEI nicely formatted
*/
function _getValueDisplay (value) {
value = new BigNumber(value);
return value.times(WEI_TO_ETH_MULTIPLIER).toFormat(5);
}
function _getValueDisplayWei (value) {
value = new BigNumber(value);
return value.toFormat(0);
}
/*
* @param {wei hex string} totalValue
* @return {string} total value (including fee) with units i.e. 1.32 [eth]
*/
function _getTotalValueDisplay (totalValue) {
totalValue = new BigNumber(totalValue);
return totalValue.times(WEI_TO_ETH_MULTIPLIER).toFormat(5);
}
function _getTotalValueDisplayWei (totalValue) {
totalValue = new BigNumber(totalValue);
return totalValue.toFormat(0);
}
function _getEthmFromWeiDisplay (weiHexString) {
const value = new BigNumber(weiHexString);
return value.times(WEI_TO_ETH_MULTIPLIER).times(1e7).toFixed(5);
}
function _getGasDisplay (gas) {
return new BigNumber(gas).times(1e-7).toFormat(4);
}

View File

@ -1,79 +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 BigNumber from 'bignumber.js';
import { getShortData, getFee, getTotalValue } from './transaction';
describe('Signer/components/util/transaction', () => {
describe('getEstimatedMiningTime', () => {
it('should return estimated mining time', () => {
});
});
describe('getShortData', () => {
it('should return short data', () => {
// given
const data = '0xh87dY78';
// when
const res = getShortData(data);
// then
expect(res).to.equal('0xh...');
});
it('should return data as is', () => {
// given
const data = '0x0';
// when
const shortData = getShortData(data);
// then
expect(shortData).to.equal('0x0');
});
});
describe('getFee', () => {
it('should return wei BigNumber object equals to gas * gasPrice', () => {
// given
const gas = '0x76c0'; // 30400
const gasPrice = '0x9184e72a000'; // 10000000000000 wei
// when
const fee = getFee(gas, gasPrice);
// then
expect(fee).to.be.an.instanceOf(BigNumber);
expect(fee.toString()).to.be.equal('304000000000000000'); // converting to string due to https://github.com/MikeMcl/bignumber.js/issues/11
});
});
describe('getTotalValue', () => {
it('should return wei BigNumber totalValue equals to value + fee', () => {
// given
const fee = new BigNumber(304000000000000000); // wei
const value = '0x9184e72a'; // 2441406250 wei
// when
const totalValue = getTotalValue(fee, value);
// then
expect(totalValue).to.be.an.instanceOf(BigNumber);
expect(totalValue.toString()).to.be.equal('304000002441406250'); // converting to string due to https://github.com/MikeMcl/bignumber.js/issues/11
});
});
});

View File

@ -1,107 +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 { isEqual } from 'lodash';
import { action, observable } from 'mobx';
export default class SignerStore {
@observable balances = {};
@observable localHashes = [];
externalLink = '';
constructor (api, withLocalTransactions = false, externalLink = '') {
this._api = api;
this._timeoutId = 0;
this.externalLink = externalLink;
if (withLocalTransactions) {
this.fetchLocalTransactions();
}
}
@action setBalance = (address, balance) => {
this.setBalances({ [address]: balance });
}
@action setBalances = (balances) => {
this.balances = Object.assign({}, this.balances, balances);
}
@action setLocalHashes = (localHashes = []) => {
// Use slice to make sure they are both Arrays (MobX uses Objects for Observable Arrays)
if (!isEqual(localHashes.slice(), this.localHashes.slice())) {
this.localHashes = localHashes;
}
}
@action unsubscribe () {
if (this._timeoutId) {
clearTimeout(this._timeoutId);
}
}
fetchBalance (address) {
this._api.eth
.getBalance(address)
.then((balance) => {
this.setBalance(address, balance);
})
.catch((error) => {
console.warn('Store:fetchBalance', error);
});
}
fetchBalances (_addresses) {
const addresses = _addresses.filter((address) => address) || [];
if (!addresses.length) {
return;
}
Promise
.all(addresses.map((address) => this._api.eth.getBalance(address)))
.then((_balances) => {
this.setBalances(
addresses.reduce((balances, address, index) => {
balances[address] = _balances[index];
return balances;
}, {})
);
})
.catch((error) => {
console.warn('Store:fetchBalances', error);
});
}
fetchLocalTransactions = () => {
const nextTimeout = () => {
this._timeoutId = setTimeout(this.fetchLocalTransactions, 1500);
};
this._api.parity
.localTransactions()
.then((localTransactions) => {
const keys = Object
.keys(localTransactions)
.filter((key) => localTransactions[key].status !== 'canceled');
this.setLocalHashes(keys);
})
.then(() => nextTimeout())
.catch(() => nextTimeout());
}
}