bundle
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 6.9 KiB |
BIN
images/case.png
Before Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 4.8 KiB |
33
package.json
@ -21,29 +21,32 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"bowser": "^1.9.2",
|
||||
"color-hash": "^1.0.3",
|
||||
"ethereumjs-tx": "^1.3.3",
|
||||
"ethereumjs-units": "^0.2.0",
|
||||
"ethereumjs-util": "^5.1.2",
|
||||
"hdkey": "0.7.1",
|
||||
"ethereumjs-util": "^5.1.4",
|
||||
"hdkey": "^0.8.0",
|
||||
"path-to-regexp": "^2.1.0",
|
||||
"raf": "^3.4.0",
|
||||
"raven-js": "^3.22.3",
|
||||
"rc-tooltip": "^3.7.0",
|
||||
"react": "^16.1.1",
|
||||
"react": "^16.2.0",
|
||||
"react-blockies": "^1.2.2",
|
||||
"react-css-transition": "^0.7.4",
|
||||
"react-dom": "^16.1.1",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-ellipsis-text": "^1.0.0",
|
||||
"react-hot-loader": "^3.1.3",
|
||||
"react-qr-svg": "^2.1.0",
|
||||
"react-redux": "^5.0.6",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"react-router-redux": "next",
|
||||
"react-scale-text": "^1.2.2",
|
||||
"react-select": "^1.1.0",
|
||||
"react-select": "^1.2.1",
|
||||
"react-transition-group": "^2.2.1",
|
||||
"redux": "^3.7.2",
|
||||
"redux-logger": "^3.0.6",
|
||||
"redux-raven-middleware": "^1.2.0",
|
||||
"redux-thunk": "^2.2.0",
|
||||
"web3": "^0.19.0"
|
||||
},
|
||||
@ -56,22 +59,22 @@
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-plugin-webpack-alias": "^2.1.2",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "^0.28.4",
|
||||
"copy-webpack-plugin": "^4.4.1",
|
||||
"css-loader": "^0.28.9",
|
||||
"express": "^4.15.3",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^0.11.2",
|
||||
"file-loader": "^1.1.9",
|
||||
"html-webpack-plugin": "^2.29.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"less": "^2.7.2",
|
||||
"less": "^3.0.1",
|
||||
"less-loader": "^4.0.5",
|
||||
"open": "^0.0.5",
|
||||
"style-loader": "^0.18.2",
|
||||
"webpack": "^3.4.1",
|
||||
"webpack-dev-middleware": "^1.11.0",
|
||||
"webpack-hot-middleware": "^2.18.0",
|
||||
"style-loader": "^0.20.2",
|
||||
"webpack": "3.11.0",
|
||||
"webpack-dev-middleware": "2.0.5",
|
||||
"webpack-hot-middleware": "2.21.0",
|
||||
"webpack-merge": "^4.1.1",
|
||||
"whatwg-fetch": "^2.0.3",
|
||||
"yargs": "^10.0.3"
|
||||
"yargs": "11.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,8 @@
|
||||
"coins": [
|
||||
{
|
||||
"name": "Ethereum Ropsten",
|
||||
"symbol": "eth",
|
||||
"network": "ropsten-eth",
|
||||
"shortcut": "eth",
|
||||
"symbol": "tETH",
|
||||
"network": "ropsten",
|
||||
"bip44": "m/44'/60'/0'/0",
|
||||
"defaultGasPrice": 64,
|
||||
"defaultGasLimit": 21000,
|
||||
@ -38,16 +37,15 @@
|
||||
"urls": [
|
||||
"https://ropsten.infura.io/QGyVKozSUEh2YhL4s2G4",
|
||||
"http://10.34.2.5:8545"
|
||||
],
|
||||
"explorer": "https://blockexplorer.com"
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"explorer": "https://ropsten.etherscan.io"
|
||||
},
|
||||
{
|
||||
"name": "Ethereum Rinkeby",
|
||||
"symbol": "etc",
|
||||
"network": "ropsten-eth",
|
||||
"shortcut": "etc",
|
||||
"symbol": "tETH",
|
||||
"network": "rinkeby",
|
||||
"bip44": "m/44'/61'/0'/0",
|
||||
"defaultGasPrice": 64,
|
||||
"defaultGasLimit": 21000,
|
||||
@ -56,19 +54,28 @@
|
||||
{
|
||||
"name": "TREZOR Wallet - Ethereum",
|
||||
"urls": [
|
||||
"https://rinkeby.infura.io/QGyVKozSUEh2YhL4s2G4",
|
||||
"http://10.34.2.5:8545"
|
||||
],
|
||||
"explorer": "https://blockexplorer.com"
|
||||
"https://rinkeby.infura.io/QGyVKozSUEh2YhL4s2G4"
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"explorer": "https://rinkeby.etherscan.io"
|
||||
}
|
||||
],
|
||||
|
||||
"fiatValueTickers": [
|
||||
|
||||
{
|
||||
"network": "ropsten",
|
||||
"url": "https://api.coinmarketcap.com/v1/ticker/ethereum/"
|
||||
},
|
||||
{
|
||||
"network": "rinkeby",
|
||||
"url": "https://api.coinmarketcap.com/v1/ticker/ethereum-classic/"
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
|
||||
|
||||
"bridge": {
|
||||
"url": "https://localback.net:21324",
|
||||
"configUrl": "data/config_signed.bin",
|
||||
@ -76,6 +83,20 @@
|
||||
},
|
||||
"extensionId": "jcjjhjgimijdkoamemaghajlhegmoclj",
|
||||
"storageVersion": "1.1.0",
|
||||
"metadataVersion": "1.0.0"
|
||||
"metadataVersion": "1.0.0",
|
||||
|
||||
|
||||
"supportedBrowsers": {
|
||||
"chrome": {
|
||||
"version": 59,
|
||||
"download": "https://www.google.com/chrome/",
|
||||
"update": "https://support.google.com/chrome/answer/95414"
|
||||
},
|
||||
"firefox": {
|
||||
"version": 54,
|
||||
"download": "https://www.mozilla.org/en-US/firefox/new/",
|
||||
"update": "https://support.mozilla.org/en-US/kb/update-firefox-latest-version"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="819.2" descent="-204.8" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " d="" />
|
||||
<glyph unicode="+" glyph-name="plus" d="M384 951.467h170.667q17.92 0 30.293-12.373t12.373-30.293v-298.667h298.667q17.92 0 30.293-12.373t12.373-30.293v-170.667q0-17.92-12.373-30.293t-30.293-12.373h-298.667v-298.667q0-17.92-12.373-30.293t-30.293-12.373h-170.667q-17.92 0-30.293 12.373t-12.373 30.293v298.667h-298.667q-17.92 0-30.293 12.373t-12.373 30.293v170.667q0 17.92 12.373 30.293t30.293 12.373h298.667v298.667q0 17.92 12.373 30.293t30.293 12.373z" />
|
||||
<glyph unicode="_" glyph-name="trezor" horiz-adv-x="679" d="M339.471 896c-142.287 0-257.634-115.347-257.634-257.634v-96.329c-49.928-8.931-81.837-21.275-81.837-37.035v-513.942l335.777-119.061 343.165 119.061v513.942c0 15.76-31.909 28.104-81.837 37.035v96.329c0 142.287-115.347 257.634-257.634 257.634zM339.471 789.915c83.698 0 151.549-67.852 151.549-151.549v-83.92c-94.502 6.876-208.597 6.876-303.099 0v83.92c0 83.698 67.852 151.549 151.549 151.549zM333.030 430.554c117.072-0.19 233.765-8.903 233.765-25.574v-324.695l-231.208-85.531-238.596 85.531v324.695c1.515 17.428 118.966 25.763 236.038 25.574z" />
|
||||
<glyph unicode="" glyph-name="settings" d="M512 1014.613q28.16 0 63.147-4.267l32.427-129.707 4.267-0.853q41.813-11.947 80.213-33.28l4.267-1.707 114.347 68.267q52.053-40.96 88.747-89.6l-68.267-114.347 2.56-4.267q21.333-37.547 33.28-79.36l0.853-5.12 129.707-32.427q4.267-36.693 4.267-62.293 0-29.013-4.267-63.147l-129.707-32.427-0.853-5.12q-12.8-41.813-33.28-79.36l-2.56-4.267 68.267-114.347q-40.96-52.053-88.747-89.6l-114.347 69.12-4.267-2.56q-37.547-21.333-80.213-33.28l-4.267-1.707-32.427-128.853q-36.693-4.267-63.147-4.267-28.16 0-63.147 4.267l-32.427 128.853-4.267 1.707q-41.813 11.947-80.213 33.28l-4.267 2.56-114.347-69.12q-51.2 40.96-88.747 89.6l68.267 114.347-2.56 4.267q-21.333 38.4-32.427 79.36l-1.707 5.12-128.853 32.427q-5.12 35.84-5.12 63.147 0 28.16 5.12 62.293l128.853 32.427 1.707 5.12q11.093 40.96 32.427 79.36l2.56 4.267-68.267 114.347q40.107 52.053 89.6 89.6l113.493-68.267 4.267 1.707q38.4 21.333 80.213 33.28l4.267 0.853 32.427 129.707q36.693 4.267 63.147 4.267zM512 708.267q-75.947 0-129.707-53.76t-53.76-129.28 53.76-129.28 129.707-53.76 129.707 53.76 53.76 129.28-53.76 129.28-129.707 53.76z" />
|
||||
<glyph unicode="" glyph-name="refresh" d="M808.107 917.333l115.2 115.2q5.973 5.973 10.667 4.267t4.693-11.093v-308.053q0-9.387-6.4-15.787t-15.787-6.4h-308.053q-9.387 0-11.093 4.693t4.267 10.667l114.347 114.347q-93.867 64-203.947 64-98.987 0-183.040-48.64t-132.693-132.693-48.64-183.040h-128q0 99.84 38.827 191.147t104.96 157.44 157.44 104.96 191.147 38.827q163.84 0 296.107-99.84zM876.373 524.8h128q0-99.84-38.827-191.147t-104.96-157.44-157.44-104.96-191.147-38.827q-163.84 0-296.96 100.693l-114.347-114.347q-5.973-6.827-10.667-4.693t-4.693 10.667v307.2q0 9.387 6.4 15.787t15.787 6.4h307.2q8.533 0 10.667-4.693t-4.693-10.667l-113.493-113.493q93.867-64.853 204.8-64.853 98.987 0 183.040 48.64t132.693 132.693 48.64 183.040z" />
|
||||
<glyph unicode="" glyph-name="eye" d="M600 966q82 0 160.5-22.5t140-59 116.5-82.5 94.5-95 68-95 42.5-82.5 14-57.5-14-57.5-43-82.5-68.5-95-94.5-95-116.5-82.5-140-59-159.5-22.5-159.5 22.5-140 59-116.5 82.5-94.5 95-68.5 95-43 82.5-14 57.5 14 57.5 42.5 82.5 68 95 94.5 95 116.5 82.5 140 59 160.5 22.5zM888 701q-15 15-18 12t5-22q25-57 25-119 0-124-88-212t-212-88-212 88-88 212q0 59 23 114 8 19 4.5 22t-17.5-12q-70-69-160-184-13-16-15-40.5t9-42.5q22-36 47-71t70-82 92.5-81 113-58.5 133.5-24.5 133.5 24 113 58.5 92.5 81.5 70 81.5 47 70.5q11 18 9 42.5t-14 41.5q-90 117-163 189zM448 599l-35-36q-15-15-19.5-38.5t4.5-41.5q37-68 93-116 16-13 38.5-11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44-89 117-11 18-28 20t-32-12z" />
|
||||
<glyph unicode="" glyph-name="arrow-up" d="M938.667 363.52l-168.96-169.813-301.227 301.227-301.227-301.227-168.107 169.813 470.187 470.187z" />
|
||||
<glyph unicode="" glyph-name="arrow-dn" d="M939.52 686.080l-469.333-470.187-470.187 470.187 168.96 169.813 301.227-301.227 301.227 301.227z" />
|
||||
<glyph unicode="" glyph-name="warning" d="M512 739.226l429.102-855.226h-858.206l429.104 855.226zM512 832c-22.070 0-44.14-14.882-60.884-44.648l-437.074-871.112c-33.486-59.532-5-108.24 63.304-108.24h869.308c68.3 0 96.792 48.708 63.3 108.24h0.002l-437.074 871.112c-16.742 29.766-38.812 44.648-60.882 44.648v0zM576 0c0-35.346-28.654-64-64-64s-64 28.654-64 64c0 35.346 28.654 64 64 64s64-28.654 64-64zM512 128c-35.346 0-64 28.654-64 64v192c0 35.346 28.654 64 64 64s64-28.654 64-64v-192c0-35.346-28.654-64-64-64z" />
|
||||
<glyph unicode="" glyph-name="info" d="M448 528c0 26.4 21.6 48 48 48h32c26.4 0 48-21.6 48-48v-32c0-26.4-21.6-48-48-48h-32c-26.4 0-48 21.6-48 48v32zM640 64h-256v64h64v192h-64v64h192v-256h64zM512 832c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM512-96c-229.75 0-416 186.25-416 416s186.25 416 416 416 416-186.25 416-416-186.25-416-416-416z" />
|
||||
<glyph unicode="" glyph-name="cross" d="M1014.662 9.34c-0.004 0.004-0.008 0.008-0.012 0.010l-310.644 310.65 310.644 310.65c0.004 0.004 0.008 0.006 0.012 0.010 3.344 3.346 5.762 7.254 7.312 11.416 4.246 11.376 1.824 24.682-7.324 33.83l-146.746 146.746c-9.148 9.146-22.45 11.566-33.828 7.32-4.16-1.55-8.070-3.968-11.418-7.31 0-0.004-0.004-0.006-0.008-0.010l-310.648-310.652-310.648 310.65c-0.004 0.004-0.006 0.006-0.010 0.010-3.346 3.342-7.254 5.76-11.414 7.31-11.38 4.248-24.682 1.826-33.83-7.32l-146.748-146.748c-9.148-9.148-11.568-22.452-7.322-33.828 1.552-4.16 3.97-8.072 7.312-11.416 0.004-0.002 0.006-0.006 0.010-0.010l310.65-310.648-310.65-310.652c-0.002-0.004-0.006-0.006-0.008-0.010-3.342-3.346-5.76-7.254-7.314-11.414-4.248-11.376-1.826-24.682 7.322-33.83l146.748-146.746c9.15-9.148 22.452-11.568 33.83-7.322 4.16 1.552 8.070 3.97 11.416 7.312 0.002 0.004 0.006 0.006 0.010 0.010l310.648 310.65 310.648-310.65c0.004-0.002 0.008-0.006 0.012-0.008 3.348-3.344 7.254-5.762 11.414-7.314 11.378-4.246 24.684-1.826 33.828 7.322l146.746 146.748c9.148 9.148 11.57 22.454 7.324 33.83-1.552 4.16-3.97 8.068-7.314 11.414z" />
|
||||
<glyph unicode="" glyph-name="checkmark" d="M864 704l-480-480-224 224-160-160 384-384 640 640z" />
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 6.4 KiB |
@ -18,24 +18,25 @@
|
||||
<glyph unicode="" glyph-name="icon-warning" d="M795.616 224.992l-264.896 465.44c-10.272 18.080-27.168 18.080-37.504 0l-264.864-465.44c-10.272-18.176-1.696-32.992 19.040-32.992h529.184c20.8 0 29.376 14.816 19.040 32.992zM549.76 286.88c0-10.464-8.48-18.976-18.912-18.976h-37.792c-10.336 0-18.912 8.512-18.912 18.976v37.952c0 10.464 8.576 18.976 18.912 18.976h37.792c10.4 0 18.912-8.544 18.912-18.976v-37.952zM549.76 400.736c0-10.464-8.48-18.976-18.912-18.976h-37.792c-10.336 0-18.912 8.512-18.912 18.976v113.856c0 10.464 8.576 18.976 18.912 18.976h37.792c10.4 0 18.912-8.544 18.912-18.976v-113.856z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-down" d="M757.216 539.072l-219.616-237.44c-8.128-8.576-19.296-13.632-31.040-13.632-11.744 0.288-23.2 5.056-31.040 13.664l-208.768 227.040c-15.36 16.928-14.176 43.040 3.008 58.176 16.864 15.424 43.392 13.952 59.040-2.656l177.76-193.504 188.608 203.904c7.52 8 18.080 12.768 29.216 13.344 11.456 0.608 21.696-3.264 30.112-10.688 16.896-15.456 18.080-41.568 2.72-58.208z" />
|
||||
<glyph unicode="" glyph-name="icon-close" d="M754.816 270.080c17.6-17.6 17.6-46.72 0-64.64-8.96-8.64-20.48-13.44-32.64-13.44s-23.68 4.8-32.32 13.44l-177.888 177.92-177.888-177.92c-16.32-16.96-47.040-17.6-64.64 0-17.92 17.92-17.92 47.040 0 64.64l178.208 177.92-178.208 177.92c-17.92 17.92-17.92 46.72 0 64.64 17.28 17.28 47.36 17.28 64.64 0l177.888-177.92 177.888 177.92c17.92 17.92 47.040 17.92 64.96 0 17.6-17.92 17.6-46.72 0-64.64l-178.24-177.92 178.24-177.92z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-left" d="M603.072 202.784l-237.44 219.616c-8.576 8.128-13.632 19.296-13.632 31.040 0.288 11.744 5.056 23.2 13.664 31.040l227.040 208.768c16.928 15.36 43.040 14.176 58.176-3.008 15.424-16.864 13.952-43.392-2.656-59.040l-193.504-177.76 203.904-188.608c8-7.52 12.768-18.080 13.344-29.216 0.608-11.456-3.264-21.696-10.688-30.112-15.456-16.896-41.568-18.080-58.208-2.72z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-up" d="M757.216 356.928l-219.616 237.44c-8.128 8.576-19.296 13.632-31.040 13.632-11.744-0.288-23.2-5.056-31.040-13.664l-208.768-227.040c-15.36-16.928-14.176-43.040 3.008-58.176 16.864-15.424 43.392-13.952 59.040 2.656l177.76 193.504 188.608-203.904c7.52-8 18.080-12.768 29.216-13.344 11.456-0.608 21.696 3.264 30.112 10.688 16.896 15.456 18.080 41.568 2.72 58.208z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-right2" d="M420.928 202.784l237.44 219.616c8.576 8.128 13.632 19.296 13.632 31.040-0.288 11.744-5.056 23.2-13.664 31.040l-227.040 208.768c-16.928 15.36-43.040 14.176-58.176-3.008-15.424-16.864-13.952-43.392 2.656-59.040l193.504-177.76-203.904-188.608c-8-7.52-12.768-18.080-13.344-29.216-0.608-11.456 3.264-21.696 10.688-30.112 15.456-16.896 41.568-18.080 58.208-2.72z" />
|
||||
<glyph unicode="" glyph-name="icon-plus" d="M768 448c0-22.080-17.92-40-40-40h-176v-176c0-22.080-17.92-40-40-40s-40 17.92-40 40v176h-176c-22.080 0-40 17.92-40 40s17.92 40 40 40h176v176c0 22.080 17.92 40 40 40s40-17.92 40-40v-176h176c22.080 0 40-17.92 40-40z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-up" d="M757.216 356.928l-219.616 237.44c-8.128 8.576-19.296 13.632-31.040 13.632-11.744-0.288-23.2-5.056-31.040-13.664l-208.768-227.040c-15.36-16.928-14.176-43.040 3.008-58.176 16.864-15.424 43.392-13.952 59.040 2.656l177.76 193.504 188.608-203.904c7.52-8 18.080-12.768 29.216-13.344 11.456-0.608 21.696 3.264 30.112 10.688 16.896 15.456 18.080 41.568 2.72 58.208z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-right2" d="M420.928 202.784l237.44 219.616c8.576 8.128 13.632 19.296 13.632 31.040-0.288 11.744-5.056 23.2-13.664 31.040l-227.040 208.768c-16.928 15.36-43.040 14.176-58.176-3.008-15.424-16.864-13.952-43.392 2.656-59.040l193.504-177.76-203.904-188.608c-8-7.52-12.768-18.080-13.344-29.216-0.608-11.456 3.264-21.696 10.688-30.112 15.456-16.896 41.568-18.080 58.208-2.72z" />
|
||||
<glyph unicode="" glyph-name="icon-plus" d="M768 448c0-22.080-17.92-40-40-40h-176v-176c0-22.080-17.92-40-40-40s-40 17.92-40 40v176h-176c-22.080 0-40 17.92-40 40s17.92 40 40 40h176v176c0 22.080 17.92 40 40 40s40-17.92 40-40v-176h176c22.080 0 40-17.92 40-40z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-right" d="M420.928 202.784l237.44 219.616c8.576 8.128 13.632 19.296 13.632 31.040-0.288 11.744-5.056 23.2-13.664 31.040l-227.040 208.768c-16.928 15.36-43.040 14.176-58.176-3.008-15.424-16.864-13.952-43.392 2.656-59.040l193.504-177.76-203.904-188.608c-8-7.52-12.768-18.080-13.344-29.216-0.608-11.456 3.264-21.696 10.688-30.112 15.456-16.896 41.568-18.080 58.208-2.72z" />
|
||||
<glyph unicode="" glyph-name="icon-help" d="M693.024 629.056c-99.968 99.936-262.080 99.936-362.048 0s-99.968-262.112 0-362.080c99.968-100 262.144-99.936 362.048 0 99.968 99.904 99.968 262.176 0 362.080zM501.216 242.048c-27.808 0-50.496 22.464-50.496 50.048 0 28.32 22.176 50.528 50.496 50.528 27.616 0 50.048-22.656 50.048-50.528 0.032-27.168-22.88-50.048-50.048-50.048zM536.416 417.536v-27.744c0-13.504-5.28-18.784-18.784-18.784h-36.224c-13.504 0-18.72 5.28-18.72 18.784v61.984c0 15.68 16.064 20.352 30.208 24.48 3.456 1.056 7.040 2.080 10.496 3.264 18.336 6.592 29.696 14.816 29.696 35.296 0 6.656 0 26.816-32.832 26.816-20.224 0-38.624-7.776-49.6-12.416-6.208-2.624-9.28-3.904-12.384-3.904-6.336 0-12.32 5.088-13.248 10.304l-12.608 32.96c-1.824 3.776-1.824 6.784-1.824 9.216 0 24.288 75.552 37.664 100.608 37.664 63.104 0 105.504-40.672 105.504-101.152 0.032-65.44-49.12-85.952-80.288-96.768z" />
|
||||
<glyph unicode="" glyph-name="icon-dashboard" d="M768 672v-160c0-17.6-14.4-32-32-32h-160c-17.6 0-32 14.4-32 32v160c0 17.6 14.4 32 32 32h160c17.6 0 32-14.4 32-32zM480 384v-160c0-17.6-14.4-32-32-32h-160c-17.6 0-32 14.4-32 32v160c0 17.6 14.4 32 32 32h160c17.6 0 32-14.4 32-32zM480 672v-160c0-17.6-14.4-32-32-32h-160c-17.6 0-32 14.4-32 32v160c0 17.6 14.4 32 32 32h160c17.6 0 32-14.4 32-32zM768 384v-160c0-17.6-14.4-32-32-32h-160c-17.6 0-32 14.4-32 32v160c0 17.6 14.4 32 32 32h160c17.6 0 32-14.4 32-32z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-right" d="M420.928 202.784l237.44 219.616c8.576 8.128 13.632 19.296 13.632 31.040-0.288 11.744-5.056 23.2-13.664 31.040l-227.040 208.768c-16.928 15.36-43.040 14.176-58.176-3.008-15.424-16.864-13.952-43.392 2.656-59.040l193.504-177.76-203.904-188.608c-8-7.52-12.768-18.080-13.344-29.216-0.608-11.456 3.264-21.696 10.688-30.112 15.456-16.896 41.568-18.080 58.208-2.72z" />
|
||||
<glyph unicode="" glyph-name="icon-eye-crossed" d="M768 456.64c-20.16-34.88-44.48-63.68-71.68-86.72l-64.64 64.64c0.64 4.16 0.96 8.64 0.96 12.8 0 60.16-51.84 108.8-115.84 108.8-2.24 0-4.16 0-6.4-0.32l-33.92 33.92c12.16 1.6 24 2.24 36.16 2.24 98.88 0 197.44-45.12 255.36-135.36zM348.8 646.080c-8.96 8.96-23.68 8.96-32.64 0l-3.52-3.52c-8.96-8.96-8.96-23.68 0-32.64l53.76-53.76c-43.52-22.4-81.6-56.32-110.4-100.8 83.84-130.56 226.88-177.6 348.48-137.28l57.6-57.6c9.28-9.28 23.68-9.28 32.96 0l3.2 3.2c8.96 8.96 8.96 23.68 0 32.64l-349.44 349.76zM516.8 338.56c-64-0.32-115.84 48.64-115.84 108.48-0.32 21.12 6.080 40.64 17.28 57.28l42.56-42.56c-1.92-5.76-2.56-12.16-1.92-18.88 2.88-30.080 30.72-52.16 62.72-49.92 2.24 0.32 4.8 0.64 7.040 0.96l42.56-42.56c-16.32-8.32-34.56-12.8-54.4-12.8z" />
|
||||
<glyph unicode="" glyph-name="icon-T1" d="M603.2 694.4h-6.4c-25.494 5.341-54.79 8.398-84.8 8.398s-59.305-3.058-87.592-8.879l2.792 0.48h-6.72c-30.053-5.643-52.489-31.68-52.489-62.956 0-0.367 0.003-0.733 0.009-1.099l-0.001 0.055v-234.88c0.075-40.921 11.238-79.22 30.643-112.071l-0.563 1.031 35.2-60.48c11.655-19.297 32.515-32.001 56.342-32.001 0.105 0 0.209 0 0.314 0.001h44.144c0.359-0.007 0.783-0.011 1.208-0.011 23.569 0 44.162 12.74 55.269 31.709l0.164 0.302 36.16 64c18.232 31.447 29.027 69.173 29.12 109.413v232.987c0.005 0.293 0.008 0.639 0.008 0.986 0 31.391-22.599 57.503-52.416 62.954l-0.392 0.059zM629.76 396.8c-0.193-35.364-9.792-68.446-26.418-96.923l0.498 0.923-35.84-64c-6.868-11.865-19.463-19.742-33.906-19.84h-44.174c-0.073 0-0.159-0.001-0.246-0.001-14.427 0-27.041 7.762-33.894 19.338l-0.1 0.183-34.88 59.84c-16.656 28.155-26.515 62.042-26.56 98.227v235.853c0.133 19.025 13.742 34.833 31.751 38.359l0.249 0.041h6.72c24.050 5.126 51.682 8.062 80 8.062s55.949-2.936 82.608-8.519l-2.608 0.457h6.72c18.258-3.568 31.867-19.375 32-38.386v-0.014zM422.4 606.080h179.2c3.535 0 6.4-2.865 6.4-6.4v-99.2c0-3.535-2.865-6.4-6.4-6.4h-179.2c-3.535 0-6.4 2.865-6.4 6.4v99.2c0 3.535 2.865 6.4 6.4 6.4z" />
|
||||
<glyph unicode="" glyph-name="icon-T1-buttons" d="M603.2 694.4h-6.4c-25.494 5.341-54.79 8.398-84.8 8.398s-59.305-3.058-87.592-8.879l2.792 0.48h-6.72c-30.053-5.643-52.489-31.68-52.489-62.956 0-0.367 0.003-0.733 0.009-1.099l-0.001 0.055v-234.88c0.075-40.921 11.238-79.22 30.643-112.071l-0.563 1.031 35.2-60.48c11.655-19.297 32.515-32.001 56.342-32.001 0.105 0 0.209 0 0.314 0.001h44.144c0.359-0.007 0.783-0.011 1.208-0.011 23.569 0 44.162 12.74 55.269 31.709l0.164 0.302 36.16 64c18.152 31.468 28.933 69.175 29.12 109.385v233.015c0.005 0.293 0.008 0.639 0.008 0.986 0 31.391-22.599 57.503-52.416 62.954l-0.392 0.059zM629.76 396.8c-0.193-35.364-9.792-68.446-26.418-96.923l0.498 0.923-35.84-64c-6.868-11.865-19.463-19.742-33.906-19.84h-44.174c-14.469 0.112-27.111 7.827-34.139 19.343l-34.981 61.297c-16.687 28.041-26.553 61.827-26.56 97.918v234.882c0 19.072 13.676 34.95 31.757 38.362l0.243 0.038h6.72c24.050 5.126 51.682 8.062 80 8.062s55.949-2.936 82.608-8.519l-2.608 0.457h6.72c18.324-3.45 32-19.328 32-38.4v0zM422.4 606.080h179.2c3.535 0 6.4-2.865 6.4-6.4v-99.2c0-3.535-2.865-6.4-6.4-6.4h-179.2c-3.535 0-6.4 2.865-6.4 6.4v99.2c0 3.535 2.865 6.4 6.4 6.4zM531.2 469.76h70.4c3.535 0 6.4-2.865 6.4-6.4v-28.8c0-3.535-2.865-6.4-6.4-6.4h-70.4c-3.535 0-6.4 2.865-6.4 6.4v28.8c0 3.535 2.865 6.4 6.4 6.4zM422.4 468.8h70.4c3.535 0 6.4-2.865 6.4-6.4v-28.8c0-3.535-2.865-6.4-6.4-6.4h-70.4c-3.535 0-6.4 2.865-6.4 6.4v28.8c0 3.535 2.865 6.4 6.4 6.4z" />
|
||||
<glyph unicode="" glyph-name="icon-T1-connect" d="M526.72 345.92h-29.44c-16.229 0.18-30.307 9.217-37.647 22.496l-0.113 0.224-23.36 41.92c-12.685 22.404-20.16 49.203-20.16 77.748 0 0.004 0 0.008 0 0.012v-0.001 164.16c-0.002 0.138-0.002 0.301-0.002 0.463 0 21.403 14.903 39.326 34.898 43.957l0.304 0.059h4.48c16.978 3.729 36.479 5.865 56.48 5.865s39.502-2.136 58.289-6.193l-1.809 0.327h4.48c20.14-4.81 34.883-22.655 34.883-43.943 0-0.189-0.001-0.377-0.003-0.565v0.029-163.52c0-0.064 0-0.139 0-0.214 0-28.079-7.233-54.468-19.937-77.407l0.417 0.821-24-43.84c-7.529-13.375-21.591-22.288-37.744-22.4h-0.016zM512 685.76c-0.097 0-0.212 0-0.327 0-18.693 0-36.923-1.981-54.492-5.745l1.699 0.305h-4.48c-12.188-2.865-21.122-13.645-21.122-26.512 0-0.129 0.001-0.258 0.003-0.387v0.020-164.48c0-0.094 0-0.204 0-0.315 0-25.018 6.525-48.512 17.966-68.873l-0.365 0.708 23.36-41.92c4.497-8.071 12.981-13.44 22.718-13.44 0.001 0 0.002 0 0.002 0h29.44c9.799 0.067 18.299 5.56 22.652 13.623l0.068 0.137 24 43.84c10.854 19.495 17.254 42.757 17.28 67.512v162.248c0.002 0.109 0.002 0.238 0.002 0.368 0 12.867-8.935 23.648-20.938 26.476l-0.184 0.037h-4.48c-15.736 3.739-33.906 6.053-52.557 6.396l-0.243 0.004zM452.48 635.52h119.040c2.474 0 4.48-2.006 4.48-4.48v-69.44c0-2.474-2.006-4.48-4.48-4.48h-119.040c-2.474 0-4.48 2.006-4.48 4.48v69.44c0 2.474 2.006 4.48 4.48 4.48zM540.48 303.68v-52.16h-18.24v-59.52h-19.84v59.52h-18.88v52.16h56.96z" />
|
||||
<glyph unicode="" d="M551.36 178.24h-78.4c-0.225-0.006-0.489-0.010-0.754-0.010-10.242 0-19.207 5.468-24.135 13.643l-0.071 0.127-64 96c-29.426 43.619-46.99 97.353-47.040 155.187v233.613c0.36 22.875 18.988 41.281 41.915 41.281 0.114 0 0.228 0 0.342-0.001h263.342c0.097 0.001 0.211 0.001 0.325 0.001 22.927 0 41.555-18.406 41.915-41.248v-239.394c-0.289-59.994-19.423-115.463-51.779-160.855l0.579 0.855-60.48-86.080c-4.695-7.399-12.575-12.414-21.664-13.114l-0.096-0.006zM380.48 690.24c-0.1 0.003-0.217 0.004-0.334 0.004-7.552 0-13.716-5.946-14.064-13.413l-0.001-0.031v-233.92c0-0.010 0-0.023 0-0.036 0-52.093 15.777-100.502 42.813-140.708l-0.573 0.904 64-96h79.040l60.16 86.080c28.821 40.408 46.080 90.794 46.080 145.211 0 0.024 0 0.049 0 0.073v-0.004 238.4c-0.35 7.498-6.513 13.444-14.066 13.444-0.118 0-0.235-0.001-0.352-0.004h0.017z" />
|
||||
<glyph unicode="" d="M407.040 624.32h209.92c4.595 0 8.32-3.725 8.32-8.32v-201.92c0-4.595-3.725-8.32-8.32-8.32h-209.92c-4.595 0-8.32 3.725-8.32 8.32v201.92c0 4.595 3.725 8.32 8.32 8.32z" />
|
||||
<glyph unicode="" d="M539.52 352h-54.72c-6.578 0.052-12.387 3.298-15.96 8.261l-0.040 0.059-45.12 64c-20.029 28.726-32.002 64.366-32.002 102.802 0 0.309 0.001 0.617 0.002 0.925v-0.047 157.76c0.349 15.459 12.963 27.856 28.473 27.856 0.34 0 0.679-0.006 1.016-0.018l-0.049 0.001h184.32c0.288 0.010 0.627 0.016 0.967 0.016 15.51 0 28.124-12.398 28.473-27.824l0.001-0.032v-160c-0.074-40.641-13.522-78.128-36.176-108.308l0.336 0.468-42.24-57.28c-3.622-5.258-9.609-8.66-16.39-8.66-0.313 0-0.624 0.007-0.934 0.022l0.044-0.002zM419.84 694.4c-0.205 0.016-0.444 0.025-0.686 0.025-4.973 0-9.062-3.781-9.551-8.624l-0.003-0.040v-155.84c0.066-34.769 11.081-66.953 29.778-93.302l-0.338 0.502 45.12-64h56l42.24 57.28c19.839 26.468 31.828 59.817 32 95.96v160.040c-0.492 4.884-4.582 8.665-9.554 8.665-0.241 0-0.481-0.009-0.717-0.026l0.032 0.002z" />
|
||||
<glyph unicode="" d="M438.4 650.88h146.88c3.181 0 5.76-2.579 5.76-5.76v-134.4c0-3.181-2.579-5.76-5.76-5.76h-146.88c-3.181 0-5.76 2.579-5.76 5.76v134.4c0 3.181 2.579 5.76 5.76 5.76z" />
|
||||
<glyph unicode="" d="M541.12 300.48v-50.56h-18.56v-57.92h-20.48v57.92h-18.88v50.56h57.92z" />
|
||||
<glyph unicode="" glyph-name="icon-eye-crossed" d="M768 456.64c-20.16-34.88-44.48-63.68-71.68-86.72l-64.64 64.64c0.64 4.16 0.96 8.64 0.96 12.8 0 60.16-51.84 108.8-115.84 108.8-2.24 0-4.16 0-6.4-0.32l-33.92 33.92c12.16 1.6 24 2.24 36.16 2.24 98.88 0 197.44-45.12 255.36-135.36zM348.8 646.080c-8.96 8.96-23.68 8.96-32.64 0l-3.52-3.52c-8.96-8.96-8.96-23.68 0-32.64l53.76-53.76c-43.52-22.4-81.6-56.32-110.4-100.8 83.84-130.56 226.88-177.6 348.48-137.28l57.6-57.6c9.28-9.28 23.68-9.28 32.96 0l3.2 3.2c8.96 8.96 8.96 23.68 0 32.64l-349.44 349.76zM516.8 338.56c-64-0.32-115.84 48.64-115.84 108.48-0.32 21.12 6.080 40.64 17.28 57.28l42.56-42.56c-1.92-5.76-2.56-12.16-1.92-18.88 2.88-30.080 30.72-52.16 62.72-49.92 2.24 0.32 4.8 0.64 7.040 0.96l42.56-42.56c-16.32-8.32-34.56-12.8-54.4-12.8z" />
|
||||
<glyph unicode="" glyph-name="icon-T1" d="M603.2 694.4h-6.4c-25.494 5.341-54.79 8.398-84.8 8.398s-59.305-3.058-87.592-8.879l2.792 0.48h-6.72c-30.053-5.643-52.489-31.68-52.489-62.956 0-0.367 0.003-0.733 0.009-1.099l-0.001 0.055v-234.88c0.075-40.921 11.238-79.22 30.643-112.071l-0.563 1.031 35.2-60.48c11.655-19.297 32.515-32.001 56.342-32.001 0.105 0 0.209 0 0.314 0.001h44.144c0.359-0.007 0.783-0.011 1.208-0.011 23.569 0 44.162 12.74 55.269 31.709l0.164 0.302 36.16 64c18.232 31.447 29.027 69.173 29.12 109.413v232.987c0.005 0.293 0.008 0.639 0.008 0.986 0 31.391-22.599 57.503-52.416 62.954l-0.392 0.059zM629.76 396.8c-0.193-35.364-9.792-68.446-26.418-96.923l0.498 0.923-35.84-64c-6.868-11.865-19.463-19.742-33.906-19.84h-44.174c-0.073 0-0.159-0.001-0.246-0.001-14.427 0-27.041 7.762-33.894 19.338l-0.1 0.183-34.88 59.84c-16.656 28.155-26.515 62.042-26.56 98.227v235.853c0.133 19.025 13.742 34.833 31.751 38.359l0.249 0.041h6.72c24.050 5.126 51.682 8.062 80 8.062s55.949-2.936 82.608-8.519l-2.608 0.457h6.72c18.258-3.568 31.867-19.375 32-38.386v-0.014zM422.4 606.080h179.2c3.535 0 6.4-2.865 6.4-6.4v-99.2c0-3.535-2.865-6.4-6.4-6.4h-179.2c-3.535 0-6.4 2.865-6.4 6.4v99.2c0 3.535 2.865 6.4 6.4 6.4z" />
|
||||
<glyph unicode="" glyph-name="icon-T1-buttons" d="M603.2 694.4h-6.4c-25.494 5.341-54.79 8.398-84.8 8.398s-59.305-3.058-87.592-8.879l2.792 0.48h-6.72c-30.053-5.643-52.489-31.68-52.489-62.956 0-0.367 0.003-0.733 0.009-1.099l-0.001 0.055v-234.88c0.075-40.921 11.238-79.22 30.643-112.071l-0.563 1.031 35.2-60.48c11.655-19.297 32.515-32.001 56.342-32.001 0.105 0 0.209 0 0.314 0.001h44.144c0.359-0.007 0.783-0.011 1.208-0.011 23.569 0 44.162 12.74 55.269 31.709l0.164 0.302 36.16 64c18.152 31.468 28.933 69.175 29.12 109.385v233.015c0.005 0.293 0.008 0.639 0.008 0.986 0 31.391-22.599 57.503-52.416 62.954l-0.392 0.059zM629.76 396.8c-0.193-35.364-9.792-68.446-26.418-96.923l0.498 0.923-35.84-64c-6.868-11.865-19.463-19.742-33.906-19.84h-44.174c-14.469 0.112-27.111 7.827-34.139 19.343l-34.981 61.297c-16.687 28.041-26.553 61.827-26.56 97.918v234.882c0 19.072 13.676 34.95 31.757 38.362l0.243 0.038h6.72c24.050 5.126 51.682 8.062 80 8.062s55.949-2.936 82.608-8.519l-2.608 0.457h6.72c18.324-3.45 32-19.328 32-38.4v0zM422.4 606.080h179.2c3.535 0 6.4-2.865 6.4-6.4v-99.2c0-3.535-2.865-6.4-6.4-6.4h-179.2c-3.535 0-6.4 2.865-6.4 6.4v99.2c0 3.535 2.865 6.4 6.4 6.4zM531.2 469.76h70.4c3.535 0 6.4-2.865 6.4-6.4v-28.8c0-3.535-2.865-6.4-6.4-6.4h-70.4c-3.535 0-6.4 2.865-6.4 6.4v28.8c0 3.535 2.865 6.4 6.4 6.4zM422.4 468.8h70.4c3.535 0 6.4-2.865 6.4-6.4v-28.8c0-3.535-2.865-6.4-6.4-6.4h-70.4c-3.535 0-6.4 2.865-6.4 6.4v28.8c0 3.535 2.865 6.4 6.4 6.4z" />
|
||||
<glyph unicode="" glyph-name="icon-T1-connect" d="M526.72 345.92h-29.44c-16.229 0.18-30.307 9.217-37.647 22.496l-0.113 0.224-23.36 41.92c-12.685 22.404-20.16 49.203-20.16 77.748 0 0.004 0 0.008 0 0.012v-0.001 164.16c-0.002 0.138-0.002 0.301-0.002 0.463 0 21.403 14.903 39.326 34.898 43.957l0.304 0.059h4.48c16.978 3.729 36.479 5.865 56.48 5.865s39.502-2.136 58.289-6.193l-1.809 0.327h4.48c20.14-4.81 34.883-22.655 34.883-43.943 0-0.189-0.001-0.377-0.003-0.565v0.029-163.52c0-0.064 0-0.139 0-0.214 0-28.079-7.233-54.468-19.937-77.407l0.417 0.821-24-43.84c-7.529-13.375-21.591-22.288-37.744-22.4h-0.016zM512 685.76c-0.097 0-0.212 0-0.327 0-18.693 0-36.923-1.981-54.492-5.745l1.699 0.305h-4.48c-12.188-2.865-21.122-13.645-21.122-26.512 0-0.129 0.001-0.258 0.003-0.387v0.020-164.48c0-0.094 0-0.204 0-0.315 0-25.018 6.525-48.512 17.966-68.873l-0.365 0.708 23.36-41.92c4.497-8.071 12.981-13.44 22.718-13.44 0.001 0 0.002 0 0.002 0h29.44c9.799 0.067 18.299 5.56 22.652 13.623l0.068 0.137 24 43.84c10.854 19.495 17.254 42.757 17.28 67.512v162.248c0.002 0.109 0.002 0.238 0.002 0.368 0 12.867-8.935 23.648-20.938 26.476l-0.184 0.037h-4.48c-15.736 3.739-33.906 6.053-52.557 6.396l-0.243 0.004zM452.48 635.52h119.040c2.474 0 4.48-2.006 4.48-4.48v-69.44c0-2.474-2.006-4.48-4.48-4.48h-119.040c-2.474 0-4.48 2.006-4.48 4.48v69.44c0 2.474 2.006 4.48 4.48 4.48zM540.48 303.68v-52.16h-18.24v-59.52h-19.84v59.52h-18.88v52.16h56.96z" />
|
||||
<glyph unicode="" d="M551.36 178.24h-78.4c-0.225-0.006-0.489-0.010-0.754-0.010-10.242 0-19.207 5.468-24.135 13.643l-0.071 0.127-64 96c-29.426 43.619-46.99 97.353-47.040 155.187v233.613c0.36 22.875 18.988 41.281 41.915 41.281 0.114 0 0.228 0 0.342-0.001h263.342c0.097 0.001 0.211 0.001 0.325 0.001 22.927 0 41.555-18.406 41.915-41.248v-239.394c-0.289-59.994-19.423-115.463-51.779-160.855l0.579 0.855-60.48-86.080c-4.695-7.399-12.575-12.414-21.664-13.114l-0.096-0.006zM380.48 690.24c-0.1 0.003-0.217 0.004-0.334 0.004-7.552 0-13.716-5.946-14.064-13.413l-0.001-0.031v-233.92c0-0.010 0-0.023 0-0.036 0-52.093 15.777-100.502 42.813-140.708l-0.573 0.904 64-96h79.040l60.16 86.080c28.821 40.408 46.080 90.794 46.080 145.211 0 0.024 0 0.049 0 0.073v-0.004 238.4c-0.35 7.498-6.513 13.444-14.066 13.444-0.118 0-0.235-0.001-0.352-0.004h0.017z" />
|
||||
<glyph unicode="" d="M407.040 624.32h209.92c4.595 0 8.32-3.725 8.32-8.32v-201.92c0-4.595-3.725-8.32-8.32-8.32h-209.92c-4.595 0-8.32 3.725-8.32 8.32v201.92c0 4.595 3.725 8.32 8.32 8.32z" />
|
||||
<glyph unicode="" d="M539.52 352h-54.72c-6.578 0.052-12.387 3.298-15.96 8.261l-0.040 0.059-45.12 64c-20.029 28.726-32.002 64.366-32.002 102.802 0 0.309 0.001 0.617 0.002 0.925v-0.047 157.76c0.349 15.459 12.963 27.856 28.473 27.856 0.34 0 0.679-0.006 1.016-0.018l-0.049 0.001h184.32c0.288 0.010 0.627 0.016 0.967 0.016 15.51 0 28.124-12.398 28.473-27.824l0.001-0.032v-160c-0.074-40.641-13.522-78.128-36.176-108.308l0.336 0.468-42.24-57.28c-3.622-5.258-9.609-8.66-16.39-8.66-0.313 0-0.624 0.007-0.934 0.022l0.044-0.002zM419.84 694.4c-0.205 0.016-0.444 0.025-0.686 0.025-4.973 0-9.062-3.781-9.551-8.624l-0.003-0.040v-155.84c0.066-34.769 11.081-66.953 29.778-93.302l-0.338 0.502 45.12-64h56l42.24 57.28c19.839 26.468 31.828 59.817 32 95.96v160.040c-0.492 4.884-4.582 8.665-9.554 8.665-0.241 0-0.481-0.009-0.717-0.026l0.032 0.002z" />
|
||||
<glyph unicode="" d="M438.4 650.88h146.88c3.181 0 5.76-2.579 5.76-5.76v-134.4c0-3.181-2.579-5.76-5.76-5.76h-146.88c-3.181 0-5.76 2.579-5.76 5.76v134.4c0 3.181 2.579 5.76 5.76 5.76z" />
|
||||
<glyph unicode="" d="M541.12 300.48v-50.56h-18.56v-57.92h-20.48v57.92h-18.88v50.56h57.92z" />
|
||||
<glyph unicode="" glyph-name="icon-arrow-left" d="M603.072 202.784l-237.44 219.616c-8.576 8.128-13.632 19.296-13.632 31.040 0.288 11.744 5.056 23.2 13.664 31.040l227.040 208.768c16.928 15.36 43.040 14.176 58.176-3.008 15.424-16.864 13.952-43.392-2.656-59.040l-193.504-177.76 203.904-188.608c8-7.52 12.768-18.080 13.344-29.216 0.608-11.456-3.264-21.696-10.688-30.112-15.456-16.896-41.568-18.080-58.208-2.72z" />
|
||||
<glyph unicode="" glyph-name="icon-top" d="M677.44 346.24c-3.255-1.423-7.047-2.252-11.033-2.252-0.284 0-0.566 0.004-0.848 0.013l0.041-0.001c-8.323 0.531-15.657 4.371-20.77 10.206l-0.030 0.034-93.44 109.44c-0.378 0.735-1.131 1.229-1.999 1.229-1.237 0-2.24-1.003-2.24-2.24 0-0.209 0.029-0.412 0.083-0.605l-0.004 0.016v-233.28c0.102-0.987 0.16-2.132 0.16-3.291 0-18.733-15.187-33.92-33.92-33.92s-33.92 15.187-33.92 33.92c0 1.159 0.058 2.304 0.172 3.433l-0.012-0.142v236.16c0.050 0.177 0.079 0.379 0.079 0.589 0 1.237-1.003 2.24-2.24 2.24-0.868 0-1.621-0.494-1.993-1.216l-0.006-0.013-88.32-104.32c-5.204-6.343-13.042-10.358-21.819-10.358-7.711 0-14.699 3.099-19.784 8.121l0.003-0.003c-6.16 5.845-9.993 14.090-9.993 23.231 0 8.17 3.062 15.625 8.101 21.28l-0.028-0.032 146.56 173.44c5.311 6.15 13.061 10.069 21.731 10.24h0.029c8.727-0.036 16.523-3.991 21.724-10.196l0.036-0.044 152-178.56c5.441-6.124 8.764-14.234 8.764-23.121 0-12.698-6.785-23.81-16.927-29.911l-0.157-0.088zM329.28 667.2c-0.024 0.488-0.038 1.060-0.038 1.635 0 18.891 14.881 34.306 33.561 35.163l0.077 0.003h292.48c18.795-1.81 33.372-17.523 33.372-36.64s-14.577-34.83-33.222-36.628l-0.15-0.012h-292.48c-18.751 0.866-33.625 16.278-33.625 35.165 0 0.463 0.009 0.923 0.027 1.381l-0.002-0.066z" />
|
||||
<glyph unicode="" glyph-name="icon-check" d="M692.8 646.080l-1.92 1.92c-6.246 7.057-15.326 11.484-25.44 11.484s-19.194-4.427-25.409-11.448l-0.031-0.036-196.48-224-3.84-1.6-3.84 1.92-48.64 57.28c-7.010 7.905-17.193 12.862-28.533 12.862-21.031 0-38.080-17.049-38.080-38.080 0-7.495 2.165-14.485 5.905-20.377l-0.092 0.155 100.8-148.16c5.391-8.036 14.386-13.292 24.618-13.44h8.662c17.251 0.146 32.385 9.075 41.163 22.529l0.117 0.191 195.2 296.32c4.473 6.632 7.141 14.803 7.141 23.597 0 11.162-4.297 21.32-11.326 28.911l0.025-0.028z" />
|
||||
<glyph unicode="" glyph-name="icon-error" d="M693.12 629.12c-46.317 46.267-110.276 74.88-180.919 74.88-141.385 0-256-114.615-256-256s114.615-256 256-256c70.642 0 134.602 28.613 180.921 74.882l-0.002-0.002c46.387 46.337 75.081 110.377 75.081 181.12s-28.694 134.783-75.079 181.118l-0.002 0.002zM494.080 615.68h53.12c16 0 18.24-9.28 18.24-14.72v-10.24l-10.88-194.56c0-14.4-8-17.28-18.88-17.28h-28.16c-10.56 0-17.28 2.88-18.88 17.92l-10.88 193.92v10.56c-1.28 4.8 2.24 14.080 16.32 14.080zM521.28 242.24c-0.095-0.001-0.207-0.001-0.319-0.001-27.747 0-50.24 22.493-50.24 50.24s22.493 50.24 50.24 50.24c27.747 0 50.24-22.493 50.24-50.24 0-0.112 0-0.224-0.001-0.336v0.017c0 0 0-0.001 0-0.001 0-27.634-22.311-50.057-49.903-50.239h-0.017z" />
|
||||
<glyph unicode="" glyph-name="icon-eye" d="M512.64 592c-99.2 0-198.4-45.76-256.64-136.64 128.64-200 394.56-203.84 512 1.28-57.92 90.24-156.48 135.36-255.36 135.36zM516.8 338.56c-64-0.32-115.84 48.64-115.84 108.48-0.32 60.16 51.52 109.12 115.84 109.12 64 0 115.84-48.64 115.84-108.8 0.32-60.16-51.52-108.8-115.84-108.8zM574.72 451.84c2.56-30.080-21.12-56.32-53.12-58.88-32-2.24-59.84 19.84-62.72 49.92-2.56 30.080 21.44 56.32 53.12 58.56 32 2.56 59.84-19.84 62.72-49.6z" />
|
||||
<glyph unicode="" glyph-name="icon-back" d="M656.224 557.696l-66.848-66.176-66.848 66.176-50.144-49.6 66.912-66.176-66.912-66.176 50.176-49.632 66.848 66.176 66.848-66.176 50.112 49.632-66.816 66.176 66.816 66.176-50.144 49.6zM337.824 704h540.928c27.2 0 49.248-21.824 49.248-48.768v-414.464c0-26.944-22.048-48.768-49.248-48.768h-540.608c-13.856 0-27.072 5.792-36.416 15.936l-192.896 209.664c-17.248 18.752-17.088 47.488 0.352 66.048l192.576 204.8c9.344 9.92 22.4 15.552 36.064 15.552z" />
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
BIN
src/images/T.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 557 KiB |
@ -1,90 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Vrstva_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 211 61" style="enable-background:new 0 0 211 61;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill-rule:evenodd;clip-rule:evenodd;}
|
||||
</style>
|
||||
<path id="unlocked" class="st0" d="M12,15v-2.6c0-2.1,1.7-3.8,3.7-3.8h1.1c2,0,3.7,1.7,3.7,3.8v0.2h-2.1c-0.1-1.1-1-1.9-2.1-1.9
|
||||
c-1.2,0-2.1,1-2.1,2.2V15h6.8c0.6,0,1,0.5,1,1v6.5c0,0.6-0.5,1-1,1h-9.8c-0.6,0-1-0.5-1-1V16c0-0.6,0.5-1,1-1H12z"/>
|
||||
<path id="locked" class="st0" d="M50.9,15h-0.5v-2.6c0-2.1-1.7-3.8-3.7-3.8h-1.1c-2,0-3.7,1.7-3.7,3.8V15h-0.9c-0.6,0-1,0.5-1,1v6.5
|
||||
c0,0.6,0.5,1,1,1h9.8c0.6,0,1-0.5,1-1V16C51.9,15.4,51.5,15,50.9,15z M44.1,12.8c0-1.2,0.9-2.2,2.1-2.2c1.1,0,2,1,2.1,2.1V15h-4.2
|
||||
V12.8z"/>
|
||||
<g id="refresh">
|
||||
<path d="M101,14.9c0.5-2.4,2.7-4.2,5.3-4.2c1,0,1.9,0.3,2.7,0.7c0.2,0.1,0.4,0.3,0.6,0.4l-2.1,2l5.8,1l-1-5.8l-1.2,1.2
|
||||
c-0.2-0.1-0.4-0.3-0.6-0.4c-1.2-0.8-2.7-1.3-4.3-1.3c-3.7,0-6.8,2.6-7.4,6.2l-0.1,0.6h2.2L101,14.9z"/>
|
||||
<path d="M111,17.2c-0.5,2.4-2.7,4.2-5.3,4.2c-1,0-1.9-0.3-2.7-0.7c-0.2-0.1-0.4-0.3-0.6-0.4l2.1-2l-5.8-1l1,5.8l1.2-1.2
|
||||
c0.2,0.1,0.4,0.3,0.6,0.4c1.2,0.8,2.7,1.3,4.3,1.3c3.7,0,6.8-2.6,7.4-6.2l0.1-0.6h-2.2L111,17.2z"/>
|
||||
</g>
|
||||
<path id="settings" d="M142.7,14.5h-2.1c-0.1-0.4-0.3-0.8-0.5-1.1l1.4-1.4c0.3-0.3,0.3-0.9,0-1.2l-0.6-0.6c-0.3-0.3-0.9-0.3-1.2,0
|
||||
l-1.4,1.4c-0.4-0.2-0.8-0.4-1.2-0.5V9.3c0-0.5-0.4-0.8-0.8-0.8h-0.8c-0.5,0-0.8,0.4-0.8,0.8v1.8c-0.5,0.1-0.9,0.3-1.3,0.6l-1.2-1.2
|
||||
c-0.3-0.3-0.9-0.3-1.2,0l-0.6,0.6c-0.3,0.3-0.3,0.9,0,1.2l1.2,1.2c-0.3,0.4-0.4,0.9-0.6,1.4h-1.6c-0.5,0-0.8,0.4-0.8,0.8v0.8
|
||||
c0,0.5,0.4,0.8,0.8,0.8h1.7c0.2,0.5,0.4,1,0.7,1.4l-1.1,1.1c-0.3,0.3-0.3,0.9,0,1.2l0.6,0.6c0.3,0.3,0.9,0.3,1.2,0l1.3-1.3
|
||||
c0.4,0.2,0.9,0.4,1.4,0.4v1.7c0,0.5,0.4,0.8,0.8,0.8h0.8c0.5,0,0.8-0.4,0.8-0.8v-2c0.4-0.1,0.8-0.3,1.2-0.6l1.3,1.3
|
||||
c0.3,0.3,0.9,0.3,1.2,0l0.6-0.6c0.3-0.3,0.3-0.9,0-1.2l-1.5-1.5c0.2-0.4,0.3-0.8,0.4-1.2h2c0.5,0,0.8-0.4,0.8-0.8v-0.8
|
||||
C143.5,14.9,143.1,14.5,142.7,14.5z M135.8,18.1c-1.2,0-2.1-0.9-2.1-2.1c0-1.2,0.9-2.1,2.1-2.1c1.2,0,2.1,0.9,2.1,2.1
|
||||
C137.9,17.2,136.9,18.1,135.8,18.1z"/>
|
||||
<g id="eject">
|
||||
<path d="M69.5,22.4h12.9c0.3,0,0.5-0.2,0.5-0.5V20c0-0.3-0.2-0.5-0.5-0.5H69.5c-0.3,0-0.5,0.2-0.5,0.5v1.9
|
||||
C69,22.2,69.2,22.4,69.5,22.4z"/>
|
||||
<path d="M75.8,9.7l-6.3,7.2c-0.2,0.2,0,0.5,0.2,0.5h12.6c0.3,0,0.4-0.3,0.2-0.5l-6.3-7.2C76.1,9.5,75.9,9.5,75.8,9.7z"/>
|
||||
</g>
|
||||
<path id="redirect" d="M76,38.5c-4.1,0-7.5,3.4-7.5,7.5c0,4.1,3.4,7.5,7.5,7.5s7.5-3.4,7.5-7.5C83.5,41.9,80.1,38.5,76,38.5z
|
||||
M76.5,49.5v-2c-3-1-4,0-5,2c0-5,3-6,5-6v-2l4,4L76.5,49.5z"/>
|
||||
<path id="warning" d="M113.5,51.9l-7-12.3c-0.3-0.5-0.7-0.5-1,0l-7,12.3c-0.3,0.5,0,0.9,0.5,0.9h14
|
||||
C113.6,52.7,113.8,52.4,113.5,51.9z M107,50.2c0,0.3-0.2,0.5-0.5,0.5h-1c-0.3,0-0.5-0.2-0.5-0.5v-1c0-0.3,0.2-0.5,0.5-0.5h1
|
||||
c0.3,0,0.5,0.2,0.5,0.5V50.2z M107,47.2c0,0.3-0.2,0.5-0.5,0.5h-1c-0.3,0-0.5-0.2-0.5-0.5v-3c0-0.3,0.2-0.5,0.5-0.5h1
|
||||
c0.3,0,0.5,0.2,0.5,0.5V47.2z"/>
|
||||
<path id="chat" d="M48,38.5h-4c-3,0-5.5,2.5-5.5,5.6c0,2.8,2,5.2,4.7,5.6v3.8l3.8-3.8H48c3,0,5.5-2.5,5.5-5.6
|
||||
C53.5,41,51,38.5,48,38.5z"/>
|
||||
<path id="info" d="M21.3,40.7c-2.9-2.9-7.7-2.9-10.6,0c-2.9,2.9-2.9,7.7,0,10.6c2.9,2.9,7.7,2.9,10.6,0
|
||||
C24.2,48.4,24.2,43.6,21.3,40.7z M15.9,39.8c0.8,0,1.4,0.6,1.4,1.4c0,0.8-0.6,1.4-1.4,1.4c-0.8,0-1.5-0.7-1.5-1.4
|
||||
C14.4,40.4,15.1,39.8,15.9,39.8z M18.2,50.4c0,0.3-0.1,0.4-0.4,0.4H14c-0.3,0-0.4-0.1-0.4-0.4v-0.9c0-0.3,0.1-0.4,0.4-0.4h0.7v-4H14
|
||||
c-0.3,0-0.4-0.1-0.4-0.4v-0.9c0-0.3,0.1-0.4,0.4-0.4h2.6c0.3,0,0.4,0.1,0.4,0.4V49h0.7c0.3,0,0.4,0.1,0.4,0.4V50.4z"/>
|
||||
<g id="close">
|
||||
<g>
|
||||
<path d="M143.1,51.2c0.5,0.5,0.5,1.4,0,1.9c-0.3,0.3-0.6,0.4-1,0.4c-0.4,0-0.7-0.1-0.9-0.4l-5.2-5.2l-5.2,5.2
|
||||
c-0.5,0.5-1.4,0.5-1.9,0c-0.5-0.5-0.5-1.4,0-1.9l5.2-5.2l-5.2-5.2c-0.5-0.5-0.5-1.4,0-1.9c0.5-0.5,1.4-0.5,1.9,0l5.2,5.2l5.2-5.2
|
||||
c0.5-0.5,1.4-0.5,1.9,0c0.5,0.5,0.5,1.4,0,1.9l-5.2,5.2L143.1,51.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="arrow-down">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M173.5,13.2l-6.8,7.4c-0.3,0.3-0.6,0.4-1,0.4c-0.4,0-0.7-0.2-1-0.4l-6.4-7.1c-0.5-0.5-0.4-1.3,0.1-1.8
|
||||
c0.5-0.5,1.3-0.4,1.8,0.1l5.5,6l5.8-6.4c0.2-0.3,0.6-0.4,0.9-0.4c0.4,0,0.7,0.1,0.9,0.3C174,11.8,174,12.6,173.5,13.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="arrow-left">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M170.8,52.2c0,0.3-0.1,0.7-0.3,0.9c-0.2,0.3-0.5,0.4-0.9,0.4h-0.1c-0.3,0-0.6-0.1-0.8-0.3l-7-6.4
|
||||
c-0.3-0.2-0.4-0.6-0.4-0.9c0-0.3,0.2-0.7,0.4-0.9l6.7-6.1c0.3-0.2,0.6-0.3,0.9-0.3c0.3,0,0.6,0.2,0.9,0.4
|
||||
c0.5,0.5,0.4,1.3-0.1,1.8l-5.7,5.2l6,5.5C170.6,51.6,170.7,51.9,170.8,52.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="arrow-right">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M191.2,39.8c0-0.3,0.1-0.7,0.3-0.9c0.2-0.3,0.5-0.4,0.9-0.4h0.1c0.3,0,0.6,0.1,0.8,0.3l7,6.4c0.3,0.2,0.4,0.6,0.4,0.9
|
||||
c0,0.3-0.2,0.7-0.4,0.9l-6.7,6.1c-0.3,0.2-0.6,0.3-0.9,0.3c-0.3,0-0.6-0.2-0.9-0.4c-0.5-0.5-0.4-1.3,0.1-1.8l5.7-5.2l-6-5.5
|
||||
C191.4,40.4,191.3,40.1,191.2,39.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="arrow-up">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M189.8,20.8c-0.3,0-0.7-0.1-0.9-0.3c-0.3-0.2-0.4-0.5-0.4-0.9v-0.1c0-0.3,0.1-0.6,0.3-0.8l6.4-7c0.2-0.3,0.6-0.4,0.9-0.4
|
||||
c0.3,0,0.7,0.2,0.9,0.4l6.1,6.7c0.2,0.3,0.3,0.6,0.3,0.9c0,0.3-0.2,0.6-0.4,0.9c-0.5,0.5-1.3,0.4-1.8-0.1l-5.2-5.7l-5.5,6
|
||||
C190.5,20.6,190.1,20.8,189.8,20.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<view id="icon-external" viewBox="30 60 30 30" />
|
||||
<view id="icon-heart-view" viewBox="0 32 32 32" />
|
||||
<view id="icon-arrow-right-view" viewBox="0 64 32 32" />
|
||||
</svg>
|
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 658 KiB |
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>Ethereum Wallet| TREZOR</title>
|
||||
<title>Ethereum Wallet | TREZOR</title>
|
||||
<meta name="title" content="TrezorConnect" />
|
||||
<meta name="description" content="TrezorConnect" />
|
||||
<meta name="keywords" content="TrezorConnect" />
|
||||
|
@ -35,7 +35,6 @@ export function loadTokensFromJSON(): any {
|
||||
const ethERC20 = await httpRequest('data/ethERC20.json', 'json');
|
||||
|
||||
const devices: ?string = get('devices');
|
||||
console.log("GET23", JSON.parse(devices))
|
||||
if (devices) {
|
||||
dispatch({
|
||||
type: CONNECT.DEVICE_FROM_STORAGE,
|
||||
@ -59,6 +58,14 @@ export function loadTokensFromJSON(): any {
|
||||
})
|
||||
}
|
||||
|
||||
const pending: ?string = get('pending');
|
||||
if (pending) {
|
||||
dispatch({
|
||||
type: 'PENDING.FROM_STORAGE',
|
||||
payload: JSON.parse(pending)
|
||||
})
|
||||
}
|
||||
|
||||
const discovery: ?string = get('discovery');
|
||||
if (discovery) {
|
||||
dispatch({
|
||||
@ -88,12 +95,11 @@ export function loadTokensFromJSON(): any {
|
||||
export const save = (key: string, value: string): any => {
|
||||
return (dispatch, getState) => {
|
||||
if (typeof window.localStorage !== 'undefined') {
|
||||
//console.log("SAVEE!!!!", key, value)
|
||||
try {
|
||||
window.localStorage.setItem(key, value);
|
||||
} catch (error) {
|
||||
// available = false;
|
||||
console.error("ERROR: " + error)
|
||||
console.error("Local Storage ERROR: " + error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,7 +108,6 @@ export const save = (key: string, value: string): any => {
|
||||
export const get = (key: string): ?string => {
|
||||
if (typeof window.localStorage !== 'undefined') {
|
||||
try {
|
||||
console.log("GETTT", JSON.parse(window.localStorage.getItem(key)))
|
||||
return window.localStorage.getItem(key);
|
||||
} catch (error) {
|
||||
// available = false;
|
||||
|
15
src/js/actions/LogActions.js
Normal file
@ -0,0 +1,15 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const toggle = (): any => {
|
||||
return (dispatch, getState) => {
|
||||
|
||||
if (!getState().log.opened) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: getState().log.opened ? 'log__close' : 'log__open'
|
||||
});
|
||||
}
|
||||
}
|
@ -65,6 +65,7 @@ export const showAddress = (address_n: string): any => {
|
||||
return async (dispatch, getState) => {
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
if (!selected) return;
|
||||
|
||||
if (selected && !selected.connected) {
|
||||
dispatch({
|
||||
|
@ -4,7 +4,7 @@
|
||||
import * as SEND from './constants/SendForm';
|
||||
import * as NOTIFICATION from './constants/notification';
|
||||
|
||||
import { getNonce, estimateGas, getGasPrice, pushTx } from './Web3Actions';
|
||||
import { estimateGas, getGasPrice, pushTx } from './Web3Actions';
|
||||
|
||||
import EthereumjsUtil from 'ethereumjs-util';
|
||||
import EthereumjsUnits from 'ethereumjs-units';
|
||||
@ -18,7 +18,8 @@ import { initialState } from '../reducers/SendFormReducer';
|
||||
import type { State, FeeLevel } from '../reducers/SendFormReducer';
|
||||
import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
|
||||
|
||||
const numberRegExp = new RegExp('^([0-9]{0,10}\\.)?[0-9]{1,18}$');
|
||||
//const numberRegExp = new RegExp('^([0-9]{0,10}\\.)?[0-9]{1,18}$');
|
||||
const numberRegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9]+\\.?([0-9]+)?|\\.[0-9]+)$');
|
||||
|
||||
const calculateFee = (gasPrice: string, gasLimit: string): string => {
|
||||
return EthereumjsUnits.convert( new BigNumber(gasPrice).times(gasLimit), 'gwei', 'ether');
|
||||
@ -50,7 +51,6 @@ export const getFeeLevels = (coin: string, gasPrice: BigNumber | string, gasLimi
|
||||
const quarter: BigNumber = gasPrice.dividedBy(4);
|
||||
const high: string = gasPrice.plus(quarter.times(2)).toString();
|
||||
const low: string = gasPrice.minus(quarter.times(2)).toString();
|
||||
coin = coin.toUpperCase();
|
||||
|
||||
return [
|
||||
{
|
||||
@ -106,11 +106,11 @@ export const init = (): any => {
|
||||
|
||||
// TODO: check if there are some unfinished tx in localStorage
|
||||
const { config } = getState().localStorage;
|
||||
const coin = config.coins.find(c => c.symbol === urlParams.coin);
|
||||
const coin = config.coins.find(c => c.network === urlParams.coin);
|
||||
|
||||
const gasPrice: BigNumber = new BigNumber( EthereumjsUnits.convert(web3instance.gasPrice, 'wei', 'gwei') ) || new BigNumber(coin.defaultGasPrice);
|
||||
const gasLimit: string = coin.defaultGasLimit.toString();
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(urlParams.coin, gasPrice, gasLimit);
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(coin.symbol, gasPrice, gasLimit);
|
||||
|
||||
// TODO: get nonce
|
||||
|
||||
@ -119,6 +119,7 @@ export const init = (): any => {
|
||||
checksum: selected.checksum,
|
||||
accountIndex: parseInt(urlParams.address),
|
||||
coin: urlParams.coin,
|
||||
coinSymbol: coin.symbol,
|
||||
token: urlParams.coin,
|
||||
location: location.pathname,
|
||||
|
||||
@ -204,15 +205,32 @@ export const validation = (): any => {
|
||||
errors.amount = 'Amount is not a number';
|
||||
} else {
|
||||
const account = getState().accounts.find(a => a.checksum === state.checksum && a.index === state.accountIndex && a.coin === state.coin);
|
||||
let decimalRegExp;
|
||||
|
||||
if (state.token !== state.coin) {
|
||||
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token).balance;
|
||||
if (new BigNumber(state.total).greaterThan(account.balance)) {
|
||||
errors.amount = `Not enough ${ state.coin.toUpperCase() } to cover transaction fee`;
|
||||
} else if (new BigNumber(state.amount).greaterThan(tokenBalance)) {
|
||||
const token: any = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token);
|
||||
|
||||
if (parseInt(token.decimals) > 0) {
|
||||
decimalRegExp = new RegExp('^(0|0\\.([0-9]{0,' + token.decimals + '})?|[1-9]+\\.?([0-9]{0,' + token.decimals + '})?|\\.[0-9]{1,' + token.decimals + '})$');
|
||||
} else {
|
||||
// decimalRegExp = new RegExp('^(0|0\\.?|[1-9]+\\.?)$');
|
||||
decimalRegExp = new RegExp('^[0-9]+$');
|
||||
}
|
||||
|
||||
if (!state.amount.match(decimalRegExp)) {
|
||||
errors.amount = `Maximum ${ token.decimals} decimals allowed`;
|
||||
} else if (new BigNumber(state.total).greaterThan(account.balance)) {
|
||||
errors.amount = `Not enough ${ state.coinSymbol.toUpperCase() } to cover transaction fee`;
|
||||
} else if (new BigNumber(state.amount).greaterThan(token.balance)) {
|
||||
errors.amount = 'Not enough funds';
|
||||
} else if (new BigNumber(state.amount).lessThanOrEqualTo('0')) {
|
||||
errors.amount = 'Amount is too low';
|
||||
}
|
||||
} else {
|
||||
if (new BigNumber(state.total).greaterThan(account.balance)) {
|
||||
decimalRegExp = new RegExp('^(0|0\\.([0-9]{0,18})?|[1-9]+\\.?([0-9]{0,18})?|\\.[0-9]{0,18})$');
|
||||
if (!state.amount.match(decimalRegExp)) {
|
||||
errors.amount = `Maximum 18 decimals allowed`;
|
||||
} else if (new BigNumber(state.total).greaterThan(account.balance)) {
|
||||
errors.amount = 'Not enough funds';
|
||||
}
|
||||
}
|
||||
@ -245,7 +263,7 @@ export const validation = (): any => {
|
||||
const gp: BigNumber = new BigNumber(state.gasPrice);
|
||||
if (gp.greaterThan(100)) {
|
||||
errors.gasPrice = 'Gas price is too high';
|
||||
} else if (gp.lessThan(1)) {
|
||||
} else if (gp.lessThanOrEqualTo('0')) {
|
||||
errors.gasPrice = 'Gas price is too low';
|
||||
}
|
||||
}
|
||||
@ -334,7 +352,7 @@ export const onCurrencyChange = (currency: any): any => {
|
||||
}
|
||||
|
||||
const { config } = getState().localStorage;
|
||||
const coin = config.coins.find(c => c.symbol === currentState.coin);
|
||||
const coin = config.coins.find(c => c.network === currentState.coin);
|
||||
|
||||
let gasLimit: string = '';
|
||||
let amount: string = currentState.amount;
|
||||
@ -355,7 +373,7 @@ export const onCurrencyChange = (currency: any): any => {
|
||||
total = calculateTotal(amount, currentState.gasPrice, currentState.gasLimit);
|
||||
}
|
||||
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coin, currentState.gasPrice, gasLimit);
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.gasPrice, gasLimit);
|
||||
|
||||
const state: State = {
|
||||
...currentState,
|
||||
@ -433,7 +451,7 @@ export const onFeeLevelChange = (feeLevel: any): any => {
|
||||
// TODO: update value for custom fee
|
||||
state.advanced = true;
|
||||
feeLevel.gasPrice = state.gasPrice;
|
||||
feeLevel.label = `${ calculateFee(state.gasPrice, state.gasLimit) } ${ state.coin.toUpperCase() }`;
|
||||
feeLevel.label = `${ calculateFee(state.gasPrice, state.gasLimit) } ${ state.coinSymbol }`;
|
||||
} else {
|
||||
const customLevel = state.feeLevels.find(f => f.value === 'Custom');
|
||||
customLevel.label = '';
|
||||
@ -462,12 +480,14 @@ export const onFeeLevelChange = (feeLevel: any): any => {
|
||||
export const updateFeeLevels = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const currentState = getState().sendForm;
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coin, currentState.recommendedGasPrice, currentState.gasLimit);
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.recommendedGasPrice, currentState.gasLimit);
|
||||
const selectedFeeLevel: ?FeeLevel = feeLevels.find(f => f.value === currentState.selectedFeeLevel.value)
|
||||
const state: State = {
|
||||
...currentState,
|
||||
feeLevels,
|
||||
selectedFeeLevel: feeLevels.find(f => f.value === currentState.selectedFeeLevel.value),
|
||||
gasPrice: currentState.recommendedGasPrice,
|
||||
selectedFeeLevel,
|
||||
//gasPrice: currentState.recommendedGasPrice, // TODO HERE!
|
||||
gasPrice: selectedFeeLevel.gasPrice, // TODO HERE!
|
||||
gasPriceNeedsUpdate: false,
|
||||
};
|
||||
|
||||
@ -507,7 +527,7 @@ export const onGasPriceChange = (gasPrice: string): any => {
|
||||
if (gasPrice.match(numberRegExp) && state.gasLimit.match(numberRegExp)) {
|
||||
const customLevel = currentState.feeLevels.find(f => f.value === 'Custom');
|
||||
customLevel.gasPrice = gasPrice;
|
||||
customLevel.label = `${ calculateFee(gasPrice, state.gasLimit) } ${ state.coin.toUpperCase() }`;
|
||||
customLevel.label = `${ calculateFee(gasPrice, state.gasLimit) } ${ state.coinSymbol }`;
|
||||
|
||||
state.selectedFeeLevel = customLevel;
|
||||
|
||||
@ -547,7 +567,7 @@ export const onGasLimitChange = (gasLimit: string): any => {
|
||||
|
||||
if (gasLimit.match(numberRegExp) && state.gasPrice.match(numberRegExp)) {
|
||||
const customLevel = currentState.feeLevels.find(f => f.value === 'Custom');
|
||||
customLevel.label = `${ calculateFee(state.gasPrice, gasLimit) } ${ state.coin.toUpperCase() }`;
|
||||
customLevel.label = `${ calculateFee(state.gasPrice, gasLimit) } ${ state.coinSymbol }`;
|
||||
|
||||
state.selectedFeeLevel = customLevel;
|
||||
|
||||
@ -640,9 +660,6 @@ export const onSend = (): any => {
|
||||
v: ''
|
||||
}
|
||||
|
||||
//const nonce = await getNonce(web3, currentAddress.address);
|
||||
//txData.nonce = web3.toHex(nonce);
|
||||
|
||||
|
||||
// const gasOptions = {
|
||||
// to: txData.to,
|
||||
@ -660,6 +677,7 @@ export const onSend = (): any => {
|
||||
// console.log("---->GASSS", txData, gasLimit, gasPrice, EthereumjsUnits.convert(gasPrice, 'gwei', 'wei'));
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
if (!selected) return;
|
||||
|
||||
let signedTransaction = await TrezorConnect.ethereumSignTransaction({
|
||||
device: {
|
||||
@ -697,8 +715,11 @@ export const onSend = (): any => {
|
||||
txData.s = '0x' + signedTransaction.data.s;
|
||||
txData.v = web3.toHex(signedTransaction.data.v);
|
||||
|
||||
const gasLimit2 = await estimateGas(web3, txData);
|
||||
console.log("---->GASSS", txData, gasLimit2.toString() );
|
||||
// const gasLimit2 = await estimateGas(web3, txData);
|
||||
// console.log("---->GASSS", txData, gasLimit2.toString() );
|
||||
|
||||
const { config } = getState().localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.network === state.coin);
|
||||
|
||||
try {
|
||||
const tx = new EthereumjsTx(txData);
|
||||
@ -708,6 +729,8 @@ export const onSend = (): any => {
|
||||
dispatch({
|
||||
type: SEND.TX_COMPLETE,
|
||||
address: account,
|
||||
token: state.token,
|
||||
amount: state.amount,
|
||||
txid,
|
||||
txData,
|
||||
});
|
||||
@ -717,7 +740,7 @@ export const onSend = (): any => {
|
||||
payload: {
|
||||
type: 'success',
|
||||
title: 'Transaction success',
|
||||
message: `<a href="https://ropsten.etherscan.io/tx/${txid}">detail</a>`,
|
||||
message: `<a href="${ selectedCoin.explorer }/tx/${txid}" class="green" target="_blank" rel="noreferrer noopener">See transaction detail</a>`,
|
||||
cancelable: true,
|
||||
actions: []
|
||||
}
|
||||
@ -736,23 +759,5 @@ export const onSend = (): any => {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// const tx = new EthereumjsTx(txData);
|
||||
// console.log("2222", tx, tx.toJSON(), tx.from, tx.to);
|
||||
// const serializedTx = '0x' + tx.serialize().toString('hex');
|
||||
|
||||
// console.log("----> PUSZ TX", web3, currentAddress, serializedTx)
|
||||
// const txid = await pushTx(web3, serializedTx);
|
||||
// console.log("----> PUSZ TX2", web3, serializedTx)
|
||||
|
||||
// dispatch({
|
||||
// type: SEND.TX_COMPLETE,
|
||||
// address: currentAddress,
|
||||
// txid,
|
||||
// txData,
|
||||
// })
|
||||
|
||||
// const [ url ] = getState().router.location.pathname.split('/send');
|
||||
// dispatch( push(url) );
|
||||
}
|
||||
}
|
||||
|
@ -106,11 +106,12 @@ export const onDetailsToggle = (): any => {
|
||||
|
||||
|
||||
|
||||
export const loadTokens = (input: string): any => {
|
||||
export const loadTokens = (input: string, account: any): any => {
|
||||
return async (dispatch, getState): Promise<any> => {
|
||||
|
||||
if (input.length < 1) return null;
|
||||
|
||||
// TODO (eth tokens, etc tokens, ropsten tokens ...)
|
||||
const { ethTokens } = getState().localStorage;
|
||||
|
||||
const value = input.toLowerCase();
|
||||
@ -121,18 +122,14 @@ export const loadTokens = (input: string): any => {
|
||||
);
|
||||
//const result = ethTokens.filter(t => t.symbol.toLowerCase().indexOf(lower) >= 0);
|
||||
|
||||
console.log("RESULT!", result.length, result)
|
||||
|
||||
if (result.length > 0) {
|
||||
return { options: result };
|
||||
} else {
|
||||
const web3instance = getState().web3.find(w3 => w3.coin === 'eth');
|
||||
const web3instance = getState().web3.find(w3 => w3.coin === account.coin);
|
||||
|
||||
const info = await getTokenInfoAsync(web3instance.erc20, input);
|
||||
info.address = input;
|
||||
|
||||
console.log("FETCH", info)
|
||||
|
||||
if (info) {
|
||||
return {
|
||||
options: [ info ]
|
||||
@ -143,13 +140,9 @@ export const loadTokens = (input: string): any => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//await resolveAfter(300000);
|
||||
//await resolveAfter(3000);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -158,10 +151,7 @@ export const loadTokens = (input: string): any => {
|
||||
export const selectToken = (token: any, account: any): any => {
|
||||
return async (dispatch, getState): Promise<any> => {
|
||||
|
||||
console.warn("ADD", token, account)
|
||||
|
||||
const web3instance = getState().web3.find(w3 => w3.coin === account.coin);
|
||||
|
||||
dispatch({
|
||||
type: TOKEN.ADD,
|
||||
payload: {
|
||||
@ -171,7 +161,6 @@ export const selectToken = (token: any, account: any): any => {
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: load token balance
|
||||
const tokenBalance = await getTokenBalanceAsync(web3instance.erc20, token.address, account.address);
|
||||
dispatch({
|
||||
type: TOKEN.SET_BALANCE,
|
||||
@ -185,6 +174,13 @@ export const selectToken = (token: any, account: any): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const removeToken = (token: any): any => {
|
||||
return {
|
||||
type: TOKEN.REMOVE,
|
||||
token
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const onTokenSearch = (search: string): any => {
|
||||
|
@ -19,7 +19,7 @@ import { getTransactionHistory } from '../services/EtherscanService';
|
||||
|
||||
import { push } from 'react-router-redux';
|
||||
|
||||
import { init as initWeb3, getNonce, getBalanceAsync, getTokenBalanceAsync } from './Web3Actions';
|
||||
import { init as initWeb3, getNonceAsync, getBalanceAsync, getTokenBalanceAsync } from './Web3Actions';
|
||||
|
||||
import type { Discovery } from '../reducers/DiscoveryReducer';
|
||||
import { resolveAfter } from '../utils/promiseUtils';
|
||||
@ -53,6 +53,10 @@ export const init = (): any => {
|
||||
try {
|
||||
await TrezorConnect.init({
|
||||
transport_reconnect: true,
|
||||
coins_src: './data/coins.json',
|
||||
firmware_releases_src: './data/releases-1.json',
|
||||
transport_config_src: './data/config_signed.bin',
|
||||
latest_bridge_src: './data/latest.txt'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
@ -116,12 +120,19 @@ export const postInit = (): any => {
|
||||
export const initConnectedDevice = (device: any): any => {
|
||||
return (dispatch, getState): void => {
|
||||
|
||||
//dispatch( onSelectDevice(device) );
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
if (device.unacquired && selected && selected.path !== device.path && !selected.connected) {
|
||||
if (selected && selected.checksum) {
|
||||
dispatch( onSelectDevice(device) );
|
||||
} else if (!selected) {
|
||||
dispatch( onSelectDevice(device) );
|
||||
}
|
||||
// if (device.unacquired && selected && selected.path !== device.path && !selected.connected) {
|
||||
// dispatch( onSelectDevice(device) );
|
||||
// } else if (!selected) {
|
||||
// dispatch( onSelectDevice(device) );
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,47 +246,27 @@ export const getSelectedDeviceState = (): any => {
|
||||
export const deviceDisconnect = (device: any): any => {
|
||||
return async (dispatch, getState): Promise<void> => {
|
||||
|
||||
if (!device || !device.features) return null;
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
if (selected && selected.features.device_id === device.features.device_id) {
|
||||
stopDiscoveryProcess(selected);
|
||||
|
||||
if (device && device.features) {
|
||||
if (selected && selected.features.device_id === device.features.device_id) {
|
||||
stopDiscoveryProcess(selected);
|
||||
}
|
||||
|
||||
const affected = getState().connect.devices.filter(d => d.features && d.checksum && !d.remember && d.features.device_id === device.features.device_id);
|
||||
if (affected.length > 0) {
|
||||
dispatch({
|
||||
type: CONNECT.REMEMBER_REQUEST,
|
||||
device,
|
||||
allInstances: affected
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const affected = getState().connect.devices.filter(d => d.features && d.checksum && !d.remember && d.features.device_id === device.features.device_id);
|
||||
if (affected.length > 0) {
|
||||
dispatch({
|
||||
type: CONNECT.REMEMBER_REQUEST,
|
||||
device,
|
||||
allInstances: affected
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// if (selected && selected.checksum) {
|
||||
// if (device.features && device.features.device_id === selected.features.device_id) {
|
||||
// stopDiscoveryProcess(selected);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// // stop running discovery process on this device
|
||||
// if (selected && selected.path === device.path){
|
||||
// if (selected.checksum) {
|
||||
// stopDiscoveryProcess(selected);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // check if disconnected device was remembered before.
|
||||
// // request modal if not
|
||||
// const affected = getState().connect.devices.filter(d => d.path === device.path && d.checksum && !device.remember);
|
||||
|
||||
|
||||
// check if reload is needed
|
||||
if (!selected) {
|
||||
dispatch( switchToFirstAvailableDevice() );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,7 +388,7 @@ export const beginDiscoveryProcess = (device: any, coin: string): any => {
|
||||
return async (dispatch, getState) => {
|
||||
|
||||
const { config } = getState().localStorage;
|
||||
const coinToDiscover = config.coins.find(c => c.symbol === coin);
|
||||
const coinToDiscover = config.coins.find(c => c.network === coin);
|
||||
|
||||
// TODO: validate device checksum
|
||||
// const checksum = await __acquire(device.path, device.instance);
|
||||
@ -455,7 +446,7 @@ export const beginDiscoveryProcess = (device: any, coin: string): any => {
|
||||
// send data to reducer
|
||||
dispatch({
|
||||
type: DISCOVERY.START,
|
||||
coin: coinToDiscover.shortcut,
|
||||
coin: coinToDiscover.network,
|
||||
device,
|
||||
xpub: response.data.publicKey,
|
||||
basePath,
|
||||
@ -574,7 +565,7 @@ export const discoverAddress = (device: any, discoveryProcess: Discovery): any =
|
||||
})
|
||||
}
|
||||
|
||||
const nonce = await getNonce(web3instance.web3, ethAddress);
|
||||
const nonce = await getNonceAsync(web3instance.web3, ethAddress);
|
||||
if (discoveryProcess.interrupted) return;
|
||||
dispatch({
|
||||
type: ADDRESS.SET_NONCE,
|
||||
|
@ -15,6 +15,41 @@ import { httpRequest } from '../utils/networkUtils';
|
||||
|
||||
type ActionMethod = (dispatch: any, getState: any) => Promise<any>;
|
||||
|
||||
type Web3Payload =
|
||||
| {
|
||||
name: string;
|
||||
instance: Web3;
|
||||
chainId: number;
|
||||
erc20abi: any;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
blockHash: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
gasPrice: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
address: string;
|
||||
balance: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
address: string;
|
||||
nonce: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
blockHash: string;
|
||||
};
|
||||
|
||||
type Web3Action = {
|
||||
type: string,
|
||||
payload?: Web3Payload
|
||||
};
|
||||
|
||||
|
||||
export function init(web3: ?Web3, coinIndex: number = 0): ActionMethod {
|
||||
return async (dispatch, getState) => {
|
||||
@ -30,7 +65,7 @@ export function init(web3: ?Web3, coinIndex: number = 0): ActionMethod {
|
||||
return;
|
||||
}
|
||||
|
||||
const coinName = coin.shortcut;
|
||||
const coinName = coin.network;
|
||||
const urls = coin.backends[0].urls;
|
||||
|
||||
let web3host: string = urls[0];
|
||||
@ -106,36 +141,42 @@ export function init(web3: ?Web3, coinIndex: number = 0): ActionMethod {
|
||||
//const shh = instance.shh.newIdentity();
|
||||
|
||||
const latestBlockFilter = instance.eth.filter('latest');
|
||||
latestBlockFilter.watch(async (error, blockHash) => {
|
||||
|
||||
const onBlockMined = async (error, blockHash) => {
|
||||
if (error) {
|
||||
console.warn("ERROR!", error);
|
||||
|
||||
// setInterval(() => {
|
||||
// dispatch( getGasPrice(coinName) );
|
||||
// }, 5000);
|
||||
window.setTimeout(() => {
|
||||
// try again
|
||||
onBlockMined("manually_triggered_error", undefined);
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
if (blockHash) {
|
||||
dispatch({
|
||||
type: WEB3.BLOCK_UPDATED,
|
||||
name: coinName,
|
||||
blockHash
|
||||
});
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: WEB3.BLOCK_UPDATED,
|
||||
name: coinName,
|
||||
blockHash
|
||||
});
|
||||
|
||||
// TODO: filter only current device
|
||||
const accounts = getState().accounts.filter(a => a.coin === coinName);
|
||||
for (const addr of accounts) {
|
||||
dispatch( getBalance(addr) );
|
||||
dispatch( getNonce(addr) );
|
||||
}
|
||||
|
||||
dispatch( getGasPrice(coinName) );
|
||||
|
||||
// if (pendingTxs.length > 0) {
|
||||
// for (const tx of pendingTxs) {
|
||||
// dispatch( getTransactionReceipt(tx) );
|
||||
// }
|
||||
// }
|
||||
});
|
||||
const pending = getState().pending.filter(p => p.coin === coinName);
|
||||
for (const tx of pending) {
|
||||
dispatch( getTransactionReceipt(tx) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
latestBlockFilter.watch(onBlockMined);
|
||||
|
||||
|
||||
// init next coin
|
||||
dispatch( init(instance, coinIndex + 1) );
|
||||
@ -238,18 +279,46 @@ export function getBalance(addr: Address): ActionMethod {
|
||||
}
|
||||
}
|
||||
|
||||
export function getTransactionReceipt(txid: string): any {
|
||||
export function getNonce(addr: Address) {
|
||||
|
||||
return async (dispatch, getState) => {
|
||||
const { web3 } = getState().web3;
|
||||
//web3.eth.getTransactionReceipt(txid, (error, tx) => {
|
||||
web3.eth.getTransaction(txid, (error, tx) => {
|
||||
if (tx && tx.blockNumber) {
|
||||
web3.eth.getBlock(tx.blockHash, (error, block) => {
|
||||
console.log("---MAMM BLOCK", error, block, tx, tx.blockHash)
|
||||
|
||||
const web3instance = getState().web3.filter(w3 => w3.coin === addr.coin)[0];
|
||||
const web3 = web3instance.web3;
|
||||
|
||||
web3.eth.getTransactionCount(addr.address, (error, result) => {
|
||||
if (!error) {
|
||||
if (addr.nonce !== result) {
|
||||
dispatch({
|
||||
type: ACTIONS.TX_CONFIRMED,
|
||||
txid,
|
||||
type: ADDRESS.SET_NONCE,
|
||||
address: addr.address,
|
||||
nonce: result
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getTransactionReceipt(tx: any): any {
|
||||
return async (dispatch, getState) => {
|
||||
|
||||
const web3instance = getState().web3.filter(w3 => w3.coin === tx.coin)[0];
|
||||
const web3 = web3instance.web3;
|
||||
|
||||
//web3.eth.getTransactionReceipt(txid, (error, tx) => {
|
||||
web3.eth.getTransaction(tx.id, (error, receipt) => {
|
||||
console.log("RECEIP", receipt)
|
||||
if (receipt && receipt.blockNumber) {
|
||||
web3.eth.getBlock(receipt.blockHash, (error, block) => {
|
||||
console.log("---MAMM BLOCK", error, block, receipt, receipt.blockHash)
|
||||
dispatch({
|
||||
//type: ACTIONS.TX_CONFIRMED,
|
||||
type: WEB3.PENDING_TX_RESOLVED,
|
||||
tx,
|
||||
receipt,
|
||||
block
|
||||
})
|
||||
});
|
||||
@ -306,7 +375,7 @@ export const getTokenBalanceAsync = (erc20: any, token: any, address: any): Prom
|
||||
});
|
||||
}
|
||||
|
||||
export function getNonce(web3, address) {
|
||||
export function getNonceAsync(web3, address) {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.getTransactionCount(address, (error, result) => {
|
||||
if (error) {
|
||||
@ -389,81 +458,6 @@ export function pushTx(web3, tx) {
|
||||
})
|
||||
}
|
||||
|
||||
export function composeTransaction() {
|
||||
return async function (dispatch, getState) {
|
||||
const { web3 } = getState().web3;
|
||||
const { address, amount } = getState().sendForm;
|
||||
|
||||
const resp = await TrezorConnect.getPublicKey({ path: "m/44'/60'/0'/0", confirmation: false });
|
||||
|
||||
const hdk = new HDKey();
|
||||
hdk.publicKey = new Buffer(resp.data.publicKey, 'hex');
|
||||
hdk.chainCode = new Buffer(resp.data.chainCode, 'hex');
|
||||
|
||||
const derivedKey = hdk.derive("m/0");
|
||||
const myAddress = EthereumjsUtil.publicToAddress(derivedKey.publicKey, true);
|
||||
|
||||
const txData = {
|
||||
address_n: [
|
||||
(44 | 0x80000000) >>> 0,
|
||||
(60 | 0x80000000) >>> 0,
|
||||
(0 | 0x80000000) >>> 0,
|
||||
0, 0
|
||||
],
|
||||
to: address,
|
||||
value: web3.toHex(web3.toWei(amount, 'ether')),
|
||||
data,
|
||||
chainId: 3
|
||||
}
|
||||
|
||||
console.log("NONCE", myAddress)
|
||||
const nonce = await getNonce(web3, '0x' + myAddress.toString('hex') );
|
||||
console.log("NONCE", nonce)
|
||||
|
||||
const gasOptions = {
|
||||
to: txData.to,
|
||||
data: txData.data
|
||||
}
|
||||
const gasLimit = await estimateGas(web3, gasOptions);
|
||||
const gasPrice = await getGasPrice(web3);
|
||||
|
||||
txData.nonce = web3.toHex(nonce);
|
||||
txData.gasLimit = web3.toHex(gasLimit);
|
||||
txData.gasPrice = web3.toHex(gasPrice);
|
||||
|
||||
console.log("NONCE", nonce, gasLimit, gasPrice)
|
||||
|
||||
let signedTransaction = await TrezorConnect.ethereumSignTransaction({
|
||||
//path: "m/44'/60'/0'/0/0",
|
||||
address_n: txData.address_n,
|
||||
nonce: strip(txData.nonce),
|
||||
gas_price: strip(txData.gasPrice),
|
||||
gas_limit: strip(txData.gasLimit),
|
||||
to: strip(txData.to),
|
||||
value: strip(txData.value),
|
||||
data: txData.data,
|
||||
chain_id: txData.chainId
|
||||
});
|
||||
|
||||
txData.r = '0x' + signedTransaction.data.r;
|
||||
txData.s = '0x' + signedTransaction.data.s;
|
||||
txData.v = web3.toHex(signedTransaction.data.v);
|
||||
|
||||
const tx = new EthereumjsTx(txData);
|
||||
const serializedTx = '0x' + tx.serialize().toString('hex');
|
||||
|
||||
const txid = await pushTx(web3, serializedTx);
|
||||
|
||||
dispatch({
|
||||
type: 'tx_complete',
|
||||
txid
|
||||
})
|
||||
|
||||
console.log("TXID", txid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,4 +6,5 @@ export const STOP: string = 'web3__stop';
|
||||
export const CREATE: string = 'web3__create';
|
||||
export const READY: string = 'web3__ready';
|
||||
export const BLOCK_UPDATED: string = 'web3__block_updated';
|
||||
export const GAS_PRICE_UPDATED: string = 'web3__gas_price_updated';
|
||||
export const GAS_PRICE_UPDATED: string = 'web3__gas_price_updated';
|
||||
export const PENDING_TX_RESOLVED: string = 'web3__pending_tx_resolved';
|
@ -15,7 +15,6 @@ export const ON_GAS_PRICE_CHANGE: string = 'send__on_gas_price_change';
|
||||
export const ON_GAS_LIMIT_CHANGE: string = 'send__on_gas_limit_change';
|
||||
export const ON_TX_DATA_CHANGE: string = 'send__on_data_change';
|
||||
export const ON_TX_SEND: string = 'send__on_send';
|
||||
export const ON_TX_COMPLETE: string = 'send__on_tx_complete';
|
||||
export const ON_GAS_PRICE_UPDATE: string = 'send__on_gas_price_update';
|
||||
|
||||
|
||||
|
@ -2,16 +2,31 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as LogActions from '../../actions/LogActions';
|
||||
|
||||
const Footer = (props: any): any => {
|
||||
return (
|
||||
<footer>
|
||||
<span>© 2018</span>
|
||||
<a href="http://satoshilabs.com" target="_blank" className="satoshi green">SatoshiLabs</a>
|
||||
<a href="tos.pdf" target="_blank" className="green">Terms</a>
|
||||
<a onClick={ props.showLog } className="green">Show Log</a>
|
||||
<a href="http://satoshilabs.com" target="_blank" rel="noreferrer noopener" className="satoshi green">SatoshiLabs</a>
|
||||
<a href="tos.pdf" target="_blank" rel="noreferrer noopener" className="green">Terms</a>
|
||||
<a onClick={ props.toggle } className="green">Show Log</a>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
export default connect(
|
||||
(state) => {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
(dispatch) => {
|
||||
return {
|
||||
toggle: bindActionCreators(LogActions.toggle, dispatch),
|
||||
};
|
||||
}
|
||||
)(Footer);
|
||||
|
@ -8,9 +8,26 @@ export default class Header extends Component {
|
||||
return (
|
||||
<header>
|
||||
<div className="layout-wrapper">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2567.5 722.3" width="100%" height="100%" preserveAspectRatio="xMinYMin meet"><path d="M1186 2932.6h46.2v147H1186v-147z"></path><path d="M249 0C149.9 0 69.7 80.2 69.7 179.3v67.2C34.9 252.8 0 261.2 0 272.1v350.7s0 9.7 10.9 14.3c39.5 16 194.9 71 230.6 83.6 4.6 1.7 5.9 1.7 7.1 1.7 1.7 0 2.5 0 7.1-1.7 35.7-12.6 191.5-67.6 231-83.6 10.1-4.2 10.5-13.9 10.5-13.9V272.1c0-10.9-34.4-19.7-69.3-25.6v-67.2C428.4 80.2 347.7 0 249 0zm0 85.7c58.4 0 93.7 35.3 93.7 93.7v58.4c-65.5-4.6-121.4-4.6-187.3 0v-58.4c0-58.5 35.3-93.7 93.6-93.7zm-.4 238.1c81.5 0 149.9 6.3 149.9 17.6v218.8c0 3.4-.4 3.8-3.4 5-2.9 1.3-139 50.4-139 50.4s-5.5 1.7-7.1 1.7c-1.7 0-7.1-2.1-7.1-2.1s-136.1-49.1-139-50.4-3.4-1.7-3.4-5V341c-.8-11.3 67.6-17.2 149.1-17.2z"></path><g transform="translate(91.363 -287.434) scale(.95575)"><path d="M666.6 890V639.3H575v-89.9h285.6v89.9h-90.7V890H666.6z"></path><path d="M1092 890l-47-107.1h-37.4V890H904.3V549.4h181.8c79.8 0 122.6 52.9 122.6 116.7 0 58.8-34 89.9-61.3 103.3l61.7 120.5H1092zm12.2-223.9c0-18.5-16.4-26.5-33.6-26.5h-63v53.8h63c17.2-.4 33.6-8.4 33.6-27.3z"></path><path d="M1262.9 890V549.4h258.3v89.9h-155.4v33.6h151.6v89.9h-151.6v37.4h155.4V890h-258.3z"></path><path d="M1574.9 890.4v-81.9l129.8-168.8h-129.8v-89.9h265.8v81.1l-130.2 169.7h134v89.9l-269.6-.1z"></path><path d="M1869.7 720.3c0-104.6 81.1-176.4 186.5-176.4 105 0 186.5 71.4 186.5 176.4 0 104.6-81.1 176-186.5 176s-186.5-71.4-186.5-176zm268 0c0-47.5-32.3-85.3-81.9-85.3-49.6 0-81.9 37.8-81.9 85.3s32.3 85.3 81.9 85.3c50 0 81.9-37.8 81.9-85.3z"></path><path d="M2473.6 890.4l-47-107.1h-37.4v107.1h-103.3V549.8h181.8c79.8 0 122.6 52.9 122.6 116.7 0 58.8-34 89.9-61.3 103.3l61.7 120.5h-117.1zm12.6-224.3c0-18.5-16.4-26.5-33.6-26.5h-63v53.8h63c17.3-.4 33.6-8.4 33.6-27.3z"></path></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 163.7 41.9" width="100%" height="100%" preserveAspectRatio="xMinYMin meet">
|
||||
<polygon points="101.1,12.8 118.2,12.8 118.2,17.3 108.9,29.9 118.2,29.9 118.2,35.2 101.1,35.2 101.1,30.7 110.4,18.1 101.1,18.1"/>
|
||||
<path d="M158.8,26.9c2.1-0.8,4.3-2.9,4.3-6.6c0-4.5-3.1-7.4-7.7-7.4h-10.5v22.3h5.8v-7.5h2.2l4.1,7.5h6.7L158.8,26.9z M154.7,22.5 h-4V18h4c1.5,0,2.5,0.9,2.5,2.2C157.2,21.6,156.2,22.5,154.7,22.5z"/>
|
||||
<path d="M130.8,12.5c-6.8,0-11.6,4.9-11.6,11.5s4.9,11.5,11.6,11.5s11.7-4.9,11.7-11.5S137.6,12.5,130.8,12.5z M130.8,30.3 c-3.4,0-5.7-2.6-5.7-6.3c0-3.8,2.3-6.3,5.7-6.3c3.4,0,5.8,2.6,5.8,6.3C136.6,27.7,134.2,30.3,130.8,30.3z"/>
|
||||
<polygon points="82.1,12.8 98.3,12.8 98.3,18 87.9,18 87.9,21.3 98,21.3 98,26.4 87.9,26.4 87.9,30 98.3,30 98.3,35.2 82.1,35.2 "/>
|
||||
<path d="M24.6,9.7C24.6,4.4,20,0,14.4,0S4.2,4.4,4.2,9.7v3.1H0v22.3h0l14.4,6.7l14.4-6.7h0V12.9h-4.2V9.7z M9.4,9.7 c0-2.5,2.2-4.5,5-4.5s5,2,5,4.5v3.1H9.4V9.7z M23,31.5l-8.6,4l-8.6-4V18.1H23V31.5z"/>
|
||||
<path d="M79.4,20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1,7.5H80l-4.9-8.3C77.2,26.1,79.4,24,79.4,20.3z M71,22.5h-4V18 h4c1.5,0,2.5,0.9,2.5,2.2C73.5,21.6,72.5,22.5,71,22.5z"/>
|
||||
<polygon points="40.5,12.8 58.6,12.8 58.6,18.1 52.4,18.1 52.4,35.2 46.6,35.2 46.6,18.1 40.5,18.1 "/>
|
||||
</svg>
|
||||
<div>
|
||||
<a href="https://trezor.io/" target="_blank" rel="noreferrer noopener">TREZOR</a>
|
||||
<a href="https://doc.satoshilabs.com/trezor-user/" target="_blank" rel="noreferrer noopener">Docs</a>
|
||||
<a href="https://blog.trezor.io/" target="_blank" rel="noreferrer noopener">Blog</a>
|
||||
<a href="https://trezor.io/support/" target="_blank" rel="noreferrer noopener">Support</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -5,36 +5,32 @@ import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as SendFormActions from '../../actions/SendFormActions';
|
||||
import { getAddress } from '../../actions/TrezorConnectActions';
|
||||
|
||||
import * as LogActions from '../../actions/LogActions';
|
||||
|
||||
const Log = (props: any) => {
|
||||
|
||||
if (!props.log.opened)
|
||||
return null;
|
||||
|
||||
return (
|
||||
<details className="log">
|
||||
Log
|
||||
</details>
|
||||
<div className="log">
|
||||
<button className="log-close transparent" onClick={ props.toggle }></button>
|
||||
<h2>Log</h2>
|
||||
<p>Attention: The log contains your XPUBs. Anyone with your XPUBs can see your account history.</p>
|
||||
<textarea></textarea>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function mapStateToProps(state, own) {
|
||||
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state) => {
|
||||
return {
|
||||
accounts: state.accounts,
|
||||
receive: state.receive
|
||||
log: state.log
|
||||
};
|
||||
},
|
||||
(dispatch) => {
|
||||
return {
|
||||
getAddress: bindActionCreators(getAddress, dispatch),
|
||||
toggle: bindActionCreators(LogActions.toggle, dispatch),
|
||||
};
|
||||
}
|
||||
)(Log);
|
@ -25,10 +25,10 @@ export default (props: any): any => {
|
||||
</svg>
|
||||
<span>Connect TREZOR to continue</span>
|
||||
</p>
|
||||
{/* <p>Don't have TREZOR? <a href="https://trezor.io/" target="_blank">Get one</a></p> */}
|
||||
{/* <p>Don't have TREZOR? <a href="https://trezor.io/" target="_blank" rel="noreferrer noopener">Get one</a></p> */}
|
||||
</div>
|
||||
<div className="image"></div>
|
||||
<p>Don't have TREZOR? <a href="https://trezor.io/" className="green" target="_blank">Get one</a></p>
|
||||
<p>Don't have TREZOR? <a href="https://trezor.io/" className="green" target="_blank" rel="noreferrer noopener">Get one</a></p>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
@ -8,6 +8,7 @@ import LocalStorageError from './LocalStorageError';
|
||||
import TrezorConnectError from './TrezorConnectError';
|
||||
import Header from '../common/Header';
|
||||
import Footer from '../common/Footer';
|
||||
import Log from '../common/Log';
|
||||
import { Notification } from '../common/Notification';
|
||||
|
||||
export default (props: any): any => {
|
||||
@ -40,6 +41,7 @@ export default (props: any): any => {
|
||||
<div className="app connect-device">
|
||||
<Header />
|
||||
{ notification }
|
||||
<Log />
|
||||
<main>
|
||||
<h2 className="claim">The private bank in your hands.</h2>
|
||||
<p>TREZOR Wallet is an easy-to-use interface for your TREZOR.</p>
|
||||
@ -59,10 +61,11 @@ export default (props: any): any => {
|
||||
</span>
|
||||
</p>
|
||||
{/* <button>Add new device</button> */}
|
||||
{/* <p>Don't have TREZOR? <a href="https://trezor.io/" target="_blank">Get one</a></p> */}
|
||||
{/* <p>Don't have TREZOR? <a href="https://trezor.io/" target="_blank" rel="noreferrer noopener">Get one</a></p> */}
|
||||
</div>
|
||||
<div className="image">
|
||||
<p>Don't have TREZOR? <a href="https://trezor.io/" className="green" target="_blank" rel="noreferrer noopener">Get one</a></p>
|
||||
</div>
|
||||
<div className="image"></div>
|
||||
<p>Don't have TREZOR? <a href="https://trezor.io/" className="green" target="_blank">Get one</a></p>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
@ -7,6 +7,8 @@ import { findSelectedDevice } from '../../reducers/TrezorConnectReducer';
|
||||
const ConfirmAddress = (props: any): any => {
|
||||
|
||||
const account = props.accounts.find(a => a.checksum === props.receive.checksum && a.index === props.receive.accountIndex && a.coin === props.receive.coin);
|
||||
const { config } = props.localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.network === account.coin);
|
||||
|
||||
return (
|
||||
<div className="confirm-address">
|
||||
@ -16,7 +18,7 @@ const ConfirmAddress = (props: any): any => {
|
||||
</div>
|
||||
<div className="content">
|
||||
<p>{ account.address }</p>
|
||||
<label>{ account.coin.toUpperCase() } account #{ (account.index + 1) }</label>
|
||||
<label>{ selectedCoin.symbol } account #{ (account.index + 1) }</label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -8,6 +8,7 @@ const Confirmation = (props): any => {
|
||||
amount,
|
||||
address,
|
||||
coin,
|
||||
coinSymbol,
|
||||
token,
|
||||
total,
|
||||
selectedFeeLevel
|
||||
@ -21,7 +22,7 @@ const Confirmation = (props): any => {
|
||||
</div>
|
||||
<div className="content">
|
||||
<label>Send </label>
|
||||
<p>{ `${amount} ${token.toUpperCase() }` }</p>
|
||||
<p>{ `${amount} ${ coinSymbol }` }</p>
|
||||
<label>To</label>
|
||||
<p>{ address }</p>
|
||||
<label>Fee</label>
|
||||
|
@ -103,6 +103,7 @@ const mapStateToProps = (state: any, own: any): any => {
|
||||
devices: state.connect.devices,
|
||||
sendForm: state.sendForm,
|
||||
receive: state.receive,
|
||||
localStorage: state.localStorage
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ export default class PinModal extends Component {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
console.warn("PROPZ", props)
|
||||
// check if this device is already known
|
||||
const isSavedDevice = props.devices.find(d => d.path === props.modal.device.path && d.remember);
|
||||
|
||||
this.state = {
|
||||
|
@ -133,8 +133,8 @@ export default class Pin extends Component {
|
||||
<button type="button" data-value="3" onClick={ event => this.onPinAdd(3) }>•</button>
|
||||
</div>
|
||||
|
||||
<div><button className="submit" type="button" onClick={ event => onPinSubmit(pin) }>Enter pin</button></div>
|
||||
<p>Not sure how PIN works? <a className="green" href="http://doc.satoshilabs.com/trezor-user/enteringyourpin.html" target="_blank">Learn more</a></p>
|
||||
<div><button className="submit" type="button" onClick={ event => onPinSubmit(pin) }>Enter PIN</button></div>
|
||||
<p>Not sure how PIN works? <a className="green" href="http://doc.satoshilabs.com/trezor-user/enteringyourpin.html" target="_blank" rel="noreferrer noopener">Learn more</a></p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -2,17 +2,36 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Notification } from '../common/Notification';
|
||||
|
||||
const Acquire = (props: any): any => {
|
||||
|
||||
const actions = [
|
||||
{
|
||||
label: 'Acquire device',
|
||||
callback: () => {
|
||||
props.acquireDevice()
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="acquire">
|
||||
<div className="warning">
|
||||
<Notification
|
||||
title="Device is used in other window"
|
||||
message="Do you want to use your device in this window?"
|
||||
className="info"
|
||||
cancelable={false}
|
||||
actions={actions}
|
||||
close={ () => {} }
|
||||
/>
|
||||
{/* <div className="warning">
|
||||
<div>
|
||||
<h2>Device is used in other window</h2>
|
||||
<p>Do you want to use your device in this window?</p>
|
||||
<h2></h2>
|
||||
<p></p>
|
||||
</div>
|
||||
<button onClick={ event => props.acquireDevice() }>Acquire device</button>
|
||||
</div>
|
||||
</div> */}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ const History = (props): any => {
|
||||
|
||||
return (
|
||||
<div key={i} className="history-pending-transaction">
|
||||
<a href={ etherscanLink } target="_blank">Details</a>
|
||||
<a href={ etherscanLink } target="_blank" rel="noreferrer noopener">Details</a>
|
||||
<span className="address">{ tx.to }</span>
|
||||
Pending...
|
||||
</div>
|
||||
|
@ -14,25 +14,6 @@ export default class AbstractAccount extends Component {
|
||||
this.props.updateAccount();
|
||||
}
|
||||
|
||||
// shouldInitAccount(newProps: any): boolean {
|
||||
// const locationChanged: boolean = newProps.location.pathname !== this.props.location.pathname;
|
||||
// const accountNotLoaded: boolean = !newProps.detail.loaded && !this.props.detail.loaded;
|
||||
// return (locationChanged || accountNotLoaded);
|
||||
// }
|
||||
|
||||
// shouldUpdateAccount(newProps: any): boolean {
|
||||
// const { detail } = this.props;
|
||||
// const loaded: boolean = detail.loaded;
|
||||
|
||||
// if (detail.address === '') {
|
||||
// const currentAccount = this.props.accounts.find(a => a.index === detail.addressIndex && a.coin === detail.coin && a.checksum === detail.checksum);
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// // return (loaded && );
|
||||
// }
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.disposeAccount();
|
||||
}
|
||||
|
@ -1,9 +1,62 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
type State = {
|
||||
style: any;
|
||||
|
||||
}
|
||||
|
||||
class Indicator extends Component {
|
||||
|
||||
state: State;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
style: {
|
||||
width: 0,
|
||||
left: 0
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.reposition();
|
||||
}
|
||||
|
||||
componentDidUpdate(newProps: any) {
|
||||
this.reposition();
|
||||
}
|
||||
|
||||
reposition() {
|
||||
const tabs = document.querySelector('.account-tabs');
|
||||
const active = tabs.querySelector('.active');
|
||||
const bounds = active.getBoundingClientRect();
|
||||
|
||||
const left = bounds.left - tabs.getBoundingClientRect().left;
|
||||
|
||||
if (this.state.style.left !== left) {
|
||||
this.setState({
|
||||
style: {
|
||||
width: bounds.width,
|
||||
left: left,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="indicator" style={ this.state.style }>{ this.props.pathname }</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const AccountTabs = (props: any): any => {
|
||||
|
||||
const urlParams = props.match.params;
|
||||
@ -24,9 +77,10 @@ const AccountTabs = (props: any): any => {
|
||||
<NavLink to={ `${basePath}/receive` }>
|
||||
Receive
|
||||
</NavLink>
|
||||
<NavLink to={ `${basePath}/signverify` }>
|
||||
{/* <NavLink to={ `${basePath}/signverify` }>
|
||||
Sign & Verify
|
||||
</NavLink>
|
||||
</NavLink> */}
|
||||
<Indicator pathname={props.match.pathname } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import BigNumber from 'bignumber.js';
|
||||
import { getAccounts } from '../../../utils/reducerUtils';
|
||||
import { findSelectedDevice } from '../../../reducers/TrezorConnectReducer';
|
||||
import Loader from '../../common/LoaderCircle';
|
||||
import Tooltip from 'rc-tooltip';
|
||||
|
||||
|
||||
const AccountSelection = (props: any): any => {
|
||||
|
||||
@ -17,7 +19,11 @@ const AccountSelection = (props: any): any => {
|
||||
const { location } = props.router;
|
||||
const accounts = props.accounts;
|
||||
const baseUrl: string = `/device/${location.params.device}`;
|
||||
const fiatRate = props.fiatRate || '1';
|
||||
|
||||
const { config } = props.localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.network === location.params.coin);
|
||||
|
||||
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
||||
|
||||
// console.warn("AccountSelectionRender", selected, props);
|
||||
|
||||
@ -25,9 +31,18 @@ const AccountSelection = (props: any): any => {
|
||||
let selectedAccounts = deviceAddresses.map((address, i) => {
|
||||
// const url: string = `${baseUrl}/coin/${location.params.coin}/address/${i}`;
|
||||
const url: string = location.pathname.replace(/address+\/([0-9]*)/, `address/${i}`);
|
||||
const b = new BigNumber(address.balance);
|
||||
const fiat = b.times(fiatRate).toFixed(2);
|
||||
const balance = address.balance !== '' ? `${ address.balance } ${ location.params.coin.toUpperCase() } / $${ fiat }` : 'Loading...';
|
||||
|
||||
let balance: string = 'Loading...';
|
||||
if (address.balance !== '') {
|
||||
if (fiatRate) {
|
||||
const accountBalance = new BigNumber(address.balance);
|
||||
const fiat = accountBalance.times(fiatRate.value).toFixed(2);
|
||||
balance = `${ address.balance } ${ selectedCoin.symbol } / $${ fiat }`;
|
||||
} else {
|
||||
balance = `${ address.balance } ${ selectedCoin.symbol }`;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<NavLink key={i} activeClassName="selected" className="account" to={ url }>
|
||||
{ `Address #${(address.index + 1 )}` }
|
||||
@ -54,34 +69,54 @@ const AccountSelection = (props: any): any => {
|
||||
if (discovery) {
|
||||
if (discovery.completed) {
|
||||
// TODO: add only if last one is not empty
|
||||
discoveryStatus = (
|
||||
<div className="add-address" onClick={ props.addAddress } >
|
||||
Add address
|
||||
</div>
|
||||
)
|
||||
//if (selectedAccounts.length > 0 && selectedAccounts[selectedAccounts.length - 1])
|
||||
const lastAccount = deviceAddresses[deviceAddresses.length - 1];
|
||||
if (lastAccount && new BigNumber(lastAccount.balance).greaterThan(0) || lastAccount.nonce > 0) {
|
||||
discoveryStatus = (
|
||||
<div className="add-address" onClick={ props.addAddress }>
|
||||
Add address
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
const tooltip = (
|
||||
<div className="aside-tooltip-wrapper">
|
||||
To add a new address, last address must have some transactions.
|
||||
</div>
|
||||
)
|
||||
discoveryStatus = (
|
||||
<Tooltip
|
||||
arrowContent={<div className="rc-tooltip-arrow-inner"></div>}
|
||||
overlay={ tooltip }
|
||||
placement="top">
|
||||
<div className="add-address disabled">
|
||||
Add address
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
} else if (!selected.connected) {
|
||||
discoveryStatus = (
|
||||
<div className="discovery-status">
|
||||
Addresses could not be loaded
|
||||
<span>{ `Connect ${ selected.instanceLabel } device` }</span>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
} else {
|
||||
discoveryStatus = (
|
||||
<div className="discovery-loading">
|
||||
<Loader size="20" /> Loading accounts...
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const { config } = props.localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.shortcut === location.params.coin);
|
||||
|
||||
let backButton = null;
|
||||
if (selectedCoin) {
|
||||
backButton = (
|
||||
<NavLink to={ baseUrl } className={ `back ${ selectedCoin.shortcut }` }>
|
||||
<span className={ selectedCoin.shortcut }>{ selectedCoin.name }</span>
|
||||
<NavLink to={ baseUrl } className={ `back ${ selectedCoin.network }` }>
|
||||
<span className={ selectedCoin.network }>{ selectedCoin.name }</span>
|
||||
</NavLink>
|
||||
);
|
||||
}
|
||||
@ -89,7 +124,9 @@ const AccountSelection = (props: any): any => {
|
||||
return (
|
||||
<section>
|
||||
{ backButton }
|
||||
{ selectedAccounts }
|
||||
<div>
|
||||
{ selectedAccounts }
|
||||
</div>
|
||||
{ discoveryStatus }
|
||||
</section>
|
||||
);
|
||||
|
@ -41,7 +41,7 @@ const Aside = (props: any): any => {
|
||||
// return (
|
||||
// <aside>
|
||||
// <div className="transition-container"></div>
|
||||
// <a className="help" href="https://trezor.io/support/" target="_blank">
|
||||
// <a className="help" href="https://trezor.io/support/" target="_blank" rel="noreferrer noopener">
|
||||
// Need help?
|
||||
// </a>
|
||||
// </aside>
|
||||
@ -66,14 +66,12 @@ const Aside = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
console.warn("ASIDEE", props)
|
||||
|
||||
return (
|
||||
<StickyContainer location={ location } devices={ props.deviceDropdownOpened.toString() }>
|
||||
<DeviceSelect {...props} />
|
||||
{ menu }
|
||||
<div className="help">
|
||||
<a href="https://trezor.io/support/" target="_blank">Need help?</a>
|
||||
<a href="https://trezor.io/support/" target="_blank" rel="noreferrer noopener">Need help?</a>
|
||||
</div>
|
||||
</StickyContainer>
|
||||
)
|
||||
|
@ -9,10 +9,10 @@ const CoinSelection = (props: any): any => {
|
||||
const { config } = props.localStorage;
|
||||
|
||||
const walletCoins = config.coins.map(item => {
|
||||
const url = `${ location.pathname }/coin/${ item.shortcut }/address/0`;
|
||||
const className = `coin ${ item.shortcut }`
|
||||
const url = `${ location.pathname }/coin/${ item.network }/address/0`;
|
||||
const className = `coin ${ item.network }`
|
||||
return (
|
||||
<NavLink key={ item.shortcut } to={ url } className={ className }>
|
||||
<NavLink key={ item.network } to={ url } className={ className }>
|
||||
{ item.name }
|
||||
</NavLink>
|
||||
)
|
||||
|
@ -70,7 +70,9 @@ const Value = (props: any): any => {
|
||||
<span className="label">{ device.instanceLabel }</span>
|
||||
<span className="status">{ deviceStatus }</span>
|
||||
</div>
|
||||
{ deviceMenu }
|
||||
<div className="device-menu">
|
||||
{ deviceMenuButtons }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ const AdvancedForm = (props: any): any => {
|
||||
Gas Price is the amount you pay per unit of gas.<br/>
|
||||
<span>TX fee = gas price * gas limit</span> & is paid to miners for including your TX in a block.<br/>
|
||||
Higher the gas price = faster transaction, but more expensive. Default is <span>{ gasPrice } GWEI.</span><br/>
|
||||
<a className="green" href="https://myetherwallet.github.io/knowledge-base/gas/what-is-gas-ethereum.html" target="_blank">Read more</a>
|
||||
<a className="green" href="https://myetherwallet.github.io/knowledge-base/gas/what-is-gas-ethereum.html" target="_blank" rel="noreferrer noopener">Read more</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -123,8 +123,6 @@ const AdvancedForm = (props: any): any => {
|
||||
{ props.children }
|
||||
</div>
|
||||
|
||||
<ReactTooltip html={true} effect="solid" place="right" offset={{ bottom: 6, right: 24 }} />
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ColorHash from 'color-hash';
|
||||
import ScaleText from 'react-scale-text';
|
||||
|
||||
const PendingTransactions = (props: any): any => {
|
||||
|
||||
const account = props.accounts.find(a => a.checksum === props.sendForm.checksum && a.index === props.sendForm.accountIndex && a.coin === props.sendForm.coin);
|
||||
const pending = props.pending.filter(p => p.coin === account.coin && p.address === account.address);
|
||||
|
||||
if (pending.length < 1) return null;
|
||||
|
||||
const tokens = props.tokens.filter(t => t.ethAddress === account.address);
|
||||
|
||||
const bgColor = new ColorHash({lightness: 0.7});
|
||||
const textColor = new ColorHash();
|
||||
|
||||
const pendings = pending.map((tx, i) => {
|
||||
|
||||
let iconColor, symbol, name;
|
||||
|
||||
if (tx.token !== tx.coin) {
|
||||
const token = tokens.find(t => t.symbol === tx.token);
|
||||
iconColor = {
|
||||
color: textColor.hex(token.name),
|
||||
background: bgColor.hex(token.name),
|
||||
borderColor: bgColor.hex(token.name)
|
||||
}
|
||||
symbol = token.symbol.toUpperCase();
|
||||
name = token.name;
|
||||
} else {
|
||||
iconColor = {
|
||||
color: textColor.hex(tx.coin),
|
||||
background: bgColor.hex(tx.coin),
|
||||
borderColor: bgColor.hex(tx.coin)
|
||||
}
|
||||
symbol = props.selectedCoin.symbol;
|
||||
name = props.selectedCoin.name;
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={i} className="tx">
|
||||
<div className="icon" style={ iconColor }>
|
||||
<div className="icon-inner">
|
||||
<ScaleText widthOnly><p>{ symbol }</p></ScaleText>
|
||||
</div>
|
||||
</div>
|
||||
<div className="name">
|
||||
<a href={ `${props.selectedCoin.explorer}/tx/${tx.id}`} target="_blank" rel="noreferrer noopener">{ name }</a>
|
||||
</div>
|
||||
<div className="amount">{ tx.amount } { symbol }</div>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<div className="pending-transactions">
|
||||
<h2>Pending transactions</h2>
|
||||
{ pendings }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PendingTransactions;
|
@ -4,6 +4,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import Select from 'react-select';
|
||||
import AdvancedForm from './AdvancedForm';
|
||||
import PendingTransactions from './PendingTransactions';
|
||||
import { FeeSelectValue, FeeSelectOption } from './FeeSelect';
|
||||
import { Notification } from '../../common/Notification';
|
||||
import AbstractAccount from '../account/AbstractAccount';
|
||||
@ -27,6 +28,7 @@ const _render = (props: any): any => {
|
||||
amount,
|
||||
setMax,
|
||||
coin,
|
||||
coinSymbol,
|
||||
token,
|
||||
feeLevels,
|
||||
fee,
|
||||
@ -38,7 +40,6 @@ const _render = (props: any): any => {
|
||||
infos,
|
||||
advanced,
|
||||
sending,
|
||||
sendingStatus
|
||||
} = props.sendForm;
|
||||
|
||||
const {
|
||||
@ -51,11 +52,14 @@ const _render = (props: any): any => {
|
||||
onSend,
|
||||
} = props.sendFormActions;
|
||||
|
||||
//const addressTokens = props.tokens.filter(t => t.ethAddress === currentAccount.address);
|
||||
const { config } = props.localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.network === coin);
|
||||
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
||||
|
||||
const tokens = addressTokens.map(t => {
|
||||
return { value: t.symbol, label: t.symbol };
|
||||
});
|
||||
tokens.unshift({ value: coin, label: coin.toUpperCase() });
|
||||
tokens.unshift({ value: selectedCoin.network, label: selectedCoin.symbol });
|
||||
|
||||
const setMaxClassName: string = setMax ? 'set-max enabled' : 'set-max';
|
||||
|
||||
@ -75,12 +79,12 @@ const _render = (props: any): any => {
|
||||
addressClassName = 'valid';
|
||||
}
|
||||
|
||||
let buttonDisabled: boolean = Object.keys(errors).length > 0 || total === '0' || address.length === 0 || sending;
|
||||
let buttonDisabled: boolean = Object.keys(errors).length > 0 || total === '0' || amount.length === 0 || address.length === 0 || sending;
|
||||
let buttonLabel: string = 'Send';
|
||||
if (coin !== token && amount.length > 0 && !errors.amount) {
|
||||
buttonLabel += ` ${amount} ${ token.toUpperCase() }`
|
||||
} else if (coin === token && total !== '0') {
|
||||
buttonLabel += ` ${total} ${ token.toUpperCase() }`;
|
||||
buttonLabel += ` ${total} ${ selectedCoin.symbol }`;
|
||||
}
|
||||
|
||||
//const device = props.devices.find(d => d.checksum === currentAccount.checksum);
|
||||
@ -90,13 +94,6 @@ const _render = (props: any): any => {
|
||||
}
|
||||
|
||||
let notification = null;
|
||||
// if (sendingStatus) {
|
||||
// if (sendingStatus.success) {
|
||||
// notification = (<Notification className="success" title="Transaction sent" message={ sendingStatus.message } />);
|
||||
// } else {
|
||||
// notification = (<Notification className="error" title="Transaction error" message={ sendingStatus.message } />);
|
||||
// }
|
||||
// }
|
||||
|
||||
return (
|
||||
<section className="send-form">
|
||||
@ -171,6 +168,8 @@ const _render = (props: any): any => {
|
||||
<AdvancedForm { ...props}>
|
||||
<button disabled={ buttonDisabled } onClick={ event => onSend() }>{ buttonLabel }</button>
|
||||
</AdvancedForm>
|
||||
|
||||
<PendingTransactions {...props} selectedCoin={selectedCoin} />
|
||||
|
||||
</section>
|
||||
);
|
||||
|
@ -31,42 +31,45 @@ const _render = (props: any): any => {
|
||||
<Notification className="info" title={ `Device ${ device.instanceLabel } is disconnected` } />
|
||||
) : null }
|
||||
|
||||
<h2 className={ props.summary.coin }>Address #{ parseInt(props.match.params.address) + 1 }</h2>
|
||||
<h2 className={ `summary-header ${props.summary.coin}` }>Address #{ parseInt(props.match.params.address) + 1 }</h2>
|
||||
|
||||
<SummaryDetails
|
||||
summary={ props.summary }
|
||||
balance={ account.balance }
|
||||
coin={ props.summary.coin }
|
||||
fiatRate={ props.fiatRate }
|
||||
fiat={ props.fiat }
|
||||
localStorage={ props.localStorage }
|
||||
onToggle={ props.summaryActions.onDetailsToggle } />
|
||||
|
||||
|
||||
<h2>Tokens</h2>
|
||||
{/* 0x58cda554935e4a1f2acbe15f8757400af275e084 */}
|
||||
<div className="filter">
|
||||
0x58cda554935e4a1f2acbe15f8757400af275e084
|
||||
<Async
|
||||
className="token-select"
|
||||
multi={ false }
|
||||
autoload={ false }
|
||||
|
||||
ignoreCase={ true }
|
||||
filterOptions= {
|
||||
(opt, str, values) => {
|
||||
console.log("TODO: filter already added", opt, str, values);
|
||||
return opt;
|
||||
(options, search, values) => {
|
||||
return options.filter(o => {
|
||||
return !tokens.find(t => t.symbol === o.symbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
value={ props.summary.selectedToken }
|
||||
onChange={ token => props.summaryActions.selectToken(token, account) }
|
||||
valueKey="symbol"
|
||||
labelKey="symbol"
|
||||
placeholder="Search for token"
|
||||
loadOptions={ props.summaryActions.loadTokens }
|
||||
searchPromptText="Type token name or address"
|
||||
noResultsText="Token not found"
|
||||
loadOptions={ input => props.summaryActions.loadTokens(input, account) }
|
||||
backspaceRemoves={true} />
|
||||
|
||||
</div>
|
||||
|
||||
<SummaryTokens tokens={ tokens } />
|
||||
<SummaryTokens tokens={ tokens } removeToken={ props.summaryActions.removeToken } />
|
||||
|
||||
</section>
|
||||
|
||||
|
@ -16,7 +16,8 @@ function mapStateToProps(state, own) {
|
||||
discovery: state.discovery,
|
||||
tokens: state.tokens,
|
||||
summary: state.summary,
|
||||
fiatRate: state.web3.fiatRate
|
||||
fiat: state.fiat,
|
||||
localStorage: state.localStorage
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,34 +2,60 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
const SummaryDetails = (props: any): any => {
|
||||
|
||||
if (!props.summary.details) {
|
||||
return (
|
||||
<div className="summary-details closed">
|
||||
<div className="toggle" onClick={ props.onToggle }></div>
|
||||
if (!props.summary.details) return (
|
||||
<div className="summary-details">
|
||||
<div className="toggle" onClick={ props.onToggle }></div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const { config } = props.localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.network === props.coin);
|
||||
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
||||
|
||||
let balanceColumn = null;
|
||||
let rateColumn = null;
|
||||
|
||||
if (fiatRate) {
|
||||
|
||||
const accountBalance = new BigNumber(props.balance);
|
||||
const fiatValue = new BigNumber(fiatRate.value);
|
||||
const fiat = accountBalance.times(fiatValue).toFixed(2);
|
||||
|
||||
balanceColumn = (
|
||||
<div className="column">
|
||||
<div className="label">Balance</div>
|
||||
<div className="fiat-value">${ fiat }</div>
|
||||
<div className="value">{ props.balance } { selectedCoin.symbol }</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
rateColumn = (
|
||||
<div className="column">
|
||||
<div className="label">Rate</div>
|
||||
<div className="fiat-value">${ fiatValue.toFixed(2) }</div>
|
||||
<div className="value">1.00 { selectedCoin.symbol }</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
balanceColumn = (
|
||||
<div className="column">
|
||||
<div className="label">Balance</div>
|
||||
<div className="fiat-value">{ props.balance } { selectedCoin.symbol }</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const fiatValue = "0";
|
||||
|
||||
return (
|
||||
<div className="summary-details">
|
||||
<div className="content">
|
||||
<div className="column">
|
||||
<div className="label">Balance</div>
|
||||
<div className="fiat-value">${ fiatValue }</div>
|
||||
<div className="value">{ props.balance } ETH</div>
|
||||
</div>
|
||||
<div className="column">
|
||||
<div className="label">Rate</div>
|
||||
<div className="fiat-value">${ props.fiatRate }</div>
|
||||
<div className="value">1.00 ETH</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="summary-details opened">
|
||||
<div className="toggle" onClick={ props.onToggle }></div>
|
||||
<div className="content">
|
||||
{ balanceColumn }
|
||||
{ rateColumn }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -13,10 +13,6 @@ const SummaryTokens = (props: any): any => {
|
||||
const textColor = new ColorHash();
|
||||
|
||||
const tokens = props.tokens.map((t, i) => {
|
||||
|
||||
// if (search.length > 0) {
|
||||
// if (t.name.toLowerCase().indexOf(search) < 0 && t.shortcut.toLowerCase().indexOf(search) < 0) return null;
|
||||
// }
|
||||
let iconColor = {
|
||||
color: textColor.hex(t.name),
|
||||
background: bgColor.hex(t.name),
|
||||
@ -30,7 +26,8 @@ const SummaryTokens = (props: any): any => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="name">{ t.name }</div>
|
||||
<div className="balance">{ t.balance }</div>
|
||||
<div className="balance">{ t.balance } { t.symbol }</div>
|
||||
<button className="transparent" onClick={ event => props.removeToken(t) }></button>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ function mapStateToProps(state, own) {
|
||||
accounts: state.accounts,
|
||||
router: state.router,
|
||||
deviceDropdownOpened: state.DOM.deviceDropdownOpened,
|
||||
fiatRate: state.web3.fiatRate,
|
||||
fiat: state.fiat,
|
||||
localStorage: state.localStorage,
|
||||
discovery: state.discovery
|
||||
};
|
||||
|
@ -13,6 +13,7 @@ import Footer from '../components/common/Footer';
|
||||
import AccountTabs from '../components/wallet/account/AccountTabs';
|
||||
|
||||
import * as TrezorConnectActions from '../actions/TrezorConnectActions';
|
||||
import * as LogActions from '../actions/LogActions';
|
||||
|
||||
const Article = (props) => {
|
||||
return (
|
||||
@ -20,8 +21,8 @@ const Article = (props) => {
|
||||
<nav>
|
||||
<Route path="/device/:device/coin/:coin/address/:address" component={ AccountTabs } />
|
||||
</nav>
|
||||
{/* <Log /> */}
|
||||
<Notifications />
|
||||
<Log />
|
||||
{ props.children }
|
||||
<Footer />
|
||||
</article>
|
||||
@ -30,13 +31,13 @@ const Article = (props) => {
|
||||
|
||||
function mapStateToProps(state, own) {
|
||||
return {
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import LandingPage from '../components/landing/LandingPage';
|
||||
import * as LogActions from '../actions/LogActions';
|
||||
|
||||
function mapStateToProps(state, own) {
|
||||
return {
|
||||
@ -19,6 +20,7 @@ function mapStateToProps(state, own) {
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,10 @@ function mapStateToProps(state, own) {
|
||||
accounts: state.accounts,
|
||||
discovery: state.discovery,
|
||||
tokens: state.tokens,
|
||||
pending: state.pending,
|
||||
sendForm: state.sendForm,
|
||||
fiatRate: state.web3.fiatRate
|
||||
fiat: state.fiat,
|
||||
localStorage: state.localStorage
|
||||
};
|
||||
}
|
||||
|
||||
|
8
src/js/flowtype/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
|
||||
export type Dispatch = (action: Action | ThunkAction | PromiseAction) => any;
|
||||
export type GetState = () => State;
|
||||
export type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
||||
export type PromiseAction = Promise<Action>;
|
@ -7,18 +7,18 @@ import store from './store';
|
||||
import router from './router';
|
||||
import { onResize, onBeforeUnload } from './actions/AppActions';
|
||||
|
||||
import Raven from 'raven-js';
|
||||
|
||||
import styles from '../styles/index.less';
|
||||
|
||||
|
||||
Raven.config('https://497392c3ff6e46dc9e54eef123979378@sentry.io/294339').install();
|
||||
|
||||
render(
|
||||
router,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// handle resize event and pass it to DOM reducer
|
||||
window.addEventListener('resize', () => {
|
||||
store.dispatch( onResize() );
|
||||
});
|
||||
|
||||
window.onbeforeunload = () => {
|
||||
store.dispatch( onBeforeUnload() );
|
||||
}
|
||||
|
37
src/js/reducers/FiatRateReducer.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export type Fiat = {
|
||||
+network: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const initialState: Array<Fiat> = [];
|
||||
|
||||
const update = (state: Array<Fiat>, action: any): Array<Fiat> => {
|
||||
const newState: Array<Fiat> = [ ...state ];
|
||||
const exists: ?Fiat = newState.find(f => f.network === action.network);
|
||||
if (exists) {
|
||||
exists.value = action.rate.price_usd;
|
||||
} else {
|
||||
newState.push({
|
||||
network: action.network,
|
||||
value: action.rate.price_usd
|
||||
})
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
|
||||
export default (state: Array<Fiat> = initialState, action: any): Array<Fiat> => {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case 'rate__update' :
|
||||
return update(state, action);
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
46
src/js/reducers/LogReducer.js
Normal file
@ -0,0 +1,46 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
type LogEntry = {
|
||||
time: number;
|
||||
type: string;
|
||||
messgage: string;
|
||||
}
|
||||
|
||||
export type State = {
|
||||
opened: boolean;
|
||||
entries: Array<LogEntry>;
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
opened: false,
|
||||
entries: [],
|
||||
};
|
||||
|
||||
|
||||
export default (state: State = initialState, action: any): State => {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case 'log__open':
|
||||
return {
|
||||
...state,
|
||||
opened: true
|
||||
}
|
||||
|
||||
case 'log__close':
|
||||
return {
|
||||
...state,
|
||||
opened: false
|
||||
}
|
||||
|
||||
case 'log__add':
|
||||
return {
|
||||
...state,
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
54
src/js/reducers/PendingTxReducer.js
Normal file
@ -0,0 +1,54 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import * as SEND from '../actions/constants/SendForm';
|
||||
import * as WEB3 from '../actions/constants/Web3';
|
||||
|
||||
export type PendingTx = {
|
||||
+id: string;
|
||||
+coin: string;
|
||||
+token: string;
|
||||
+amount: string;
|
||||
+address: string;
|
||||
}
|
||||
|
||||
const initialState: Array<PendingTx> = [];
|
||||
|
||||
const add = (state: Array<PendingTx>, action: any) => {
|
||||
const newState = [ ...state ];
|
||||
newState.push({
|
||||
id: action.txid,
|
||||
coin: action.address.coin,
|
||||
token: action.token,
|
||||
amount: action.amount,
|
||||
address: action.address.address,
|
||||
});
|
||||
return newState;
|
||||
}
|
||||
|
||||
const remove = (state: Array<PendingTx>, action: any) => {
|
||||
return state.filter(tx => tx.id !== action.tx.id);
|
||||
}
|
||||
|
||||
const fromStorage = (state: Array<PendingTx>, action: any) => {
|
||||
return state.filter(tx => tx.id !== action.tx.id);
|
||||
}
|
||||
|
||||
export default function pending(state: Array<PendingTx> = initialState, action: any): any {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case SEND.TX_COMPLETE :
|
||||
return add(state, action);
|
||||
|
||||
case WEB3.PENDING_TX_RESOLVED :
|
||||
return remove(state, action);
|
||||
|
||||
case 'PENDING.FROM_STORAGE' :
|
||||
return action.payload;
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
@ -13,6 +13,7 @@ export type State = {
|
||||
+checksum: ?string;
|
||||
+accountIndex: number;
|
||||
+coin: string;
|
||||
+coinSymbol: string;
|
||||
token: string;
|
||||
location: string;
|
||||
|
||||
@ -36,7 +37,6 @@ export type State = {
|
||||
nonce: string;
|
||||
total: string;
|
||||
sending: boolean;
|
||||
sendingStatus: ?SendStatus;
|
||||
errors: {[k: string]: string};
|
||||
warnings: {[k: string]: string};
|
||||
infos: {[k: string]: string};
|
||||
@ -48,15 +48,12 @@ export type FeeLevel = {
|
||||
value: string;
|
||||
}
|
||||
|
||||
type SendStatus = {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
checksum: null,
|
||||
accountIndex: 0,
|
||||
coin: '',
|
||||
coinSymbol: '',
|
||||
token: '',
|
||||
location: '',
|
||||
|
||||
@ -64,8 +61,8 @@ export const initialState: State = {
|
||||
untouched: true,
|
||||
touched: {},
|
||||
balanceNeedUpdate: false,
|
||||
//address: '',
|
||||
address: '0x574BbB36871bA6b78E27f4B4dCFb76eA0091880B',
|
||||
address: '',
|
||||
//address: '0x574BbB36871bA6b78E27f4B4dCFb76eA0091880B',
|
||||
amount: '',
|
||||
setMax: false,
|
||||
feeLevels: [],
|
||||
@ -78,7 +75,6 @@ export const initialState: State = {
|
||||
nonce: '0',
|
||||
total: '0',
|
||||
sending: false,
|
||||
sendingStatus: null,
|
||||
errors: {},
|
||||
warnings: {},
|
||||
infos: {},
|
||||
@ -166,26 +162,32 @@ export default (state: State = initialState, action: any): State => {
|
||||
return {
|
||||
...state,
|
||||
sending: true,
|
||||
sendingStatus: null,
|
||||
}
|
||||
|
||||
case SEND.TX_COMPLETE :
|
||||
return {
|
||||
...state,
|
||||
|
||||
sending: false,
|
||||
sendingStatus: {
|
||||
success: true,
|
||||
message: action.txid
|
||||
}
|
||||
touched: {},
|
||||
address: '',
|
||||
amount: '',
|
||||
setMax: false,
|
||||
gasPriceNeedsUpdate: false,
|
||||
gasLimit: state.gasLimit,
|
||||
gasPrice: state.recommendedGasPrice,
|
||||
data: '',
|
||||
nonce: '0',
|
||||
total: '0',
|
||||
errors: {},
|
||||
warnings: {},
|
||||
infos: {},
|
||||
|
||||
}
|
||||
case SEND.TX_ERROR :
|
||||
return {
|
||||
...state,
|
||||
sending: false,
|
||||
sendingStatus: {
|
||||
success: false,
|
||||
message: action.response
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,6 +47,12 @@ const forget = (state: Array<Token>, action: any): Array<Token> => {
|
||||
return state.filter(t => t.checksum !== action.device.checksum);
|
||||
}
|
||||
|
||||
const remove = (state: Array<Token>, action: any): Array<Token> => {
|
||||
return state.filter(t => {
|
||||
return !(t.ethAddress === action.token.ethAddress && t.address === action.token.address);
|
||||
});
|
||||
}
|
||||
|
||||
export default (state: Array<Token> = initialState, action: any): Array<Token> => {
|
||||
|
||||
switch (action.type) {
|
||||
@ -54,6 +60,9 @@ export default (state: Array<Token> = initialState, action: any): Array<Token> =
|
||||
case TOKEN.ADD :
|
||||
return create(state, action.payload);
|
||||
|
||||
case TOKEN.REMOVE :
|
||||
return remove(state, action);
|
||||
|
||||
case TOKEN.SET_BALANCE :
|
||||
return setBalance(state, action.payload);
|
||||
|
||||
|
@ -5,7 +5,6 @@ import { TRANSPORT, DEVICE } from 'trezor-connect';
|
||||
import * as CONNECT from '../actions/constants/TrezorConnect';
|
||||
|
||||
export type TrezorDevice = {
|
||||
initialized: boolean;
|
||||
remember: boolean;
|
||||
connected: boolean;
|
||||
path: string;
|
||||
@ -22,7 +21,7 @@ export type TrezorDevice = {
|
||||
}
|
||||
|
||||
export type SelectedDevice = {
|
||||
id: string;
|
||||
id: string; // could be device path if unacquired or features.device_id
|
||||
instance: ?number;
|
||||
}
|
||||
|
||||
@ -74,7 +73,6 @@ const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice =>
|
||||
// ...current,
|
||||
...upcoming,
|
||||
// make sure that instance specific variables will not be overridden
|
||||
initialized: current.initialized,
|
||||
connected: typeof upcoming.connected === 'boolean' ? upcoming.connected : current.connected,
|
||||
remember: typeof upcoming.remember === 'boolean' ? upcoming.remember : current.remember,
|
||||
instance: current.instance,
|
||||
@ -106,12 +104,11 @@ const addDevice = (state: State, device: Object): State => {
|
||||
let affectedDevices: Array<TrezorDevice> = [];
|
||||
let otherDevices: Array<TrezorDevice> = [];
|
||||
if (device.unacquired) {
|
||||
// connected device is unacquired, but it was already merged with saved devices
|
||||
// when DEVICE.CHANGE event occurs
|
||||
// ignore this event
|
||||
// check if connected device is unacquired, but it was already merged with saved device(s) after DEVICE.CHANGE action
|
||||
affectedDevices = newState.devices.filter(d => d.path === device.path);
|
||||
const diff = newState.devices.filter(d => affectedDevices.indexOf(d) === -1);
|
||||
|
||||
// if so, ignore this action
|
||||
if (affectedDevices.length > 0) {
|
||||
return state;
|
||||
}
|
||||
@ -129,13 +126,11 @@ const addDevice = (state: State, device: Object): State => {
|
||||
|
||||
const newDevice: TrezorDevice = {
|
||||
...device,
|
||||
initialized: false,
|
||||
acquiring: false,
|
||||
remember: false,
|
||||
connected: true,
|
||||
path: device.path,
|
||||
label: device.label,
|
||||
id: 'ABCD',
|
||||
checksum: null,
|
||||
// instance: 0,
|
||||
instanceLabel: device.label,
|
||||
@ -158,7 +153,6 @@ const setDeviceState = (state: State, action: any): State => {
|
||||
if (index > -1) {
|
||||
const changedDevice: TrezorDevice = {
|
||||
...newState.devices[index],
|
||||
initialized: true,
|
||||
checksum: action.checksum
|
||||
};
|
||||
newState.devices[index] = changedDevice;
|
||||
@ -251,7 +245,8 @@ const forgetDevice = (state: State, action: any): State => {
|
||||
newState.devices.splice(newState.devices.indexOf(action.device), 1);
|
||||
} else {
|
||||
// remove all instances after disconnect (remember request declined)
|
||||
newState.devices = state.devices.filter(d => d.path !== action.device.path);
|
||||
//newState.devices = state.devices.filter(d => d.path !== action.device.path);
|
||||
newState.devices = state.devices.filter(d => (d.features && d.features.device_id !== action.device.features.device_id) || (!d.features && d.path !== action.device.path));
|
||||
}
|
||||
|
||||
return newState;
|
||||
@ -277,13 +272,11 @@ const duplicate = (state: State, device: any): State => {
|
||||
// if (affectedDevices.length > 0) {
|
||||
const newDevice: TrezorDevice = {
|
||||
...device,
|
||||
initialized: false,
|
||||
checksum: null,
|
||||
remember: device.remember,
|
||||
connected: device.connected,
|
||||
path: device.path,
|
||||
label: device.label,
|
||||
id: 'ABCD',
|
||||
instance: new Date().getTime(),
|
||||
instanceLabel: device.instanceLabel,
|
||||
ts: 0,
|
||||
|
@ -5,6 +5,7 @@ import { combineReducers } from 'redux';
|
||||
import { routerReducer } from 'react-router-redux';
|
||||
|
||||
import DOM from './AppReducer.js';
|
||||
import log from './LogReducer.js';
|
||||
import localStorage from './LocalStorageReducer.js';
|
||||
import connect from './TrezorConnectReducer.js';
|
||||
import notifications from './NotificationReducer.js';
|
||||
@ -17,10 +18,13 @@ import receive from './ReceiveReducer.js';
|
||||
import summary from './SummaryReducer.js';
|
||||
import tokens from './TokensReducer.js';
|
||||
import discovery from './DiscoveryReducer.js';
|
||||
import pending from './PendingTxReducer.js';
|
||||
import fiat from './FiatRateReducer.js';
|
||||
|
||||
export default combineReducers({
|
||||
router: routerReducer,
|
||||
DOM,
|
||||
log,
|
||||
localStorage,
|
||||
connect,
|
||||
notifications,
|
||||
@ -32,5 +36,7 @@ export default combineReducers({
|
||||
receive,
|
||||
summary,
|
||||
tokens,
|
||||
discovery
|
||||
discovery,
|
||||
pending,
|
||||
fiat
|
||||
});
|
@ -7,13 +7,17 @@ import { resolveAfter } from '../utils/promiseUtils';
|
||||
|
||||
const loadRateAction = (): any => {
|
||||
return async (dispatch, getState) => {
|
||||
const config = getState().localStorage.config;
|
||||
try {
|
||||
const rate = await httpRequest('https://api.coinmarketcap.com/v1/ticker/ethereum/?convert=USD', 'json');
|
||||
|
||||
dispatch({
|
||||
type: 'rate__update',
|
||||
rate: rate[0]
|
||||
})
|
||||
for (let i = 0; i < config.fiatValueTickers.length; i++) {
|
||||
const rate = await httpRequest(`${config.fiatValueTickers[i].url}?convert=USD`, 'json');
|
||||
dispatch({
|
||||
type: 'rate__update',
|
||||
network: config.fiatValueTickers[i].network,
|
||||
rate: rate[0]
|
||||
});
|
||||
}
|
||||
|
||||
} catch(error) {
|
||||
|
||||
@ -29,11 +33,12 @@ const loadRateAction = (): any => {
|
||||
*/
|
||||
const LocalStorageService = (store: any) => (next: any) => (action: any) => {
|
||||
|
||||
if (action.type === LOCATION_CHANGE && !store.getState().router.location) {
|
||||
next(action);
|
||||
|
||||
//if (action.type === LOCATION_CHANGE && !store.getState().router.location) {
|
||||
if (action.type === 'storage__ready') {
|
||||
store.dispatch(loadRateAction());
|
||||
}
|
||||
|
||||
next(action);
|
||||
};
|
||||
|
||||
export default LocalStorageService;
|
@ -10,6 +10,8 @@ import * as MODAL from '../actions/constants/Modal';
|
||||
import * as TOKEN from '../actions/constants/Token';
|
||||
import * as ADDRESS from '../actions/constants/Address';
|
||||
import * as DISCOVERY from '../actions/constants/Discovery';
|
||||
import * as SEND from '../actions/constants/SendForm';
|
||||
import * as WEB3 from '../actions/constants/Web3';
|
||||
|
||||
|
||||
// https://github.com/STRML/react-localstorage/blob/master/react-localstorage.js
|
||||
@ -34,10 +36,17 @@ const findDiscovery = (devices, discovery) => {
|
||||
}, []);
|
||||
}
|
||||
|
||||
const findPendingTxs = (accounts, pending) => {
|
||||
return accounts.reduce((arr, account) => {
|
||||
return arr.concat(pending.filter(a => a.address === account.address));
|
||||
}, []);
|
||||
}
|
||||
|
||||
const save = (dispatch, getState) => {
|
||||
const devices = getState().connect.devices.filter(d => d.remember === true && !d.unacquired);
|
||||
const accounts = findAccounts(devices, getState().accounts);
|
||||
const tokens = findTokens(accounts, getState().tokens);
|
||||
const pending = findPendingTxs(accounts, getState().pending);
|
||||
const discovery = findDiscovery(devices, getState().discovery);
|
||||
|
||||
// save devices
|
||||
@ -51,6 +60,9 @@ const save = (dispatch, getState) => {
|
||||
|
||||
// tokens
|
||||
dispatch( LocalStorageActions.save('tokens', JSON.stringify( tokens ) ) );
|
||||
|
||||
// pending transactions
|
||||
dispatch( LocalStorageActions.save('pending', JSON.stringify( pending ) ) );
|
||||
}
|
||||
|
||||
|
||||
@ -74,6 +86,7 @@ const LocalStorageService = (store: any) => (next: any) => (action: any) => {
|
||||
break;
|
||||
|
||||
case TOKEN.ADD :
|
||||
case TOKEN.REMOVE :
|
||||
case TOKEN.SET_BALANCE :
|
||||
save(store.dispatch, store.getState);
|
||||
// store.dispatch( LocalStorageActions.save('tokens', JSON.stringify( tokens ) ) );
|
||||
@ -103,6 +116,11 @@ const LocalStorageService = (store: any) => (next: any) => (action: any) => {
|
||||
// store.dispatch( LocalStorageActions.save('selectedDevice', JSON.stringify( store.getState().connect.selectedDevice ) ) );
|
||||
break;
|
||||
|
||||
case SEND.TX_COMPLETE :
|
||||
case WEB3.PENDING_TX_RESOLVED :
|
||||
save(store.dispatch, store.getState);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ const validation = (store: any, params: UrlParams): boolean => {
|
||||
if (params.hasOwnProperty('device')) {
|
||||
const { devices } = store.getState().connect;
|
||||
|
||||
let device; // = devices.find(d => d.path === params.device || d.features.device_id === params.device);
|
||||
let device;
|
||||
if (params.hasOwnProperty('deviceInstance')) {
|
||||
device = devices.find(d => d.features && d.features.device_id === params.device && d.instance === params.deviceInstance );
|
||||
} else {
|
||||
@ -50,7 +50,7 @@ const validation = (store: any, params: UrlParams): boolean => {
|
||||
|
||||
if (params.hasOwnProperty('coin')) {
|
||||
const { config } = store.getState().localStorage;
|
||||
const coin = config.coins.find(c => c.symbol === params.coin);
|
||||
const coin = config.coins.find(c => c.network === params.coin);
|
||||
if (!coin) return false;
|
||||
if (!params.address) return false;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import * as ACTIONS from '../actions';
|
||||
const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
||||
|
||||
const prevState = store.getState().connect;
|
||||
const prevModalState = store.getState().connect;
|
||||
const prevModalState = store.getState().modal;
|
||||
|
||||
next(action);
|
||||
|
||||
@ -32,6 +32,22 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
||||
} else if (action.type === DEVICE.DISCONNECT) {
|
||||
store.dispatch( TrezorConnectActions.deviceDisconnect(action.device) );
|
||||
|
||||
} else if (action.type === CONNECT.REMEMBER_REQUEST) {
|
||||
// TODO:
|
||||
if (prevModalState.opened && prevModalState.windowType === CONNECT.REMEMBER_REQUEST) {
|
||||
|
||||
|
||||
store.dispatch({
|
||||
type: CONNECT.FORGET,
|
||||
device: store.getState().modal.device
|
||||
});
|
||||
|
||||
store.dispatch({
|
||||
type: CONNECT.FORGET,
|
||||
device: prevModalState.device
|
||||
});
|
||||
}
|
||||
|
||||
} else if (action.type === CONNECT.FORGET) {
|
||||
//store.dispatch( TrezorConnectActions.forgetDevice(action.device) );
|
||||
store.dispatch( TrezorConnectActions.switchToFirstAvailableDevice() );
|
||||
@ -62,6 +78,7 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
||||
|
||||
// interrupt process of remembering device (force forget)
|
||||
// TODO: the same for disconnect more than 1 device at once
|
||||
// TODO: move it to modal actions
|
||||
const { modal } = store.getState();
|
||||
if (modal.opened && modal.windowType === CONNECT.REMEMBER_REQUEST) {
|
||||
if (action.device.features && modal.device.features.device_id === action.device.features.device_id) {
|
||||
|
@ -12,6 +12,7 @@ import reducers from '../reducers';
|
||||
import services from '../services';
|
||||
import { Middleware } from 'redux';
|
||||
import { GenericStoreEnhancer } from 'redux';
|
||||
import RavenMiddleware from 'redux-raven-middleware';
|
||||
|
||||
export const history = createHistory( { queryKey: false } );
|
||||
|
||||
@ -19,6 +20,7 @@ const initialState: any = {};
|
||||
const enhancers = [];
|
||||
const middleware = [
|
||||
thunk,
|
||||
RavenMiddleware('https://497392c3ff6e46dc9e54eef123979378@sentry.io/294339'),
|
||||
routerMiddleware(history)
|
||||
];
|
||||
|
||||
|
137
src/solidity/rinkeby-token.js
Normal file
@ -0,0 +1,137 @@
|
||||
pragma solidity ^0.4.4;
|
||||
|
||||
contract Token {
|
||||
|
||||
/// @return total amount of tokens
|
||||
function totalSupply() constant returns (uint256 supply) {}
|
||||
|
||||
/// @param _owner The address from which the balance will be retrieved
|
||||
/// @return The balance
|
||||
function balanceOf(address _owner) constant returns (uint256 balance) {}
|
||||
|
||||
/// @notice send `_value` token to `_to` from `msg.sender`
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return Whether the transfer was successful or not
|
||||
function transfer(address _to, uint256 _value) returns (bool success) {}
|
||||
|
||||
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return Whether the transfer was successful or not
|
||||
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
|
||||
|
||||
/// @notice `msg.sender` approves `_addr` to spend `_value` tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @param _value The amount of wei to be approved for transfer
|
||||
/// @return Whether the approval was successful or not
|
||||
function approve(address _spender, uint256 _value) returns (bool success) {}
|
||||
|
||||
/// @param _owner The address of the account owning tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @return Amount of remaining tokens allowed to spent
|
||||
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
|
||||
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
contract StandardToken is Token {
|
||||
|
||||
function transfer(address _to, uint256 _value) returns (bool success) {
|
||||
//Default assumes totalSupply can't be over max (2^256 - 1).
|
||||
//If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
|
||||
//Replace the if with this one instead.
|
||||
//if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
|
||||
if (balances[msg.sender] >= _value && _value > 0) {
|
||||
balances[msg.sender] -= _value;
|
||||
balances[_to] += _value;
|
||||
Transfer(msg.sender, _to, _value);
|
||||
return true;
|
||||
} else { return false; }
|
||||
}
|
||||
|
||||
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
|
||||
//same as above. Replace this line with the following if you want to protect against wrapping uints.
|
||||
//if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
|
||||
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
Transfer(_from, _to, _value);
|
||||
return true;
|
||||
} else { return false; }
|
||||
}
|
||||
|
||||
function balanceOf(address _owner) constant returns (uint256 balance) {
|
||||
return balances[_owner];
|
||||
}
|
||||
|
||||
function approve(address _spender, uint256 _value) returns (bool success) {
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
Approval(msg.sender, _spender, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
|
||||
mapping (address => uint256) balances;
|
||||
mapping (address => mapping (address => uint256)) allowed;
|
||||
uint256 public totalSupply;
|
||||
}
|
||||
|
||||
|
||||
//name this contract whatever you'd like
|
||||
contract DariaCoin is StandardToken {
|
||||
|
||||
function () {
|
||||
//if ether is sent to this address, send it back.
|
||||
throw;
|
||||
}
|
||||
|
||||
/* Public variables of the token */
|
||||
|
||||
/*
|
||||
NOTE:
|
||||
The following variables are OPTIONAL vanities. One does not have to include them.
|
||||
They allow one to customise the token contract & in no way influences the core functionality.
|
||||
Some wallets/interfaces might not even bother to look at this information.
|
||||
*/
|
||||
string public name; //fancy name: eg Simon Bucks
|
||||
uint8 public decimals; //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.
|
||||
string public symbol; //An identifier: eg SBX
|
||||
string public version = 'H1.0'; //human 0.1 standard. Just an arbitrary versioning scheme.
|
||||
|
||||
//
|
||||
// CHANGE THESE VALUES FOR YOUR TOKEN
|
||||
//
|
||||
|
||||
//make sure this function name matches the contract name above. So if you're token is called TutorialToken, make sure the //contract name above is also TutorialToken instead of ERC20Token
|
||||
|
||||
function DariaCoin(
|
||||
) {
|
||||
balances[msg.sender] = 666; // Give the creator all initial tokens (100000 for example)
|
||||
totalSupply = 666; // Update total supply (100000 for example)
|
||||
name = "Daria Coin :)"; // Set the name for display purposes
|
||||
decimals = 2; // Amount of decimals for display purposes
|
||||
symbol = "DC!"; // Set the symbol for display purposes
|
||||
}
|
||||
|
||||
/* Approves and then calls the receiving contract */
|
||||
function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
Approval(msg.sender, _spender, _value);
|
||||
|
||||
//call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
|
||||
//receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
|
||||
//it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.
|
||||
if(!_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) { throw; }
|
||||
return true;
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ aside {
|
||||
width: 320px;
|
||||
height: 64px;
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.04);
|
||||
background: @color_white;
|
||||
|
||||
.Select-control {
|
||||
height: 63px;
|
||||
@ -43,9 +44,9 @@ aside {
|
||||
|
||||
.Select-arrow {
|
||||
visibility: hidden;
|
||||
&:after {
|
||||
content: ''
|
||||
}
|
||||
// &:after {
|
||||
// content: ''
|
||||
// }
|
||||
}
|
||||
|
||||
.device {
|
||||
@ -197,10 +198,10 @@ aside {
|
||||
color: @color_text_primary;
|
||||
height: 50px;
|
||||
|
||||
.hover();
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: @color_gray_light;
|
||||
background-color: @color_gray_light;
|
||||
}
|
||||
|
||||
&.account {
|
||||
@ -216,21 +217,49 @@ aside {
|
||||
color: @color_text_secondary;
|
||||
}
|
||||
|
||||
// &:last-child {
|
||||
// border-bottom: 1px solid @color_divider;
|
||||
// }
|
||||
}
|
||||
&:before {
|
||||
content: '';
|
||||
width: 0px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: @color_green_primary;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: @color_white;
|
||||
border-left: 3px solid @color_green_primary;
|
||||
padding-left: 27px;
|
||||
|
||||
&:hover {
|
||||
&.selected {
|
||||
background: @color_white;
|
||||
//border-left: 3px solid @color_green_primary;
|
||||
//border-bottom: 1px solid @color_divider;
|
||||
//padding-left: 27px;
|
||||
|
||||
&:before {
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: @color_white;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
// border-bottom: 1px solid @color_divider;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
line-height: 1px;
|
||||
background-color: @color_divider;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
&.coin {
|
||||
padding-left: 80px;
|
||||
&:before {
|
||||
@ -303,15 +332,16 @@ aside {
|
||||
}
|
||||
}
|
||||
|
||||
&.ropsten:before,
|
||||
&.eth:before {
|
||||
background-image: url('../images/eth-logo.png');
|
||||
background-size: auto 20px;
|
||||
}
|
||||
&.rinkeby:before,
|
||||
&.etc:before {
|
||||
background-image: url('../images/etc-logo.png');
|
||||
background-size: auto 20px;
|
||||
}
|
||||
|
||||
&.btc:before {
|
||||
background-image: url('../images/btc-logo.png');
|
||||
}
|
||||
@ -330,8 +360,6 @@ aside {
|
||||
&.zec:before {
|
||||
background-image: url('../images/zec-logo.png');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.coin-divider {
|
||||
@ -387,7 +415,7 @@ aside {
|
||||
|
||||
.add-address {
|
||||
position: relative;
|
||||
padding: 4px 0 4px 20px;
|
||||
padding: 8px 0 8px 20px;
|
||||
cursor: pointer;
|
||||
color: @color_text_secondary;
|
||||
display: flex;
|
||||
@ -425,11 +453,12 @@ aside {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
padding: 16px 0 16px 30px;
|
||||
padding: 8px 0 8px 22px;
|
||||
white-space: nowrap;
|
||||
border-top: 1px solid @color_divider;
|
||||
color: @color_text_secondary;
|
||||
//border-top: 1px solid @color_divider;
|
||||
.loader-circle {
|
||||
margin-right: 12px;
|
||||
margin-right: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ html, body {
|
||||
position: relative;
|
||||
background-color: @color_body;
|
||||
font-family: @font-default;
|
||||
font-weight: 300;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,15 @@
|
||||
@color_white: #ffffff;
|
||||
|
||||
@color_header: #212121;
|
||||
@color_body: #EBEBEB;
|
||||
@color_body: #E3E3E3;
|
||||
@color_main: #FBFBFB;
|
||||
@color_landing: #F9F9F9;
|
||||
|
||||
/// new!!!
|
||||
|
||||
@color_text_primary: #505050;
|
||||
@color_text_secondary: #A9A9A9;
|
||||
@color_text_primary: #494949;
|
||||
@color_text_secondary: #757575;
|
||||
|
||||
@color_gray_light: #F2F2F2; // hover menu
|
||||
@color_divider: #EBEBEB;
|
||||
@color_divider: #E3E3E3; //#EBEBEB;
|
||||
|
||||
@color_green_primary: #01B757;
|
||||
@color_green_secondary: #00AB51;
|
||||
|
@ -12,11 +12,12 @@ article {
|
||||
position: relative;
|
||||
|
||||
.account-tabs {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0px 48px;
|
||||
padding: 0px 28px; // 20px padding arround links
|
||||
max-width: 600px;
|
||||
|
||||
a {
|
||||
@ -24,6 +25,9 @@ article {
|
||||
font-size: 14px;
|
||||
color: @color_text_secondary;
|
||||
margin: 0px 4px;
|
||||
padding: 20px;
|
||||
.hover();
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
color: @color_text_primary;
|
||||
@ -37,6 +41,16 @@ article {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator {
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
width: 100px;
|
||||
height: 2px;
|
||||
background: @color_green_primary;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +62,7 @@ article {
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
padding: 24px 48px;
|
||||
}
|
||||
|
||||
|
@ -19,15 +19,6 @@
|
||||
url('../fonts/roboto/roboto-mono-v4-greek_cyrillic-ext_greek-ext_latin_cyrillic_vietnamese_latin-ext-regular.svg#RobotoMono') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'glyphicons';
|
||||
src: url('../fonts/glyphicons.eot') format('embedded-opentype'),
|
||||
url('../fonts/glyphicons.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/glyphicons.woff') format('woff'),
|
||||
url('../fonts/glyphicons.ttf') format('truetype'),
|
||||
url('../fonts/glyphicons.svg#icomoon') format('svg');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'icomoon';
|
||||
src: url('../fonts/icomoon.eot') format('embedded-opentype'),
|
||||
@ -37,11 +28,6 @@
|
||||
url('../fonts/icomoon.svg#icomoon') format('svg');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../fonts/pass.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-default: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
|
||||
@font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
|
||||
@font-family-monospace: "Roboto Mono", Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
@ -52,74 +38,6 @@
|
||||
// background: @color_info_secondary;
|
||||
// }
|
||||
|
||||
.glyphicon-base() {
|
||||
display: inline-block;
|
||||
font-family: 'glyphicons';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.glyphicon-trezor {
|
||||
.glyphicon-base();
|
||||
content: "\5f";
|
||||
padding-top: 1px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.glyphicon-info {
|
||||
.glyphicon-base();
|
||||
content: "\ea0c";
|
||||
}
|
||||
|
||||
.glyphicon-warning {
|
||||
.glyphicon-base();
|
||||
content: "\ea07";
|
||||
}
|
||||
|
||||
.glyphicon-cross {
|
||||
.glyphicon-base();
|
||||
content: "\ea0f";
|
||||
}
|
||||
|
||||
.glyphicon-checkmark {
|
||||
.glyphicon-base();
|
||||
content: "\ea10";
|
||||
}
|
||||
|
||||
.glyphicon-up {
|
||||
.glyphicon-base();
|
||||
content: "\e113";
|
||||
}
|
||||
|
||||
.glyphicon-down {
|
||||
.glyphicon-base();
|
||||
content: "\e114";
|
||||
}
|
||||
|
||||
.glyphicon-eye-open {
|
||||
.glyphicon-base();
|
||||
content: "\e105";
|
||||
}
|
||||
|
||||
.glyphicon-settings {
|
||||
.glyphicon-base();
|
||||
content: "\e019";
|
||||
}
|
||||
|
||||
.glyphicon-refresh {
|
||||
.glyphicon-base();
|
||||
content: "\e031";
|
||||
}
|
||||
|
||||
.glyphicon-plus {
|
||||
.glyphicon-base();
|
||||
content: "\2b";
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
|
||||
.icomoon-base() {
|
||||
display: inline-block;
|
||||
font-family: 'icomoon';
|
||||
@ -140,16 +58,16 @@
|
||||
content: "\e902";
|
||||
}
|
||||
|
||||
.icomoon-info {
|
||||
.icomoon-base();
|
||||
content: "\e904";
|
||||
}
|
||||
|
||||
.icomoon-refresh {
|
||||
.icomoon-base();
|
||||
content: "\e903";
|
||||
}
|
||||
|
||||
.icomoon-info {
|
||||
.icomoon-base();
|
||||
content: "\e904";
|
||||
}
|
||||
|
||||
.icomoon-chat {
|
||||
.icomoon-base();
|
||||
content: "\e905";
|
||||
@ -175,37 +93,27 @@
|
||||
content: "\e909";
|
||||
}
|
||||
|
||||
.icomoon-eye-error {
|
||||
.icomoon-base();
|
||||
content: "\e912";
|
||||
}
|
||||
|
||||
.icomoon-T1 {
|
||||
.icomoon-base();
|
||||
content: "\e913";
|
||||
}
|
||||
|
||||
.icomoon-close {
|
||||
.icomoon-base();
|
||||
content: "\e90a";
|
||||
}
|
||||
|
||||
.icomoon-arrow-left {
|
||||
.icomoon-arrow-up {
|
||||
.icomoon-base();
|
||||
content: "\e90b";
|
||||
}
|
||||
|
||||
.icomoon-arrow-up {
|
||||
.icomoon-arrow-right2 {
|
||||
.icomoon-base();
|
||||
content: "\e90c";
|
||||
}
|
||||
|
||||
.icomoon-arrow-right {
|
||||
.icomoon-plus {
|
||||
.icomoon-base();
|
||||
content: "\e90d";
|
||||
}
|
||||
|
||||
.icomoon-plus {
|
||||
.icomoon-arrow-right {
|
||||
.icomoon-base();
|
||||
content: "\e90e";
|
||||
}
|
||||
@ -216,6 +124,24 @@
|
||||
}
|
||||
|
||||
|
||||
.icomoon-eye-error {
|
||||
.icomoon-base();
|
||||
content: "\e911";
|
||||
}
|
||||
|
||||
.icomoon-T1 {
|
||||
.icomoon-base();
|
||||
content: "\e912";
|
||||
}
|
||||
|
||||
|
||||
|
||||
.icomoon-arrow-left {
|
||||
.icomoon-base();
|
||||
content: "\e91a";
|
||||
}
|
||||
|
||||
|
||||
.icomoon-setmax {
|
||||
.icomoon-base();
|
||||
content: "\e91b";
|
||||
@ -235,3 +161,8 @@
|
||||
.icomoon-base();
|
||||
content: "\e91e";
|
||||
}
|
||||
|
||||
.icomoon-back {
|
||||
.icomoon-base();
|
||||
content: "\e91f";
|
||||
}
|
||||
|
@ -7,21 +7,31 @@ header {
|
||||
fill: @color_white;
|
||||
height: 28px;
|
||||
width: 100px;
|
||||
margin-top: 9px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 16px;
|
||||
margin-left: 20px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.layout-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 1170px;
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
padding: 0 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color: @color_white;
|
||||
margin-left: 24px;
|
||||
.hover();
|
||||
|
||||
&:first-child {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active {
|
||||
color: @color_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,3 +26,4 @@
|
||||
|
||||
@import './inputs.less';
|
||||
@import './loader.less';
|
||||
@import './log.less';
|
||||
|
@ -32,7 +32,7 @@ input {
|
||||
&.warning {
|
||||
border-color: @color_warning_primary;
|
||||
&:focus {
|
||||
box-shadow: 0 1px 4px 0 rgba(1, 183, 87, 0.25);
|
||||
box-shadow: 0 1px 4px 0 rgba(235, 138, 0, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,6 +221,4 @@ a.green:visited {
|
||||
border-color: @color_white;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
text-align: center;
|
||||
padding-top: 65px;
|
||||
margin-top: 0px;
|
||||
background: @color_landing;
|
||||
|
||||
h2.claim {
|
||||
font-size: 36px;
|
||||
@ -67,6 +68,7 @@
|
||||
}
|
||||
|
||||
.image {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: calc(100vh - 143px);
|
||||
min-height: 500px;
|
||||
@ -75,6 +77,13 @@
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 0px;
|
||||
background-size: contain;
|
||||
p {
|
||||
position: absolute;
|
||||
bottom: 32px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0px auto;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
|
50
src/styles/log.less
Normal file
@ -0,0 +1,50 @@
|
||||
.log {
|
||||
position: relative;
|
||||
color: @color_info_primary;
|
||||
background: @color_info_secondary;
|
||||
padding: 24px 48px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
|
||||
.log-close {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 0;
|
||||
padding: 12px;
|
||||
color: inherit;
|
||||
transition: opacity 0.3s;
|
||||
|
||||
&:after {
|
||||
.icomoon-close;
|
||||
}
|
||||
&:active,
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0px;
|
||||
margin: 2px 0px;
|
||||
font-size: 12px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
min-height: 200px;
|
||||
resize: vertical;
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
border-radius: 4px;
|
||||
background-color: @color_white;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
// overflow: hidden;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@ -157,6 +157,8 @@
|
||||
height: 80px;
|
||||
margin-top: 15px;
|
||||
margin-left: 10px;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
color: @color_text_primary;
|
||||
border: 1px solid @color_divider;
|
||||
background: @color_white;
|
||||
@ -186,10 +188,10 @@
|
||||
input {
|
||||
letter-spacing: 6px;
|
||||
line-height: 48px;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
height: auto;
|
||||
padding: 0px 34px;
|
||||
padding: 0px 31px;
|
||||
color: @color_text_primary;
|
||||
background: transparent;
|
||||
}
|
||||
@ -202,7 +204,7 @@
|
||||
margin: auto 0;
|
||||
padding: 0;
|
||||
&:after {
|
||||
.icomoon-arrow-left;
|
||||
.icomoon-back;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
p {
|
||||
padding: 0px;
|
||||
margin-bottom: 8px 0px;
|
||||
margin: 8px 0px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.aside-tooltip-wrapper {
|
||||
width: 260px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.rc-tooltip {
|
||||
position: absolute;
|
||||
z-index: 1070;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// https://github.com/JedWatson/react-select/blob/master/less/select.less
|
||||
|
||||
@import '~react-select/less/select';
|
||||
@import '~react-select/less/select.less';
|
||||
|
||||
// override predefined colors
|
||||
@select-primary-color: @color_white;
|
||||
@ -10,6 +10,8 @@
|
||||
@select-item-border-radius: 0px;
|
||||
@select-input-border-color: transparent;
|
||||
@select-input-border-focus: @color_divider;
|
||||
// @select-input-bg: transparent;
|
||||
// @select-input-bg-focus: transparent;
|
||||
|
||||
.Select-focus-state(@color) {
|
||||
// do nothing
|
||||
@ -67,7 +69,13 @@
|
||||
}
|
||||
|
||||
.Select-noresults {
|
||||
|
||||
color: @color_text_secondary;
|
||||
font-family: @font-default;
|
||||
}
|
||||
|
||||
.Select-placeholder {
|
||||
color: @color_text_secondary;
|
||||
font-family: @font-default;
|
||||
}
|
||||
|
||||
.Select-value-label {
|
||||
@ -90,240 +98,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*@select-input-height: 34px;
|
||||
@select-primary-color: #fff;
|
||||
@select-input-bg-focus: #ff0000;
|
||||
@select-input-border-radius: 0px;
|
||||
@select-input-border-focus: @select-input-border-color;
|
||||
|
||||
.Select {
|
||||
width: 240px;
|
||||
height: 34px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
&.is-focused:not(.is-open) > .Select-control {
|
||||
border-color: @select-input-border-color;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.Select-control {
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.Select-menu-outer {
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
}
|
||||
|
||||
.Select-option {
|
||||
&:last-child {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.fee-label {
|
||||
display: inline-block;
|
||||
width: 70%;
|
||||
}
|
||||
.fee-size {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.CurrencySelect {
|
||||
width: 70px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
|
||||
.CoinSelect {
|
||||
width: 290px;
|
||||
height: 64px;
|
||||
.Select-control {
|
||||
height: 63px;
|
||||
border: 0px;
|
||||
border-radius: 4px 0px 0px 0px;
|
||||
border-right: 1px solid @color_divider;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
||||
.Select-input {
|
||||
background: transparent;
|
||||
//display: none !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #F2F2F2;
|
||||
.Select-arrow {
|
||||
&:after {
|
||||
color: #494949;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Select-value {
|
||||
padding: 0px;
|
||||
.Select-value-label {
|
||||
display: inline-block;
|
||||
height: 63px;
|
||||
padding-top: 20px;
|
||||
padding-left: 50px;
|
||||
font-size: 1.15em;
|
||||
font-weight: bold;
|
||||
line-height: 26px;
|
||||
color: #494949;
|
||||
|
||||
}
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
z-index: 2;
|
||||
left: 20px;
|
||||
top: 21px;
|
||||
|
||||
|
||||
background-image: url(../images/eth-logo.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: auto 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.Select-menu-outer {
|
||||
position: relative;
|
||||
top: 0;
|
||||
border: 0px;
|
||||
border-top: 1px solid rgba(218, 218, 218, 0.5);
|
||||
border-right: 1px solid rgba(218, 218, 218, 0.5);
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.04);
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.Select-menu {
|
||||
max-height: none;
|
||||
overflow-x: none;
|
||||
}
|
||||
|
||||
.Select-option {
|
||||
width: 290px;
|
||||
height: 64px;
|
||||
padding-top: 20px;
|
||||
padding-left: 60px;
|
||||
position: relative;
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
||||
span {
|
||||
height: 63px;
|
||||
font-size: 1.15em;
|
||||
font-weight: bold;
|
||||
line-height: 26px;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
z-index: 2;
|
||||
left: 20px;
|
||||
top: 21px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
|
||||
&.btc:before {
|
||||
background-image: url('../images/btc-logo.png');
|
||||
}
|
||||
&.ltc:before {
|
||||
background-image: url('../images/ltc-logo.png');
|
||||
}
|
||||
&.btg:before {
|
||||
background-image: url('../images/btg-logo.png');
|
||||
}
|
||||
&.bch:before {
|
||||
background-image: url('../images/bch-logo.png');
|
||||
}
|
||||
&.dash:before {
|
||||
background-image: url('../images/dash-logo.png');
|
||||
}
|
||||
&.zec:before {
|
||||
background-image: url('../images/zec-logo.png');
|
||||
}
|
||||
&.eth:before {
|
||||
background-image: url('../images/eth-logo.png');
|
||||
background-size: auto 20px;
|
||||
}
|
||||
&.etc:before {
|
||||
background-image: url('../images/etc-logo.png');
|
||||
background-size: auto 20px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #F2F2F2;
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
background: yellow;
|
||||
}
|
||||
}
|
||||
|
||||
.Select-arrow-zone {
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
.Select-arrow {
|
||||
border: 0px;
|
||||
width: 28px;
|
||||
|
||||
&:after {
|
||||
.glyphicon-down;
|
||||
color: #B3B3B3;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: -8px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-open {
|
||||
.Select-arrow {
|
||||
top: 0px;
|
||||
&:after {
|
||||
.glyphicon-up;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// /*
|
||||
//
|
||||
//
|
||||
//
|
||||
// */
|
@ -1,5 +1,4 @@
|
||||
.send-form {
|
||||
padding-bottom: 24px;
|
||||
|
||||
.Select {
|
||||
width: 98px;
|
||||
@ -27,6 +26,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
.Select-control {
|
||||
cursor: default;
|
||||
}
|
||||
.Select-arrow {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.fee-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -53,7 +61,7 @@
|
||||
padding-bottom: 24px;
|
||||
|
||||
.error,
|
||||
.warning,
|
||||
.warning:not(input),
|
||||
.info {
|
||||
position: absolute;
|
||||
left: 48px;
|
||||
@ -65,7 +73,7 @@
|
||||
.error {
|
||||
color: @color_error_primary;
|
||||
}
|
||||
.warning {
|
||||
.warning:not(input) {
|
||||
color: @color_warning_primary;
|
||||
}
|
||||
.info {
|
||||
@ -184,6 +192,8 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0px 48px;
|
||||
|
||||
padding-bottom: 24px;
|
||||
button {
|
||||
width: 50%;
|
||||
}
|
||||
@ -283,4 +293,58 @@
|
||||
resize: none;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
|
||||
.pending-transactions {
|
||||
|
||||
border-top: 1px solid @color_divider;
|
||||
|
||||
.tx {
|
||||
border-bottom: 1px solid @color_divider;
|
||||
padding: 14px 48px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
//border: 8px solid white;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
line-height: 30px;
|
||||
text-transform: uppercase;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
padding: 6px;
|
||||
p {
|
||||
line-height: 24px;
|
||||
padding: 0px;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
|
||||
a, a:visited {
|
||||
color: @color_text_secondary;
|
||||
.hover();
|
||||
|
||||
&:hover, &:active {
|
||||
color: @color_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.balance {
|
||||
color: @color_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,27 @@
|
||||
.summary {
|
||||
|
||||
h2 {
|
||||
//padding: 35px 50px 0px 50px;
|
||||
color: red;
|
||||
.summary-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 32px;
|
||||
height: 22px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
|
||||
&.ropsten:before,
|
||||
&.eth:before {
|
||||
background-image: url('../images/eth-logo.png');
|
||||
background-size: auto 20px;
|
||||
}
|
||||
&.rinkeby:before,
|
||||
&.etc:before {
|
||||
background-image: url('../images/etc-logo.png');
|
||||
background-size: auto 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.token-select {
|
||||
@ -36,25 +55,26 @@
|
||||
|
||||
.summary-details {
|
||||
position: relative;
|
||||
padding: 35px 50px 0px 50px;
|
||||
padding: 0px 48px;
|
||||
border-bottom: 1px solid @color_divider;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
padding-bottom: 32px;
|
||||
|
||||
.column {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
padding-bottom: 30px;
|
||||
margin-right: 48px;
|
||||
|
||||
.label {
|
||||
color: #A9A9A9;
|
||||
font-weight: 600;
|
||||
.label, .value {
|
||||
color: @color_text_secondary;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.fiat-value {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
margin: 7px 0 6px 0;
|
||||
color: #494949;
|
||||
color: @color_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,45 +89,38 @@
|
||||
height: 40px;
|
||||
//line-height: 30px;
|
||||
background: @color_white;
|
||||
color: #B3B3B3;
|
||||
color: @color_text_secondary;
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.04);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease-in-out;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: #F2F2F2;
|
||||
&:before {
|
||||
color: #494949;
|
||||
}
|
||||
background: @color_divider;
|
||||
color: @color_text_primary;
|
||||
}
|
||||
|
||||
&:before {
|
||||
.glyphicon-up;
|
||||
color: #B3B3B3;
|
||||
.icomoon-arrow-down;
|
||||
transition: transform 0.3s;
|
||||
transform-origin: 50% 50%;
|
||||
position: absolute;
|
||||
left: 14px;
|
||||
top: 16px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
left: 8px;
|
||||
top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.closed {
|
||||
.content {
|
||||
display: none;
|
||||
}
|
||||
.toggle {
|
||||
&:before {
|
||||
.glyphicon-down;
|
||||
top: 18px;
|
||||
}
|
||||
&.opened {
|
||||
.toggle:before {
|
||||
transform: rotate(180deg);
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter {
|
||||
background: @color_main;
|
||||
padding: 30px 48px 10px 48px;
|
||||
//background: @color_main;
|
||||
padding: 0px 48px 32px 48px;
|
||||
// text-align: right;
|
||||
|
||||
// input {
|
||||
@ -115,78 +128,30 @@
|
||||
// }
|
||||
}
|
||||
|
||||
.add-token-form {
|
||||
position: relative;
|
||||
.toggle {
|
||||
cursor: pointer;
|
||||
padding: 15px 50px;
|
||||
.token-select {
|
||||
.Select-control {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 15px 50px;
|
||||
}
|
||||
|
||||
|
||||
.column {
|
||||
padding-right: 10px;
|
||||
label {
|
||||
display: block;
|
||||
color: #A9A9A9;
|
||||
font-weight: 600;
|
||||
.Select-option {
|
||||
.hover();
|
||||
&.is-focused {
|
||||
background: @color_gray_light;
|
||||
}
|
||||
|
||||
input {
|
||||
&.token-address {
|
||||
width: 230px;
|
||||
}
|
||||
|
||||
&.token-name {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
&.token-shortcut {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
&.token-decimal {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
.glyphicon-up;
|
||||
color: #B3B3B3;
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 21px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:after {
|
||||
color: #494949;
|
||||
}
|
||||
}
|
||||
|
||||
&.closed {
|
||||
&:after {
|
||||
.glyphicon-down;
|
||||
|
||||
&.is-selected {
|
||||
background: @color_divider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.token {
|
||||
border-top: 1px solid @color_divider;
|
||||
padding: 15px 50px;
|
||||
padding: 14px 48px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.icon {
|
||||
width: 36px;
|
||||
@ -208,24 +173,27 @@
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
line-height: 30px;
|
||||
color: @color_text_secondary;
|
||||
}
|
||||
|
||||
.balance {
|
||||
color: red;
|
||||
line-height: 30px;
|
||||
button {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
padding: 0px;
|
||||
padding-top: 3px;
|
||||
&:after {
|
||||
.icomoon-close;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
&:last-child {
|
||||
// border-bottom: 1px solid @color_divider;
|
||||
}
|
||||
}
|
||||
|
||||
.token-select {
|
||||
.Select-control {
|
||||
cursor: text;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { TREZOR_CONNECT_FILES, SRC, PORT } from './constants';
|
||||
import { TREZOR_CONNECT_FILES, TREZOR_CONNECT_HTML, SRC, PORT } from './constants';
|
||||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
@ -88,10 +88,10 @@ module.exports = {
|
||||
inject: true
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
{ from: `${TREZOR_CONNECT_FILES}coins.json` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}releases.json` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}latest.txt` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}config_signed.bin` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}coins.json`, to: './data/coins.json' },
|
||||
{ from: `${TREZOR_CONNECT_FILES}releases-1.json`, to: './data/releases-1.json' },
|
||||
{ from: `${TREZOR_CONNECT_FILES}latest.txt`, to: './data/latest.txt' },
|
||||
{ from: `${TREZOR_CONNECT_FILES}config_signed.bin`, to: './data/config_signed.bin' },
|
||||
// { from: `${SRC}images/favicon.png` },
|
||||
// { from: `${SRC}images` },
|
||||
]),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { SRC, BUILD, TREZOR_LIBRARY, TREZOR_CONNECT_FILES } from './constants';
|
||||
import { SRC, BUILD, TREZOR_LIBRARY, TREZOR_CONNECT_FILES, TREZOR_CONNECT_HTML } from './constants';
|
||||
import webpack from 'webpack';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import ExtractTextPlugin from 'extract-text-webpack-plugin';
|
||||
@ -12,7 +12,7 @@ const extractLess = new ExtractTextPlugin({
|
||||
module.exports = {
|
||||
entry: {
|
||||
index: ['whatwg-fetch', `${SRC}js/index.js`],
|
||||
'trezor-library': `${TREZOR_LIBRARY}.js`
|
||||
//'trezor-library': `${TREZOR_LIBRARY}.js`
|
||||
},
|
||||
output: {
|
||||
filename: 'js/[name].[hash].js',
|
||||
@ -47,17 +47,26 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.(png|gif|jpg)$/,
|
||||
loader: 'file-loader?name=../images/[name].[ext]'
|
||||
loader: 'file-loader',
|
||||
query: {
|
||||
publicPath: '../',
|
||||
name: 'images/[name].[hash].[ext]',
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|svg|woff|woff2)$/,
|
||||
loader: 'file-loader?publicPath=../&name=fonts/[name].[ext]',
|
||||
// loader: 'file-loader?publicPath=../&name=fonts/[name].[hash].[ext]',
|
||||
loader: 'file-loader',
|
||||
query: {
|
||||
publicPath: '../',
|
||||
name: 'fonts/[name].[hash].[ext]',
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(wasm)$/,
|
||||
loader: 'file-loader',
|
||||
query: {
|
||||
name: 'js/[name].[ext]',
|
||||
name: 'js/[name].[hash].[ext]',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -88,8 +97,11 @@ module.exports = {
|
||||
//{from: `${SRC}/app/robots.txt`},
|
||||
//{ from: `${SRC}js/vendor`, to: `${BUILD}js/vendor` },
|
||||
//{ from: `${SRC}config.json` },
|
||||
{ from: `${SRC}images`, to: `${BUILD}images` },
|
||||
{ from: `${SRC}data`, to: `${BUILD}data` },
|
||||
//{ from: `${SRC}images/favicon.png`, to: `${BUILD}favicon.png` },
|
||||
{ from: `${SRC}images/favicon.ico`, to: `${BUILD}favicon.ico` },
|
||||
{ from: `${SRC}images/favicon.png`, to: `${BUILD}favicon.png` },
|
||||
{ from: `${SRC}images/dashboard.png`, to: `${BUILD}images/dashboard.png` },
|
||||
{ from: `${SRC}data`, to: `${BUILD}data`, cache: false },
|
||||
]),
|
||||
new webpack.optimize.OccurrenceOrderPlugin(),
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
@ -99,10 +111,11 @@ module.exports = {
|
||||
// }
|
||||
// }),
|
||||
new CopyWebpackPlugin([
|
||||
{ from: `${TREZOR_CONNECT_FILES}coins.json` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}releases.json` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}latest.txt` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}config_signed.bin` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}coins.json`, to: `${BUILD}/data/coins.json` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}releases-1.json`, to: `${BUILD}/data/releases-1.json` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}releases-2.json`, to: `${BUILD}/data/releases-2.json` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}latest.txt`, to: `${BUILD}/data/latest.txt` },
|
||||
{ from: `${TREZOR_CONNECT_FILES}config_signed.bin`, to: `${BUILD}/data/config_signed.bin` },
|
||||
]),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
|