mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Resolve merge conflict.
This commit is contained in:
commit
86b7cc6637
@ -6,6 +6,7 @@
|
|||||||
- Fix formatting of account details.
|
- Fix formatting of account details.
|
||||||
- Use web3 minified dist for faster inject times
|
- Use web3 minified dist for faster inject times
|
||||||
- Fix issue where dropdowns were not in front of icons.
|
- Fix issue where dropdowns were not in front of icons.
|
||||||
|
- Update transaction approval styles.
|
||||||
- Align failed and successful transaction history text.
|
- Align failed and successful transaction history text.
|
||||||
- Fix issue where large domain names and large transaction values would misalign the transaction history.
|
- Fix issue where large domain names and large transaction values would misalign the transaction history.
|
||||||
|
|
||||||
|
74
app/images/forward-carrat.svg
Normal file
74
app/images/forward-carrat.svg
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="4.2333331mm"
|
||||||
|
height="12.800793mm"
|
||||||
|
viewBox="0 0 14.999999 45.357139"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="forward-carrat.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="5.6"
|
||||||
|
inkscape:cx="17.87049"
|
||||||
|
inkscape:cy="17.678567"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
showguides="false"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:window-width="1276"
|
||||||
|
inkscape:window-height="755"
|
||||||
|
inkscape:window-x="4"
|
||||||
|
inkscape:window-y="1"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid4136"
|
||||||
|
originx="-180"
|
||||||
|
originy="-602.14286" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-180,-404.8622)">
|
||||||
|
<path
|
||||||
|
style="fill:#f7861c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 180,404.8622 0,7.5 10,15 -10,15 0,7.85714 15,-22.85714 z"
|
||||||
|
id="path4138"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccccc" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@ -18,7 +18,7 @@ html, body, #app-content, .super-dev-container {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #cccccc;
|
background: white;
|
||||||
}
|
}
|
||||||
.mock-app-root {
|
.mock-app-root {
|
||||||
background: #F7F7F7;
|
background: #F7F7F7;
|
||||||
|
84
development/states/empty-account-detail.json
Normal file
84
development/states/empty-account-detail.json
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
{
|
||||||
|
"metamask": {
|
||||||
|
"isInitialized": true,
|
||||||
|
"isUnlocked": true,
|
||||||
|
"currentDomain": "example.com",
|
||||||
|
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||||
|
"identities": {
|
||||||
|
"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": {
|
||||||
|
"name": "Wallet 1",
|
||||||
|
"address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
|
||||||
|
"mayBeFauceting": false
|
||||||
|
},
|
||||||
|
"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b": {
|
||||||
|
"name": "Wallet 2",
|
||||||
|
"address": "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b",
|
||||||
|
"mayBeFauceting": false
|
||||||
|
},
|
||||||
|
"0xeb9e64b93097bc15f01f13eae97015c57ab64823": {
|
||||||
|
"name": "Wallet 3",
|
||||||
|
"address": "0xeb9e64b93097bc15f01f13eae97015c57ab64823",
|
||||||
|
"mayBeFauceting": false
|
||||||
|
},
|
||||||
|
"0x704107d04affddd9b66ab9de3dd7b095852e9b69": {
|
||||||
|
"name": "Wallet 4",
|
||||||
|
"address": "0x704107d04affddd9b66ab9de3dd7b095852e9b69",
|
||||||
|
"mayBeFauceting": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unconfTxs": {},
|
||||||
|
"accounts": {
|
||||||
|
"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": {
|
||||||
|
"code": "0x",
|
||||||
|
"balance": "0x01",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"
|
||||||
|
},
|
||||||
|
"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b": {
|
||||||
|
"code": "0x",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"balance": "0x01",
|
||||||
|
"address": "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b"
|
||||||
|
},
|
||||||
|
"0xeb9e64b93097bc15f01f13eae97015c57ab64823": {
|
||||||
|
"code": "0x",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"balance": "0x01",
|
||||||
|
"address": "0xeb9e64b93097bc15f01f13eae97015c57ab64823"
|
||||||
|
},
|
||||||
|
"0x704107d04affddd9b66ab9de3dd7b095852e9b69": {
|
||||||
|
"code": "0x",
|
||||||
|
"balance": "0x0",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"address": "0x704107d04affddd9b66ab9de3dd7b095852e9b69"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transactions": [],
|
||||||
|
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
|
||||||
|
"network": "2",
|
||||||
|
"seedWords": null,
|
||||||
|
"isConfirmed": true,
|
||||||
|
"unconfMsgs": {},
|
||||||
|
"messages": [],
|
||||||
|
"provider": {
|
||||||
|
"type": "testnet"
|
||||||
|
},
|
||||||
|
"selectedAccount": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"
|
||||||
|
},
|
||||||
|
"appState": {
|
||||||
|
"menuOpen": false,
|
||||||
|
"currentView": {
|
||||||
|
"name": "accountDetail",
|
||||||
|
"detailView": null,
|
||||||
|
"context": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"
|
||||||
|
},
|
||||||
|
"accountDetail": {
|
||||||
|
"subview": "transactions"
|
||||||
|
},
|
||||||
|
"currentDomain": "127.0.0.1:9966",
|
||||||
|
"transForward": true,
|
||||||
|
"isLoading": false,
|
||||||
|
"warning": null
|
||||||
|
},
|
||||||
|
"identities": {}
|
||||||
|
}
|
1
development/states/pending-tx-contract.json
Normal file
1
development/states/pending-tx-contract.json
Normal file
File diff suppressed because one or more lines are too long
1
development/states/pending-tx-value.json
Normal file
1
development/states/pending-tx-value.json
Normal file
File diff suppressed because one or more lines are too long
1
development/states/pending_crash.json
Normal file
1
development/states/pending_crash.json
Normal file
File diff suppressed because one or more lines are too long
44
test/unit/nameForAccount_test.js
Normal file
44
test/unit/nameForAccount_test.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
var assert = require('assert')
|
||||||
|
var sinon = require('sinon')
|
||||||
|
|
||||||
|
var path = require('path')
|
||||||
|
var contractNamer = require(path.join(__dirname, '..', '..', 'ui', 'lib', 'contract-namer.js'))
|
||||||
|
|
||||||
|
describe('contractNamer', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.sinon = sinon.sandbox.create()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
this.sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('naming a contract', function() {
|
||||||
|
|
||||||
|
it('should return nothing for an unknown random account', function() {
|
||||||
|
const input = '0x2386F26FC10000'
|
||||||
|
const output = contractNamer(input)
|
||||||
|
assert.deepEqual(output, null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should accept identities as an optional second parameter', function() {
|
||||||
|
const input = '0x2386F26FC10000'.toLowerCase()
|
||||||
|
const expected = 'bar'
|
||||||
|
const identities = {}
|
||||||
|
identities[input] = { name: expected }
|
||||||
|
const output = contractNamer(input, identities)
|
||||||
|
assert.deepEqual(output, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should check for identities case insensitively', function() {
|
||||||
|
const input = '0x2386F26FC10000'.toLowerCase()
|
||||||
|
const expected = 'bar'
|
||||||
|
const identities = {}
|
||||||
|
identities[input] = { name: expected }
|
||||||
|
const output = contractNamer(input.toUpperCase(), identities)
|
||||||
|
assert.deepEqual(output, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
@ -52,6 +52,12 @@ describe('util', function() {
|
|||||||
var result = util.addressSummary(address)
|
var result = util.addressSummary(address)
|
||||||
assert.equal(result, '0xFDEa65C8...b825')
|
assert.equal(result, '0xFDEa65C8...b825')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should accept arguments for firstseg, lastseg, and keepPrefix', function() {
|
||||||
|
var address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'
|
||||||
|
var result = util.addressSummary(address, 4, 4, false)
|
||||||
|
assert.equal(result, 'FDEa...b825')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('isValidAddress', function() {
|
describe('isValidAddress', function() {
|
||||||
|
19
ui-dev.js
19
ui-dev.js
@ -1,3 +1,20 @@
|
|||||||
|
/* UI DEV
|
||||||
|
*
|
||||||
|
* This is a utility module.
|
||||||
|
* It initializes a minimalist browserifiable project
|
||||||
|
* that contains the Metamask UI, with a mocked state.
|
||||||
|
*
|
||||||
|
* Includes a state menu for switching between different
|
||||||
|
* mocked states, along with query param support,
|
||||||
|
* so those states are preserved when live-reloading.
|
||||||
|
*
|
||||||
|
* This is a convenient way to develop on the UI
|
||||||
|
* without having to re-enter your password
|
||||||
|
* every time the plugin rebuilds.
|
||||||
|
*
|
||||||
|
* To use, run `npm run ui`.
|
||||||
|
*/
|
||||||
|
|
||||||
const render = require('react-dom').render
|
const render = require('react-dom').render
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const Root = require('./ui/app/root')
|
const Root = require('./ui/app/root')
|
||||||
@ -54,7 +71,7 @@ render(
|
|||||||
style: {
|
style: {
|
||||||
height: '500px',
|
height: '500px',
|
||||||
width: '360px',
|
width: '360px',
|
||||||
boxShadow: '2px 2px 5px grey',
|
boxShadow: 'grey 0px 2px 9px',
|
||||||
margin: '20px',
|
margin: '20px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
|
@ -22,7 +22,7 @@ AccountPanel.prototype.render = function () {
|
|||||||
var panelState = {
|
var panelState = {
|
||||||
key: `accountPanel${identity.address}`,
|
key: `accountPanel${identity.address}`,
|
||||||
identiconKey: identity.address,
|
identiconKey: identity.address,
|
||||||
identiconLabel: identity.name,
|
identiconLabel: identity.name || '',
|
||||||
attributes: [
|
attributes: [
|
||||||
{
|
{
|
||||||
key: 'ADDRESS',
|
key: 'ADDRESS',
|
||||||
|
@ -12,9 +12,11 @@ function EthBalanceComponent () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EthBalanceComponent.prototype.render = function () {
|
EthBalanceComponent.prototype.render = function () {
|
||||||
var state = this.props
|
var props = this.props
|
||||||
var style = state.style
|
var style = props.style
|
||||||
var value = formatBalance(state.value)
|
|
||||||
|
const value = formatBalance(props.value)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
h('.ether-balance', {
|
h('.ether-balance', {
|
||||||
@ -30,30 +32,37 @@ EthBalanceComponent.prototype.render = function () {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
EthBalanceComponent.prototype.renderBalance = function (value) {
|
EthBalanceComponent.prototype.renderBalance = function (value) {
|
||||||
|
const props = this.props
|
||||||
if (value === 'None') return value
|
if (value === 'None') return value
|
||||||
var balanceObj = generateBalanceObject(value)
|
var balanceObj = generateBalanceObject(value)
|
||||||
|
|
||||||
var balance = balanceObj.balance
|
var balance = balanceObj.balance
|
||||||
var label = balanceObj.label
|
var label = balanceObj.label
|
||||||
|
var tagName = props.inline ? 'span' : 'div'
|
||||||
|
var topTag = props.inline ? 'div' : '.flex-column'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
h(Tooltip, {
|
h(Tooltip, {
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
title: value.split(' ')[0],
|
title: value.split(' ')[0],
|
||||||
}, [
|
}, [
|
||||||
h('.flex-column', {
|
h(topTag, {
|
||||||
style: {
|
style: {
|
||||||
alignItems: 'flex-end',
|
alignItems: 'flex-end',
|
||||||
lineHeight: '13px',
|
lineHeight: props.fontSize || '13px',
|
||||||
fontFamily: 'Montserrat Light',
|
fontFamily: 'Montserrat Regular',
|
||||||
textRendering: 'geometricPrecision',
|
textRendering: 'geometricPrecision',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
h('div', balance),
|
h(tagName, {
|
||||||
h('div', {
|
|
||||||
style: {
|
style: {
|
||||||
color: ' #AEAEAE',
|
fontSize: props.fontSize || '12px',
|
||||||
fontSize: '12px',
|
},
|
||||||
|
}, balance + ' '),
|
||||||
|
h(tagName, {
|
||||||
|
style: {
|
||||||
|
color: props.labelColor || '#AEAEAE',
|
||||||
|
fontSize: props.fontSize || '12px',
|
||||||
},
|
},
|
||||||
}, label),
|
}, label),
|
||||||
]),
|
]),
|
||||||
|
74
ui/app/components/mini-account-panel.js
Normal file
74
ui/app/components/mini-account-panel.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
const inherits = require('util').inherits
|
||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const Identicon = require('./identicon')
|
||||||
|
|
||||||
|
module.exports = AccountPanel
|
||||||
|
|
||||||
|
|
||||||
|
inherits(AccountPanel, Component)
|
||||||
|
function AccountPanel () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountPanel.prototype.render = function () {
|
||||||
|
var props = this.props
|
||||||
|
var picOrder = props.picOrder || 'left'
|
||||||
|
const { imageSeed } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
h('.identity-panel.flex-row.flex-left', {
|
||||||
|
style: {
|
||||||
|
cursor: props.onClick ? 'pointer' : undefined,
|
||||||
|
},
|
||||||
|
onClick: props.onClick,
|
||||||
|
}, [
|
||||||
|
|
||||||
|
this.genIcon(imageSeed, picOrder),
|
||||||
|
|
||||||
|
h('div.flex-column.flex-justify-center', {
|
||||||
|
style: {
|
||||||
|
lineHeight: '15px',
|
||||||
|
order: 2,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: picOrder === 'left' ? 'flex-begin' : 'flex-end',
|
||||||
|
},
|
||||||
|
}, this.props.children),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountPanel.prototype.genIcon = function (seed, picOrder) {
|
||||||
|
const props = this.props
|
||||||
|
|
||||||
|
// When there is no seed value, this is a contract creation.
|
||||||
|
// We then show the contract icon.
|
||||||
|
if (!seed) {
|
||||||
|
return h('.identicon-wrapper.flex-column.select-none', {
|
||||||
|
style: {
|
||||||
|
order: picOrder === 'left' ? 1 : 3,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('i.fa.fa-file-text-o.fa-lg', {
|
||||||
|
style: {
|
||||||
|
fontSize: '42px',
|
||||||
|
transform: 'translate(0px, -16px)',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there was a seed, we return an identicon for that address.
|
||||||
|
return h('.identicon-wrapper.flex-column.select-none', {
|
||||||
|
style: {
|
||||||
|
order: picOrder === 'left' ? 1 : 3,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h(Identicon, {
|
||||||
|
address: seed,
|
||||||
|
imageify: props.imageifyIdenticons,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,17 @@ const Component = require('react').Component
|
|||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
|
|
||||||
const AccountPanel = require('./account-panel')
|
const MiniAccountPanel = require('./mini-account-panel')
|
||||||
|
const EtherBalance = require('./eth-balance')
|
||||||
const addressSummary = require('../util').addressSummary
|
const addressSummary = require('../util').addressSummary
|
||||||
const readableDate = require('../util').readableDate
|
|
||||||
const formatBalance = require('../util').formatBalance
|
const formatBalance = require('../util').formatBalance
|
||||||
|
const nameForAddress = require('../../lib/contract-namer')
|
||||||
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const BN = ethUtil.BN
|
||||||
|
|
||||||
|
const baseGasFee = new BN('21000', 10)
|
||||||
|
const gasCost = new BN('4a817c800', 16)
|
||||||
|
const baseFeeHex = baseGasFee.mul(gasCost).toString(16)
|
||||||
|
|
||||||
module.exports = PendingTxDetails
|
module.exports = PendingTxDetails
|
||||||
|
|
||||||
@ -14,52 +21,204 @@ function PendingTxDetails () {
|
|||||||
Component.call(this)
|
Component.call(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingTxDetails.prototype.render = function () {
|
const PTXP = PendingTxDetails.prototype
|
||||||
var state = this.props
|
|
||||||
return this.renderGeneric(h, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingTxDetails.prototype.renderGeneric = function (h, state) {
|
PTXP.render = function () {
|
||||||
var txData = state.txData
|
var props = this.props
|
||||||
|
var txData = props.txData
|
||||||
|
|
||||||
var txParams = txData.txParams || {}
|
var txParams = txData.txParams || {}
|
||||||
var address = txParams.from || state.selectedAddress
|
var address = txParams.from || props.selectedAddress
|
||||||
var identity = state.identities[address] || { address: address }
|
var identity = props.identities[address] || { address: address }
|
||||||
var account = state.accounts[address] || { address: address }
|
var balance = props.accounts[address].balance
|
||||||
|
|
||||||
|
var gasCost = ethUtil.stripHexPrefix(txParams.gas || baseFeeHex)
|
||||||
|
var txValue = ethUtil.stripHexPrefix(txParams.value || '0x0')
|
||||||
|
var maxCost = ((new BN(txValue, 16)).add(new BN(gasCost, 16))).toString(16)
|
||||||
|
var dataLength = txParams.data ? (txParams.data.length - 2) / 2 : 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
h('div', [
|
h('div', [
|
||||||
|
|
||||||
// account that will sign
|
h('.flex-row.flex-center', {
|
||||||
h(AccountPanel, {
|
style: {
|
||||||
showFullAddress: true,
|
maxWidth: '100%',
|
||||||
identity: identity,
|
},
|
||||||
account: account,
|
}, [
|
||||||
imageifyIdenticons: state.imageifyIdenticons,
|
|
||||||
|
h(MiniAccountPanel, {
|
||||||
|
imageSeed: address,
|
||||||
|
imageifyIdenticons: props.imageifyIdenticons,
|
||||||
|
picOrder: 'right',
|
||||||
|
}, [
|
||||||
|
h('span.font-small', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
|
||||||
|
},
|
||||||
|
}, identity.name),
|
||||||
|
h('span.font-small', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Light, Montserrat, sans-serif',
|
||||||
|
},
|
||||||
|
}, addressSummary(address, 6, 4, false)),
|
||||||
|
|
||||||
|
h('span.font-small', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Light, Montserrat, sans-serif',
|
||||||
|
},
|
||||||
|
}, h(EtherBalance, {
|
||||||
|
value: balance,
|
||||||
|
inline: true,
|
||||||
|
})),
|
||||||
|
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('img', {
|
||||||
|
src: 'images/forward-carrat.svg',
|
||||||
|
style: {
|
||||||
|
padding: '5px 6px 0px 10px',
|
||||||
|
height: '37px',
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// tx data
|
this.miniAccountPanelForRecipient(),
|
||||||
h('.tx-data.flex-column.flex-justify-center.flex-grow.select-none', [
|
|
||||||
|
|
||||||
h('.flex-row.flex-space-between', [
|
|
||||||
h('label.font-small', 'TO ADDRESS'),
|
|
||||||
h('span.font-small', addressSummary(txParams.to)),
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('.flex-row.flex-space-between', [
|
h('style', `
|
||||||
h('label.font-small', 'DATE'),
|
.table-box {
|
||||||
h('span.font-small', readableDate(txData.time)),
|
margin: 7px 0px 0px 0px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.table-box .row {
|
||||||
|
margin: 0px;
|
||||||
|
background: rgb(236,236,236);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-family: Montserrat Light, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 5px 25px;
|
||||||
|
}
|
||||||
|
.table-box .row .value {
|
||||||
|
font-family: Montserrat Regular;
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
|
||||||
|
h('.table-box', [
|
||||||
|
|
||||||
|
h('.row', [
|
||||||
|
h('.cell.label', 'Amount'),
|
||||||
|
h('.cell.value', formatBalance(txParams.value)),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('.flex-row.flex-space-between', [
|
h('.cell.row', [
|
||||||
h('label.font-small', 'AMOUNT'),
|
h('.cell.label', 'Max Transaction Fee'),
|
||||||
h('span.font-small', formatBalance(txParams.value)),
|
h('.cell.value', formatBalance(gasCost)),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('.cell.row', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Regular',
|
||||||
|
background: 'white',
|
||||||
|
padding: '10px 25px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('.cell.label', 'Max Total'),
|
||||||
|
h('.cell.value', {
|
||||||
|
style: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h(EtherBalance, {
|
||||||
|
value: maxCost,
|
||||||
|
inline: true,
|
||||||
|
labelColor: 'black',
|
||||||
|
fontSize: '16px',
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
h('.cell.row', {
|
||||||
|
style: {
|
||||||
|
background: '#f7f7f7',
|
||||||
|
paddingBottom: '0px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('.cell.label'),
|
||||||
|
h('.cell.value', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Light',
|
||||||
|
fontSize: '11px',
|
||||||
|
},
|
||||||
|
}, `Data included: ${dataLength} bytes`),
|
||||||
|
]),
|
||||||
|
]), // End of Table
|
||||||
|
|
||||||
|
this.warnIfNeeded(),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PTXP.miniAccountPanelForRecipient = function () {
|
||||||
|
var props = this.props
|
||||||
|
var txData = props.txData
|
||||||
|
var txParams = txData.txParams || {}
|
||||||
|
var isContractDeploy = !('to' in txParams)
|
||||||
|
|
||||||
|
// If it's not a contract deploy, send to the account
|
||||||
|
if (!isContractDeploy) {
|
||||||
|
return h(MiniAccountPanel, {
|
||||||
|
imageSeed: txParams.to,
|
||||||
|
imageifyIdenticons: props.imageifyIdenticons,
|
||||||
|
picOrder: 'left',
|
||||||
|
}, [
|
||||||
|
h('span.font-small', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
|
||||||
|
},
|
||||||
|
}, nameForAddress(txParams.to, props.identities)),
|
||||||
|
h('span.font-small', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Light, Montserrat, sans-serif',
|
||||||
|
},
|
||||||
|
}, addressSummary(txParams.to, 6, 4, false)),
|
||||||
|
])
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return h(MiniAccountPanel, {
|
||||||
|
imageifyIdenticons: props.imageifyIdenticons,
|
||||||
|
picOrder: 'left',
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('span.font-small', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
|
||||||
|
},
|
||||||
|
}, 'New Contract'),
|
||||||
|
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should analyze if there is a DELEGATECALL opcode
|
||||||
|
// in the recipient contract, and show a warning if so.
|
||||||
|
PTXP.warnIfNeeded = function () {
|
||||||
|
const containsDelegateCall = !!this.props.txData.containsDelegateCall
|
||||||
|
|
||||||
|
if (!containsDelegateCall) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return h('span.error', {
|
||||||
|
style: {
|
||||||
|
fontFamily: 'Montserrat Light',
|
||||||
|
fontSize: '13px',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('i.fa.fa-lg.fa-info-circle', { style: { margin: '5px' } }),
|
||||||
|
h('span', ' Your identity may be used in other contracts!'),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
@ -21,29 +21,35 @@ PendingTx.prototype.render = function () {
|
|||||||
key: txData.id,
|
key: txData.id,
|
||||||
}, [
|
}, [
|
||||||
|
|
||||||
// header
|
|
||||||
h('h3', {
|
|
||||||
style: {
|
|
||||||
fontWeight: 'bold',
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
}, 'Submit Transaction'),
|
|
||||||
|
|
||||||
// tx info
|
// tx info
|
||||||
h(PendingTxDetails, state),
|
h(PendingTxDetails, state),
|
||||||
|
|
||||||
// send + cancel
|
h('style', `
|
||||||
h('.flex-row.flex-space-around', [
|
.conf-buttons button {
|
||||||
h('button', {
|
margin-left: 10px;
|
||||||
onClick: state.cancelTransaction,
|
text-transform: uppercase;
|
||||||
}, 'Reject'),
|
|
||||||
h('button', {
|
|
||||||
onClick: state.sendTransaction,
|
|
||||||
}, 'Approve'),
|
|
||||||
]),
|
|
||||||
|
|
||||||
])
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
`),
|
||||||
|
|
||||||
|
// send + cancel
|
||||||
|
h('.flex-row.flex-space-around.conf-buttons', {
|
||||||
|
style: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
margin: '14px 25px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('button.confirm', {
|
||||||
|
onClick: state.sendTransaction,
|
||||||
|
style: { background: 'rgb(251,117,1)' },
|
||||||
|
}, 'Accept'),
|
||||||
|
|
||||||
|
h('button.cancel', {
|
||||||
|
onClick: state.cancelTransaction,
|
||||||
|
style: { background: 'rgb(254,35,17)' },
|
||||||
|
}, 'Reject'),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -39,14 +39,14 @@ ConfirmTxScreen.prototype.render = function () {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
h('.unconftx-section.flex-column.flex-grow', [
|
h('.flex-column.flex-grow', [
|
||||||
|
|
||||||
// subtitle and nav
|
// subtitle and nav
|
||||||
h('.section-title.flex-row.flex-center', [
|
h('.section-title.flex-row.flex-center', [
|
||||||
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
|
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
|
||||||
onClick: this.goHome.bind(this),
|
onClick: this.goHome.bind(this),
|
||||||
}),
|
}),
|
||||||
h('h2.page-subtitle', 'Confirmation'),
|
h('h2.page-subtitle', 'Confirm Transaction'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('h3', {
|
h('h3', {
|
||||||
|
@ -411,10 +411,6 @@ input.large-input {
|
|||||||
}
|
}
|
||||||
/* tx confirm */
|
/* tx confirm */
|
||||||
|
|
||||||
.unconftx-section {
|
|
||||||
margin: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unconftx-section input[type=password] {
|
.unconftx-section input[type=password] {
|
||||||
height: 22px;
|
height: 22px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
@ -220,3 +220,9 @@ hr.horizontal-line {
|
|||||||
.invisible {
|
.invisible {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.one-line-concat {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ for (var currency in valueTable) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
valuesFor: valuesFor,
|
valuesFor: valuesFor,
|
||||||
addressSummary: addressSummary,
|
addressSummary: addressSummary,
|
||||||
|
miniAddressSummary: miniAddressSummary,
|
||||||
isAllOneCase: isAllOneCase,
|
isAllOneCase: isAllOneCase,
|
||||||
isValidAddress: isValidAddress,
|
isValidAddress: isValidAddress,
|
||||||
numericBalance: numericBalance,
|
numericBalance: numericBalance,
|
||||||
@ -44,10 +45,19 @@ function valuesFor (obj) {
|
|||||||
.map(function (key) { return obj[key] })
|
.map(function (key) { return obj[key] })
|
||||||
}
|
}
|
||||||
|
|
||||||
function addressSummary (address) {
|
function addressSummary (address, firstSegLength = 10, lastSegLength = 4, includeHex = true) {
|
||||||
|
if (!address) return ''
|
||||||
|
let checked = ethUtil.toChecksumAddress(address)
|
||||||
|
if (!includeHex) {
|
||||||
|
checked = ethUtil.stripHexPrefix(checked)
|
||||||
|
}
|
||||||
|
return checked ? checked.slice(0, firstSegLength) + '...' + checked.slice(checked.length - lastSegLength) : '...'
|
||||||
|
}
|
||||||
|
|
||||||
|
function miniAddressSummary (address) {
|
||||||
if (!address) return ''
|
if (!address) return ''
|
||||||
var checked = ethUtil.toChecksumAddress(address)
|
var checked = ethUtil.toChecksumAddress(address)
|
||||||
return checked ? checked.slice(0, 2 + 8) + '...' + checked.slice(-4) : '...'
|
return checked ? checked.slice(0, 4) + '...' + checked.slice(-4) : '...'
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidAddress (address) {
|
function isValidAddress (address) {
|
||||||
@ -95,7 +105,8 @@ function parseBalance (balance) {
|
|||||||
return [beforeDecimal, afterDecimal]
|
return [beforeDecimal, afterDecimal]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes wei hex, returns "None" or "${formattedAmount} ETH"
|
// Takes wei hex, returns an object with three properties.
|
||||||
|
// Its "formatted" property is what we generally use to render values.
|
||||||
function formatBalance (balance, decimalsToKeep) {
|
function formatBalance (balance, decimalsToKeep) {
|
||||||
var parsed = parseBalance(balance)
|
var parsed = parseBalance(balance)
|
||||||
var beforeDecimal = parsed[0]
|
var beforeDecimal = parsed[0]
|
||||||
|
31
ui/lib/contract-namer.js
Normal file
31
ui/lib/contract-namer.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* CONTRACT NAMER
|
||||||
|
*
|
||||||
|
* Takes an address,
|
||||||
|
* Returns a nicname if we have one stored,
|
||||||
|
* otherwise returns null.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Nickname keys must be stored in lower case.
|
||||||
|
const nicknames = {}
|
||||||
|
|
||||||
|
module.exports = function(addr, identities = {}) {
|
||||||
|
|
||||||
|
const address = addr.toLowerCase()
|
||||||
|
const ids = hashFromIdentities(identities)
|
||||||
|
|
||||||
|
console.dir({ addr, ids })
|
||||||
|
return addrFromHash(address, ids) || addrFromHash(address, nicknames)
|
||||||
|
}
|
||||||
|
|
||||||
|
function hashFromIdentities(identities) {
|
||||||
|
const result = {}
|
||||||
|
for (let key in identities) {
|
||||||
|
result[key] = identities[key].name
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function addrFromHash(addr, hash) {
|
||||||
|
const address = addr.toLowerCase()
|
||||||
|
return hash[address] || null
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user