mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-23 02:10:12 +01:00
Merge master.
This commit is contained in:
commit
6895d330ff
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
- Integrate ShapeShift
|
||||||
|
- Add a for for Coinbase to specify amount to buy
|
||||||
- Fix various typos.
|
- Fix various typos.
|
||||||
|
- Make dapp-metamask connection more reliable
|
||||||
|
- Remove Ethereum Classic from provider menu.
|
||||||
|
|
||||||
## 2.7.3 2016-07-29
|
## 2.7.3 2016-07-29
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ const extension = require('./lib/extension')
|
|||||||
|
|
||||||
const STORAGE_KEY = 'metamask-config'
|
const STORAGE_KEY = 'metamask-config'
|
||||||
|
|
||||||
|
|
||||||
const controller = new MetamaskController({
|
const controller = new MetamaskController({
|
||||||
// User confirmation callbacks:
|
// User confirmation callbacks:
|
||||||
showUnconfirmedMessage,
|
showUnconfirmedMessage,
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
const MAINET_RPC_URL = 'https://mainnet.infura.io/'
|
const MAINET_RPC_URL = 'https://mainnet.infura.io/'
|
||||||
const TESTNET_RPC_URL = 'https://morden.infura.io/'
|
const TESTNET_RPC_URL = 'https://morden.infura.io/'
|
||||||
const DEFAULT_RPC_URL = TESTNET_RPC_URL
|
const DEFAULT_RPC_URL = TESTNET_RPC_URL
|
||||||
const CLASSIC_RPC_URL = 'https://mainnet-nf.infura.io/'
|
|
||||||
|
global.METAMASK_DEBUG = false
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
network: {
|
network: {
|
||||||
default: DEFAULT_RPC_URL,
|
default: DEFAULT_RPC_URL,
|
||||||
mainnet: MAINET_RPC_URL,
|
mainnet: MAINET_RPC_URL,
|
||||||
testnet: TESTNET_RPC_URL,
|
testnet: TESTNET_RPC_URL,
|
||||||
classic: CLASSIC_RPC_URL,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
|
const LocalMessageDuplexStream = require('post-message-stream')
|
||||||
const PortStream = require('./lib/port-stream.js')
|
const PortStream = require('./lib/port-stream.js')
|
||||||
const ObjectMultiplex = require('./lib/obj-multiplex')
|
const ObjectMultiplex = require('./lib/obj-multiplex')
|
||||||
const extension = require('./lib/extension')
|
const extension = require('./lib/extension')
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*global Web3*/
|
/*global Web3*/
|
||||||
cleanContextForImports()
|
cleanContextForImports()
|
||||||
require('web3/dist/web3.min.js')
|
require('web3/dist/web3.min.js')
|
||||||
const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
|
const LocalMessageDuplexStream = require('post-message-stream')
|
||||||
const setupDappAutoReload = require('./lib/auto-reload.js')
|
const setupDappAutoReload = require('./lib/auto-reload.js')
|
||||||
const MetamaskInpageProvider = require('./lib/inpage-provider.js')
|
const MetamaskInpageProvider = require('./lib/inpage-provider.js')
|
||||||
restoreContextAfterImports()
|
restoreContextAfterImports()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const once = require('once')
|
const once = require('once')
|
||||||
const ensnare = require('./ensnare.js')
|
const ensnare = require('ensnare')
|
||||||
|
|
||||||
module.exports = setupDappAutoReload
|
module.exports = setupDappAutoReload
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ const rp = require('request-promise')
|
|||||||
|
|
||||||
const TESTNET_RPC = MetamaskConfig.network.testnet
|
const TESTNET_RPC = MetamaskConfig.network.testnet
|
||||||
const MAINNET_RPC = MetamaskConfig.network.mainnet
|
const MAINNET_RPC = MetamaskConfig.network.mainnet
|
||||||
const CLASSIC_RPC = MetamaskConfig.network.classic
|
|
||||||
|
|
||||||
/* The config-manager is a convenience object
|
/* The config-manager is a convenience object
|
||||||
* wrapping a pojo-migrator.
|
* wrapping a pojo-migrator.
|
||||||
@ -146,9 +145,6 @@ ConfigManager.prototype.getCurrentRpcAddress = function () {
|
|||||||
case 'testnet':
|
case 'testnet':
|
||||||
return TESTNET_RPC
|
return TESTNET_RPC
|
||||||
|
|
||||||
case 'classic':
|
|
||||||
return CLASSIC_RPC
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC
|
return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC
|
||||||
}
|
}
|
||||||
@ -320,9 +316,13 @@ ConfigManager.prototype.getConversionDate = function () {
|
|||||||
return ('conversionDate' in data) && data.conversionDate
|
return ('conversionDate' in data) && data.conversionDate
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigManager.prototype.setShouldntShowWarning = function (confirmed) {
|
ConfigManager.prototype.setShouldntShowWarning = function () {
|
||||||
var data = this.getData()
|
var data = this.getData()
|
||||||
data.isEthConfirmed = confirmed
|
if (data.isEthConfirmed) {
|
||||||
|
data.isEthConfirmed = !data.isEthConfirmed
|
||||||
|
} else {
|
||||||
|
data.isEthConfirmed = true
|
||||||
|
}
|
||||||
this.setData(data)
|
this.setData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
module.exports = ensnare
|
|
||||||
|
|
||||||
// creates a proxy object that calls cb everytime the obj's properties/fns are accessed
|
|
||||||
function ensnare (obj, cb) {
|
|
||||||
var proxy = {}
|
|
||||||
Object.keys(obj).forEach(function (key) {
|
|
||||||
var val = obj[key]
|
|
||||||
switch (typeof val) {
|
|
||||||
case 'function':
|
|
||||||
proxy[key] = function () {
|
|
||||||
cb()
|
|
||||||
val.apply(obj, arguments)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
Object.defineProperty(proxy, key, {
|
|
||||||
get: function () { cb(); return obj[key] },
|
|
||||||
set: function (val) { cb(); obj[key] = val; return val },
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return proxy
|
|
||||||
}
|
|
@ -156,8 +156,9 @@ IdentityStore.prototype.getNetwork = function (err) {
|
|||||||
this._currentState.network = 'loading'
|
this._currentState.network = 'loading'
|
||||||
return this._didUpdate()
|
return this._didUpdate()
|
||||||
}
|
}
|
||||||
|
if (global.METAMASK_DEBUG) {
|
||||||
console.log('web3.getNetwork returned ' + network)
|
console.log('web3.getNetwork returned ' + network)
|
||||||
|
}
|
||||||
this._currentState.network = network
|
this._currentState.network = network
|
||||||
this._didUpdate()
|
this._didUpdate()
|
||||||
})
|
})
|
||||||
@ -478,7 +479,9 @@ IdentityStore.prototype._restoreFromSeed = function (password, seed, derivedKey)
|
|||||||
|
|
||||||
keyStore.generateNewAddress(derivedKey, 3)
|
keyStore.generateNewAddress(derivedKey, 3)
|
||||||
configManager.setWallet(keyStore.serialize())
|
configManager.setWallet(keyStore.serialize())
|
||||||
console.log('restored from seed. saved to keystore')
|
if (global.METAMASK_DEBUG) {
|
||||||
|
console.log('restored from seed. saved to keystore')
|
||||||
|
}
|
||||||
return keyStore
|
return keyStore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
const HttpProvider = require('web3/lib/web3/httpprovider')
|
|
||||||
const Streams = require('mississippi')
|
const Streams = require('mississippi')
|
||||||
const ObjectMultiplex = require('./obj-multiplex')
|
const ObjectMultiplex = require('./obj-multiplex')
|
||||||
const StreamProvider = require('web3-stream-provider')
|
const StreamProvider = require('web3-stream-provider')
|
||||||
const RemoteStore = require('./remote-store.js').RemoteStore
|
const RemoteStore = require('./remote-store.js').RemoteStore
|
||||||
const MetamaskConfig = require('../config.js')
|
|
||||||
|
|
||||||
module.exports = MetamaskInpageProvider
|
module.exports = MetamaskInpageProvider
|
||||||
|
|
||||||
@ -27,13 +25,6 @@ function MetamaskInpageProvider (connectionStream) {
|
|||||||
})
|
})
|
||||||
self.publicConfigStore = publicConfigStore
|
self.publicConfigStore = publicConfigStore
|
||||||
|
|
||||||
// connect to sync provider
|
|
||||||
self.syncProvider = createSyncProvider(publicConfigStore.get('provider'))
|
|
||||||
// subscribe to publicConfig to update the syncProvider on change
|
|
||||||
publicConfigStore.subscribe(function (state) {
|
|
||||||
self.syncProvider = createSyncProvider(state.provider)
|
|
||||||
})
|
|
||||||
|
|
||||||
// connect to async provider
|
// connect to async provider
|
||||||
var asyncProvider = new StreamProvider()
|
var asyncProvider = new StreamProvider()
|
||||||
Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
|
Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
|
||||||
@ -48,9 +39,9 @@ function MetamaskInpageProvider (connectionStream) {
|
|||||||
|
|
||||||
MetamaskInpageProvider.prototype.send = function (payload) {
|
MetamaskInpageProvider.prototype.send = function (payload) {
|
||||||
const self = this
|
const self = this
|
||||||
let selectedAddress
|
|
||||||
|
|
||||||
var result = null
|
let selectedAddress
|
||||||
|
let result = null
|
||||||
switch (payload.method) {
|
switch (payload.method) {
|
||||||
|
|
||||||
case 'eth_accounts':
|
case 'eth_accounts':
|
||||||
@ -65,9 +56,10 @@ MetamaskInpageProvider.prototype.send = function (payload) {
|
|||||||
result = selectedAddress || '0x0000000000000000000000000000000000000000'
|
result = selectedAddress || '0x0000000000000000000000000000000000000000'
|
||||||
break
|
break
|
||||||
|
|
||||||
// fallback to normal rpc
|
// throw not-supported Error
|
||||||
default:
|
default:
|
||||||
return self.syncProvider.send(payload)
|
var message = 'The MetaMask Web3 object does not support synchronous methods. See https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#all-async---think-of-metamask-as-a-light-client for details.'
|
||||||
|
throw new Error(message)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,35 +81,6 @@ MetamaskInpageProvider.prototype.isConnected = function () {
|
|||||||
|
|
||||||
// util
|
// util
|
||||||
|
|
||||||
function createSyncProvider (providerConfig) {
|
|
||||||
providerConfig = providerConfig || {}
|
|
||||||
let syncProviderUrl
|
|
||||||
|
|
||||||
if (providerConfig.rpcTarget) {
|
|
||||||
syncProviderUrl = providerConfig.rpcTarget
|
|
||||||
} else {
|
|
||||||
switch (providerConfig.type) {
|
|
||||||
case 'testnet':
|
|
||||||
syncProviderUrl = MetamaskConfig.network.testnet
|
|
||||||
break
|
|
||||||
case 'mainnet':
|
|
||||||
syncProviderUrl = MetamaskConfig.network.mainnet
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
syncProviderUrl = MetamaskConfig.network.default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const provider = new HttpProvider(syncProviderUrl)
|
|
||||||
// Stubbing out the send method to throw on sync methods:
|
|
||||||
provider.send = function() {
|
|
||||||
var message = 'The MetaMask Web3 object does not support synchronous methods. See https://github.com/MetaMask/faq#all-async---think-of-metamask-as-a-light-client for details.'
|
|
||||||
throw new Error(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
return provider
|
|
||||||
}
|
|
||||||
|
|
||||||
function remoteStoreWithLocalStorageCache (storageKey) {
|
function remoteStoreWithLocalStorageCache (storageKey) {
|
||||||
// read local cache
|
// read local cache
|
||||||
var initState = JSON.parse(localStorage[storageKey] || '{}')
|
var initState = JSON.parse(localStorage[storageKey] || '{}')
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
const Duplex = require('readable-stream').Duplex
|
|
||||||
const inherits = require('util').inherits
|
|
||||||
|
|
||||||
module.exports = LocalMessageDuplexStream
|
|
||||||
|
|
||||||
inherits(LocalMessageDuplexStream, Duplex)
|
|
||||||
|
|
||||||
function LocalMessageDuplexStream (opts) {
|
|
||||||
Duplex.call(this, {
|
|
||||||
objectMode: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
// this._origin = opts.origin
|
|
||||||
this._name = opts.name
|
|
||||||
this._target = opts.target
|
|
||||||
|
|
||||||
// console.log('LocalMessageDuplexStream ('+this._name+') - initialized...')
|
|
||||||
window.addEventListener('message', this._onMessage.bind(this), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// private
|
|
||||||
|
|
||||||
LocalMessageDuplexStream.prototype._onMessage = function (event) {
|
|
||||||
var msg = event.data
|
|
||||||
// console.log('LocalMessageDuplexStream ('+this._name+') - heard message...', event)
|
|
||||||
// validate message
|
|
||||||
if (event.origin !== location.origin) return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (event.origin !== location.origin) ')
|
|
||||||
if (typeof msg !== 'object') return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (typeof msg !== "object") ')
|
|
||||||
if (msg.target !== this._name) return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (msg.target !== this._name) ', msg.target, this._name)
|
|
||||||
if (!msg.data) return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (!msg.data) ')
|
|
||||||
// console.log('LocalMessageDuplexStream ('+this._name+') - accepted', msg.data)
|
|
||||||
// forward message
|
|
||||||
try {
|
|
||||||
this.push(msg.data)
|
|
||||||
} catch (err) {
|
|
||||||
this.emit('error', err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// stream plumbing
|
|
||||||
|
|
||||||
LocalMessageDuplexStream.prototype._read = noop
|
|
||||||
|
|
||||||
LocalMessageDuplexStream.prototype._write = function (data, encoding, cb) {
|
|
||||||
// console.log('LocalMessageDuplexStream ('+this._name+') - sending message...')
|
|
||||||
var message = {
|
|
||||||
target: this._target,
|
|
||||||
data: data,
|
|
||||||
}
|
|
||||||
window.postMessage(message, location.origin)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
|
|
||||||
// util
|
|
||||||
|
|
||||||
function noop () {}
|
|
@ -99,7 +99,9 @@ module.exports = class MetamaskController {
|
|||||||
function logger (err, request, response) {
|
function logger (err, request, response) {
|
||||||
if (err) return console.error(err)
|
if (err) return console.error(err)
|
||||||
if (!request.isMetamaskInternal) {
|
if (!request.isMetamaskInternal) {
|
||||||
console.log(`RPC (${originDomain}):`, request, '->', response)
|
if (global.METAMASK_DEBUG) {
|
||||||
|
console.log(`RPC (${originDomain}):`, request, '->', response)
|
||||||
|
}
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.error('Error in RPC response:\n', response.error)
|
console.error('Error in RPC response:\n', response.error)
|
||||||
}
|
}
|
||||||
@ -223,7 +225,9 @@ module.exports = class MetamaskController {
|
|||||||
|
|
||||||
// Log blocks
|
// Log blocks
|
||||||
processBlock (block) {
|
processBlock (block) {
|
||||||
console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`)
|
if (global.METAMASK_DEBUG) {
|
||||||
|
console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`)
|
||||||
|
}
|
||||||
this.verifyNetwork()
|
this.verifyNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +278,7 @@ module.exports = class MetamaskController {
|
|||||||
|
|
||||||
agreeToEthWarning (cb) {
|
agreeToEthWarning (cb) {
|
||||||
try {
|
try {
|
||||||
this.configManager.setShouldntShowWarning(true)
|
this.configManager.setShouldntShowWarning()
|
||||||
cb()
|
cb()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
cb(e)
|
cb(e)
|
||||||
|
189
development/states/custom-rpc.json
Normal file
189
development/states/custom-rpc.json
Normal file
File diff suppressed because one or more lines are too long
@ -19,6 +19,7 @@ const Root = require('./ui/app/root')
|
|||||||
const configureStore = require('./ui/app/store')
|
const configureStore = require('./ui/app/store')
|
||||||
const actions = require('./ui/app/actions')
|
const actions = require('./ui/app/actions')
|
||||||
const states = require('./development/states')
|
const states = require('./development/states')
|
||||||
|
const Selector = require('./development/selector')
|
||||||
const MetamaskController = require('./app/scripts/metamask-controller')
|
const MetamaskController = require('./app/scripts/metamask-controller')
|
||||||
const extension = require('./development/mockExtension')
|
const extension = require('./development/mockExtension')
|
||||||
|
|
||||||
@ -139,6 +140,8 @@ render(
|
|||||||
},
|
},
|
||||||
}, 'Reset State'),
|
}, 'Reset State'),
|
||||||
|
|
||||||
|
h(Selector, { actions, selectedKey: selectedView, states, store }),
|
||||||
|
|
||||||
h('.mock-app-root', {
|
h('.mock-app-root', {
|
||||||
style: {
|
style: {
|
||||||
height: '500px',
|
height: '500px',
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
"debounce": "^1.0.0",
|
"debounce": "^1.0.0",
|
||||||
"dnode": "^1.2.2",
|
"dnode": "^1.2.2",
|
||||||
"end-of-stream": "^1.1.0",
|
"end-of-stream": "^1.1.0",
|
||||||
|
"ensnare": "^1.0.0",
|
||||||
"eth-bin-to-ops": "^1.0.0",
|
"eth-bin-to-ops": "^1.0.0",
|
||||||
"eth-lightwallet": "^2.3.3",
|
"eth-lightwallet": "^2.3.3",
|
||||||
"eth-query": "^1.0.3",
|
"eth-query": "^1.0.3",
|
||||||
@ -53,6 +54,7 @@
|
|||||||
"once": "^1.3.3",
|
"once": "^1.3.3",
|
||||||
"pojo-migrator": "^2.1.0",
|
"pojo-migrator": "^2.1.0",
|
||||||
"polyfill-crypto.getrandomvalues": "^1.0.0",
|
"polyfill-crypto.getrandomvalues": "^1.0.0",
|
||||||
|
"post-message-stream": "^1.0.0",
|
||||||
"pumpify": "^1.3.4",
|
"pumpify": "^1.3.4",
|
||||||
"react": "^15.0.2",
|
"react": "^15.0.2",
|
||||||
"react-addons-css-transition-group": "^15.0.2",
|
"react-addons-css-transition-group": "^15.0.2",
|
||||||
@ -73,7 +75,7 @@
|
|||||||
"vreme": "^3.0.2",
|
"vreme": "^3.0.2",
|
||||||
"web3": "ethereum/web3.js#0.16.0",
|
"web3": "ethereum/web3.js#0.16.0",
|
||||||
"web3-provider-engine": "^7.8.3",
|
"web3-provider-engine": "^7.8.3",
|
||||||
"web3-stream-provider": "^2.0.5",
|
"web3-stream-provider": "^2.0.6",
|
||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -107,6 +109,7 @@
|
|||||||
"qunit": "^0.9.1",
|
"qunit": "^0.9.1",
|
||||||
"sinon": "^1.17.3",
|
"sinon": "^1.17.3",
|
||||||
"tape": "^4.5.1",
|
"tape": "^4.5.1",
|
||||||
|
"testem": "^1.10.3",
|
||||||
"uglifyify": "^3.0.1",
|
"uglifyify": "^3.0.1",
|
||||||
"vinyl-buffer": "^1.0.0",
|
"vinyl-buffer": "^1.0.0",
|
||||||
"vinyl-source-stream": "^1.1.0",
|
"vinyl-source-stream": "^1.1.0",
|
||||||
|
@ -15,7 +15,7 @@ const ExportAccountView = require('./components/account-export')
|
|||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const EditableLabel = require('./components/editable-label')
|
const EditableLabel = require('./components/editable-label')
|
||||||
const Tooltip = require('./components/tooltip')
|
const Tooltip = require('./components/tooltip')
|
||||||
|
const BuyButtonSubview = require('./components/buy-button-subview')
|
||||||
module.exports = connect(mapStateToProps)(AccountDetailScreen)
|
module.exports = connect(mapStateToProps)(AccountDetailScreen)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
@ -173,14 +173,19 @@ AccountDetailScreen.prototype.render = function () {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
h('button', {
|
h('button', {
|
||||||
onClick: () => props.dispatch(actions.buyEth(selected)),
|
onClick: () => props.dispatch(actions.buyEthView(selected)),
|
||||||
style: {
|
style: {
|
||||||
marginBottom: '20px',
|
marginBottom: '20px',
|
||||||
marginRight: '8px',
|
marginRight: '8px',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: '219px',
|
left: '219px',
|
||||||
},
|
},
|
||||||
}, 'BUY'),
|
}, props.accountDetail.subview === 'buyForm' ? [h('i.fa.fa-arrow-left', {
|
||||||
|
style: {
|
||||||
|
width: '22.641px',
|
||||||
|
height: '14px',
|
||||||
|
},
|
||||||
|
})] : 'BUY'),
|
||||||
|
|
||||||
h('button', {
|
h('button', {
|
||||||
onClick: () => props.dispatch(actions.showSendPage()),
|
onClick: () => props.dispatch(actions.showSendPage()),
|
||||||
@ -221,6 +226,8 @@ AccountDetailScreen.prototype.subview = function () {
|
|||||||
case 'export':
|
case 'export':
|
||||||
var state = extend({key: 'export'}, this.props)
|
var state = extend({key: 'export'}, this.props)
|
||||||
return h(ExportAccountView, state)
|
return h(ExportAccountView, state)
|
||||||
|
case 'buyForm':
|
||||||
|
return h(BuyButtonSubview, extend({key: 'buyForm'}, this.props))
|
||||||
default:
|
default:
|
||||||
return this.transactionList()
|
return this.transactionList()
|
||||||
}
|
}
|
||||||
@ -251,3 +258,14 @@ AccountDetailScreen.prototype.transactionList = function () {
|
|||||||
AccountDetailScreen.prototype.requestAccountExport = function () {
|
AccountDetailScreen.prototype.requestAccountExport = function () {
|
||||||
this.props.dispatch(actions.requestExportAccount())
|
this.props.dispatch(actions.requestExportAccount())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AccountDetailScreen.prototype.buyButtonDeligator = function () {
|
||||||
|
var props = this.props
|
||||||
|
|
||||||
|
if (this.props.accountDetail.subview === 'buyForm') {
|
||||||
|
props.dispatch(actions.backToAccountDetail(props.address))
|
||||||
|
} else {
|
||||||
|
props.dispatch(actions.buyEthView())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -115,6 +115,26 @@ var actions = {
|
|||||||
// buy Eth with coinbase
|
// buy Eth with coinbase
|
||||||
BUY_ETH: 'BUY_ETH',
|
BUY_ETH: 'BUY_ETH',
|
||||||
buyEth: buyEth,
|
buyEth: buyEth,
|
||||||
|
buyEthView: buyEthView,
|
||||||
|
BUY_ETH_VIEW: 'BUY_ETH_VIEW',
|
||||||
|
UPDATE_COINBASE_AMOUNT: 'UPDATE_COIBASE_AMOUNT',
|
||||||
|
updateCoinBaseAmount: updateCoinBaseAmount,
|
||||||
|
UPDATE_BUY_ADDRESS: 'UPDATE_BUY_ADDRESS',
|
||||||
|
updateBuyAddress: updateBuyAddress,
|
||||||
|
COINBASE_SUBVIEW: 'COINBASE_SUBVIEW',
|
||||||
|
coinBaseSubview: coinBaseSubview,
|
||||||
|
SHAPESHIFT_SUBVIEW: 'SHAPESHIFT_SUBVIEW',
|
||||||
|
shapeShiftSubview: shapeShiftSubview,
|
||||||
|
PAIR_UPDATE: 'PAIR_UPDATE',
|
||||||
|
pairUpdate: pairUpdate,
|
||||||
|
coinShiftRquest: coinShiftRquest,
|
||||||
|
SHOW_SUB_LOADING_INDICATION: 'SHOW_SUB_LOADING_INDICATION',
|
||||||
|
showSubLoadingIndication: showSubLoadingIndication,
|
||||||
|
HIDE_SUB_LOADING_INDICATION: 'HIDE_SUB_LOADING_INDICATION',
|
||||||
|
hideSubLoadingIndication: hideSubLoadingIndication,
|
||||||
|
// QR STUFF:
|
||||||
|
SHOW_QR: 'SHOW_QR',
|
||||||
|
getQr: getQr,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = actions
|
module.exports = actions
|
||||||
@ -520,6 +540,18 @@ function hideLoadingIndication () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showSubLoadingIndication () {
|
||||||
|
return {
|
||||||
|
type: actions.SHOW_SUB_LOADING_INDICATION,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideSubLoadingIndication () {
|
||||||
|
return {
|
||||||
|
type: actions.HIDE_SUB_LOADING_INDICATION,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showWarning (text) {
|
function showWarning (text) {
|
||||||
return this.displayWarning(text)
|
return this.displayWarning(text)
|
||||||
}
|
}
|
||||||
@ -618,3 +650,132 @@ function buyEth (address, amount) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buyEthView (address) {
|
||||||
|
return {
|
||||||
|
type: actions.BUY_ETH_VIEW,
|
||||||
|
value: address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCoinBaseAmount (value) {
|
||||||
|
return {
|
||||||
|
type: actions.UPDATE_COINBASE_AMOUNT,
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBuyAddress (value) {
|
||||||
|
return {
|
||||||
|
type: actions.UPDATE_BUY_ADDRESS,
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function coinBaseSubview () {
|
||||||
|
return {
|
||||||
|
type: actions.COINBASE_SUBVIEW,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pairUpdate (coin) {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(actions.showSubLoadingIndication())
|
||||||
|
dispatch(actions.hideWarning())
|
||||||
|
shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => {
|
||||||
|
dispatch(actions.hideSubLoadingIndication())
|
||||||
|
dispatch({
|
||||||
|
type: actions.PAIR_UPDATE,
|
||||||
|
value: {
|
||||||
|
marketinfo: mktResponse,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shapeShiftSubview (network) {
|
||||||
|
var pair = 'btc_eth'
|
||||||
|
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(actions.showSubLoadingIndication())
|
||||||
|
shapeShiftRequest('marketinfo', {pair}, (mktResponse) => {
|
||||||
|
shapeShiftRequest('getcoins', {}, (response) => {
|
||||||
|
dispatch(actions.hideSubLoadingIndication())
|
||||||
|
if (mktResponse.error) return dispatch(actions.showWarning(mktResponse.error))
|
||||||
|
dispatch({
|
||||||
|
type: actions.SHAPESHIFT_SUBVIEW,
|
||||||
|
value: {
|
||||||
|
marketinfo: mktResponse,
|
||||||
|
coinOptions: response,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function coinShiftRquest (data, marketData) {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
shapeShiftRequest('shift', { method: 'POST', data}, (response) => {
|
||||||
|
if (response.error) return dispatch(actions.showWarning(response.error))
|
||||||
|
var message = `
|
||||||
|
Deposit your ${response.depositType} to the address bellow:`
|
||||||
|
dispatch(actions.getQr(response.deposit, '125x125', [message].concat(marketData)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQr (data, size, message) {
|
||||||
|
return (dispatch) => {
|
||||||
|
qrRequest(data, size, (response) => {
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
if (response.error) return dispatch(actions.showWarning(response.error))
|
||||||
|
dispatch({
|
||||||
|
type: actions.SHOW_QR,
|
||||||
|
value: {
|
||||||
|
qr: response,
|
||||||
|
message: message,
|
||||||
|
data: data,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shapeShiftRequest (query, options, cb) {
|
||||||
|
var queryResponse, method
|
||||||
|
!options ? options = {} : null
|
||||||
|
options.method ? method = options.method : method = 'GET'
|
||||||
|
|
||||||
|
var requestListner = function (request) {
|
||||||
|
queryResponse = JSON.parse(this.responseText)
|
||||||
|
cb ? cb(queryResponse) : null
|
||||||
|
return queryResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
var shapShiftReq = new XMLHttpRequest()
|
||||||
|
shapShiftReq.addEventListener('load', requestListner)
|
||||||
|
shapShiftReq.open(method, `https://shapeshift.io/${query}/${options.pair ? options.pair : ''}`, true)
|
||||||
|
|
||||||
|
if (options.method === 'POST') {
|
||||||
|
var jsonObj = JSON.stringify(options.data)
|
||||||
|
shapShiftReq.setRequestHeader('Content-Type', 'application/json')
|
||||||
|
return shapShiftReq.send(jsonObj)
|
||||||
|
} else {
|
||||||
|
return shapShiftReq.send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function qrRequest (data, size, cb) {
|
||||||
|
var requestListner = function (request) {
|
||||||
|
cb ? cb(this.responseText) : null
|
||||||
|
return this.responseText
|
||||||
|
}
|
||||||
|
|
||||||
|
var qrReq = new XMLHttpRequest()
|
||||||
|
qrReq.addEventListener('load', requestListner)
|
||||||
|
qrReq.open('GET', `https://api.qrserver.com/v1/create-qr-code/?size=${size}&format=svg&data=${data}`, true)
|
||||||
|
qrReq.send()
|
||||||
|
}
|
||||||
|
@ -28,7 +28,7 @@ const DropMenuItem = require('./components/drop-menu-item')
|
|||||||
const NetworkIndicator = require('./components/network')
|
const NetworkIndicator = require('./components/network')
|
||||||
const Tooltip = require('./components/tooltip')
|
const Tooltip = require('./components/tooltip')
|
||||||
const EthStoreWarning = require('./eth-store-warning')
|
const EthStoreWarning = require('./eth-store-warning')
|
||||||
|
const BuyView = require('./components/buy-button-subview')
|
||||||
module.exports = connect(mapStateToProps)(App)
|
module.exports = connect(mapStateToProps)(App)
|
||||||
|
|
||||||
inherits(App, Component)
|
inherits(App, Component)
|
||||||
@ -225,15 +225,6 @@ App.prototype.renderNetworkDropdown = function () {
|
|||||||
provider: props.provider,
|
provider: props.provider,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
h(DropMenuItem, {
|
|
||||||
label: 'Ethereum Classic Network',
|
|
||||||
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
|
|
||||||
action: () => props.dispatch(actions.setProviderType('classic')),
|
|
||||||
icon: h('.menu-icon.hollow-diamond'),
|
|
||||||
activeNetworkRender: props.network,
|
|
||||||
provider: props.provider,
|
|
||||||
}),
|
|
||||||
|
|
||||||
h(DropMenuItem, {
|
h(DropMenuItem, {
|
||||||
label: 'Morden Test Network',
|
label: 'Morden Test Network',
|
||||||
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
|
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
|
||||||
@ -366,6 +357,8 @@ App.prototype.renderPrimary = function () {
|
|||||||
|
|
||||||
case 'createVault':
|
case 'createVault':
|
||||||
return h(CreateVaultScreen, {key: 'createVault'})
|
return h(CreateVaultScreen, {key: 'createVault'})
|
||||||
|
case 'buyEth':
|
||||||
|
return h(BuyView, {key: 'buyEthView'})
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return h(AccountDetailScreen, {key: 'account-detail'})
|
return h(AccountDetailScreen, {key: 'account-detail'})
|
||||||
|
123
ui/app/components/buy-button-subview.js
Normal file
123
ui/app/components/buy-button-subview.js
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
const actions = require('../actions')
|
||||||
|
const CoinbaseForm = require('./coinbase-form')
|
||||||
|
const ShapeshiftForm = require('./shapeshift-form')
|
||||||
|
const extension = require('../../../app/scripts/lib/extension')
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps)(BuyButtonSubview)
|
||||||
|
|
||||||
|
function mapStateToProps (state) {
|
||||||
|
return {
|
||||||
|
selectedAccount: state.selectedAccount,
|
||||||
|
warning: state.appState.warning,
|
||||||
|
buyView: state.appState.buyView,
|
||||||
|
network: state.metamask.network,
|
||||||
|
provider: state.metamask.provider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(BuyButtonSubview, Component)
|
||||||
|
function BuyButtonSubview () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
BuyButtonSubview.prototype.render = function () {
|
||||||
|
const props = this.props
|
||||||
|
const currentForm = props.buyView.formView
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.buy-eth-section', [
|
||||||
|
// back button
|
||||||
|
h('.flex-row', {
|
||||||
|
style: {
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
|
||||||
|
onClick: () => props.dispatch(actions.backToAccountDetail(props.selectedAccount)),
|
||||||
|
style: {
|
||||||
|
position: 'absolute',
|
||||||
|
left: '10px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
h('h2.page-subtitle', 'Buy Eth'),
|
||||||
|
]),
|
||||||
|
h('h3.flex-row.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
paddingTop: '4px',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h(currentForm.coinbase ? '.activeForm' : '.inactiveForm', {
|
||||||
|
onClick: () => props.dispatch(actions.coinBaseSubview()),
|
||||||
|
}, 'Coinbase'),
|
||||||
|
h('a', {
|
||||||
|
onClick: (event) => this.navigateTo('https://github.com/MetaMask/faq/blob/master/COINBASE.md'),
|
||||||
|
}, [
|
||||||
|
h('i.fa.fa-question-circle', {
|
||||||
|
style: {
|
||||||
|
position: 'relative',
|
||||||
|
right: '33px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
h(currentForm.shapeshift ? '.activeForm' : '.inactiveForm', {
|
||||||
|
onClick: () => props.dispatch(actions.shapeShiftSubview(props.provider.type)),
|
||||||
|
}, 'Shapeshift'),
|
||||||
|
|
||||||
|
h('a', {
|
||||||
|
href: 'https://github.com/MetaMask/faq/blob/master/COINBASE.md',
|
||||||
|
onClick: (event) => this.navigateTo('https://info.shapeshift.io/about'),
|
||||||
|
}, [
|
||||||
|
h('i.fa.fa-question-circle', {
|
||||||
|
style: {
|
||||||
|
position: 'relative',
|
||||||
|
right: '28px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
this.formVersionSubview(),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BuyButtonSubview.prototype.formVersionSubview = function () {
|
||||||
|
if (this.props.network === '1') {
|
||||||
|
if (this.props.buyView.formView.coinbase) {
|
||||||
|
return h(CoinbaseForm, this.props)
|
||||||
|
} else if (this.props.buyView.formView.shapeshift) {
|
||||||
|
return h(ShapeshiftForm, this.props)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return h('div.flex-column', {
|
||||||
|
style: {
|
||||||
|
alignItems: 'center',
|
||||||
|
margin: '50px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('h3.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
width: '225px',
|
||||||
|
},
|
||||||
|
}, 'In order to access this feature please switch too the Main Network'),
|
||||||
|
h('h3.text-transform-uppercase', 'or:'),
|
||||||
|
this.props.network === '2' ? h('button.text-transform-uppercase', {
|
||||||
|
onClick: () => this.props.dispatch(actions.buyEth()),
|
||||||
|
style: {
|
||||||
|
marginTop: '15px',
|
||||||
|
},
|
||||||
|
}, 'Go To Test Faucet') : null,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuyButtonSubview.prototype.navigateTo = function (url) {
|
||||||
|
extension.tabs.create({ url })
|
||||||
|
}
|
162
ui/app/components/coinbase-form.js
Normal file
162
ui/app/components/coinbase-form.js
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
const actions = require('../actions')
|
||||||
|
|
||||||
|
const isValidAddress = require('../util').isValidAddress
|
||||||
|
module.exports = connect(mapStateToProps)(CoinbaseForm)
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
selectedAccount: state.selectedAccount,
|
||||||
|
warning: state.appState.warning,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(CoinbaseForm, Component)
|
||||||
|
|
||||||
|
function CoinbaseForm() {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinbaseForm.prototype.render = function () {
|
||||||
|
var props = this.props
|
||||||
|
var amount = props.buyView.amount
|
||||||
|
var address = props.buyView.buyAddress
|
||||||
|
|
||||||
|
return h('.flex-column', {
|
||||||
|
style: {
|
||||||
|
// margin: '10px',
|
||||||
|
padding: '25px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('.flex-column', {
|
||||||
|
style: {
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('.flex-row', [
|
||||||
|
h('div', 'Address:'),
|
||||||
|
h('.ellip-address', address),
|
||||||
|
]),
|
||||||
|
h('.flex-row', [
|
||||||
|
h('div', 'Amount: $'),
|
||||||
|
h('.input-container', [
|
||||||
|
h('input.buy-inputs', {
|
||||||
|
style: {
|
||||||
|
width: '3em',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
|
defaultValue: amount,
|
||||||
|
onChange: this.handleAmount.bind(this),
|
||||||
|
}),
|
||||||
|
h('i.fa.fa-pencil-square-o.edit-text', {
|
||||||
|
style: {
|
||||||
|
fontSize: '12px',
|
||||||
|
color: '#F7861C',
|
||||||
|
position: 'relative',
|
||||||
|
bottom: '5px',
|
||||||
|
right: '11px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('.info-gray', {
|
||||||
|
style: {
|
||||||
|
fontSize: '10px',
|
||||||
|
fontFamily: 'Montserrat Light',
|
||||||
|
margin: '15px',
|
||||||
|
lineHeight: '13px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
`there is a USD$ 5 a day max and a USD$ 50
|
||||||
|
dollar limit per the life time of an account without a
|
||||||
|
coinbase account. A fee of 3.75% will be aplied to debit/credit cards.`),
|
||||||
|
|
||||||
|
!props.warning ? h('div', {
|
||||||
|
style: {
|
||||||
|
width: '340px',
|
||||||
|
height: '22px',
|
||||||
|
},
|
||||||
|
}) : props.warning && h('span.error.flex-center', props.warning),
|
||||||
|
|
||||||
|
|
||||||
|
h('.flex-row', {
|
||||||
|
style: {
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
margin: '33px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('button', {
|
||||||
|
onClick: this.toCoinbase.bind(this),
|
||||||
|
}, 'Continue to Coinbase'),
|
||||||
|
|
||||||
|
h('button', {
|
||||||
|
onClick: () => props.dispatch(actions.backTobuyView(props.accounts.address)),
|
||||||
|
}, 'Cancel'),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
CoinbaseForm.prototype.handleAmount = function (event) {
|
||||||
|
this.props.dispatch(actions.updateCoinBaseAmount(event.target.value))
|
||||||
|
}
|
||||||
|
CoinbaseForm.prototype.handleAddress = function (event) {
|
||||||
|
this.props.dispatch(actions.updateBuyAddress(event.target.value))
|
||||||
|
}
|
||||||
|
CoinbaseForm.prototype.toCoinbase = function () {
|
||||||
|
var props = this.props
|
||||||
|
var amount = props.buyView.amount
|
||||||
|
var address = props.buyView.buyAddress
|
||||||
|
var message
|
||||||
|
|
||||||
|
if (isValidAddress(address) && isValidAmountforCoinBase(amount).valid) {
|
||||||
|
props.dispatch(actions.buyEth(address, props.buyView.amount))
|
||||||
|
} else if (!isValidAmountforCoinBase(amount).valid) {
|
||||||
|
message = isValidAmountforCoinBase(amount).message
|
||||||
|
return props.dispatch(actions.showWarning(message))
|
||||||
|
} else {
|
||||||
|
message = 'Receiving address is invalid.'
|
||||||
|
return props.dispatch(actions.showWarning(message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinbaseForm.prototype.renderLoading = function () {
|
||||||
|
|
||||||
|
return h('img', {
|
||||||
|
style: {
|
||||||
|
width: '27px',
|
||||||
|
marginRight: '-27px',
|
||||||
|
},
|
||||||
|
src: 'images/loading.svg',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function isValidAmountforCoinBase(amount) {
|
||||||
|
amount = parseFloat(amount)
|
||||||
|
|
||||||
|
if (amount) {
|
||||||
|
if (amount <= 5 && amount > 0) {
|
||||||
|
return {
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
} else if (amount > 5) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: 'The amount can not be greater then $5',
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: 'Can not buy amounts less then $0',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: 'The amount entered is not a number',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -41,9 +41,6 @@ DropMenuItem.prototype.activeNetworkRender = function () {
|
|||||||
case 'Main Ethereum Network':
|
case 'Main Ethereum Network':
|
||||||
if (providerType === 'mainnet') return h('.check', '✓')
|
if (providerType === 'mainnet') return h('.check', '✓')
|
||||||
break
|
break
|
||||||
case 'Ethereum Classic Network':
|
|
||||||
if (providerType === 'classic') return h('.check', '✓')
|
|
||||||
break
|
|
||||||
case 'Morden Test Network':
|
case 'Morden Test Network':
|
||||||
if (activeNetwork === '2') return h('.check', '✓')
|
if (activeNetwork === '2') return h('.check', '✓')
|
||||||
break
|
break
|
||||||
|
@ -23,7 +23,7 @@ Network.prototype.render = function () {
|
|||||||
|
|
||||||
if (networkNumber === 'loading') {
|
if (networkNumber === 'loading') {
|
||||||
|
|
||||||
return h('img', {
|
return h('img.network-indicator', {
|
||||||
title: 'Attempting to connect to blockchain.',
|
title: 'Attempting to connect to blockchain.',
|
||||||
onClick: (event) => this.props.onClick(event),
|
onClick: (event) => this.props.onClick(event),
|
||||||
style: {
|
style: {
|
||||||
@ -36,9 +36,6 @@ Network.prototype.render = function () {
|
|||||||
} else if (providerName === 'mainnet') {
|
} else if (providerName === 'mainnet') {
|
||||||
hoverText = 'Main Ethereum Network'
|
hoverText = 'Main Ethereum Network'
|
||||||
iconName = 'ethereum-network'
|
iconName = 'ethereum-network'
|
||||||
} else if (providerName === 'classic') {
|
|
||||||
hoverText = 'Ethereum Classic Network'
|
|
||||||
iconName = 'classic-network'
|
|
||||||
} else if (parseInt(networkNumber) === 2) {
|
} else if (parseInt(networkNumber) === 2) {
|
||||||
hoverText = 'Morden Test Network'
|
hoverText = 'Morden Test Network'
|
||||||
iconName = 'morden-test-network'
|
iconName = 'morden-test-network'
|
||||||
@ -66,15 +63,6 @@ Network.prototype.render = function () {
|
|||||||
}},
|
}},
|
||||||
'Etherum Main Net'),
|
'Etherum Main Net'),
|
||||||
])
|
])
|
||||||
case 'classic-network':
|
|
||||||
return h('.network-indicator', [
|
|
||||||
h('.menu-icon.hollow-diamond'),
|
|
||||||
h('.network-name', {
|
|
||||||
style: {
|
|
||||||
color: '#039396',
|
|
||||||
}},
|
|
||||||
'Etherum Classic'),
|
|
||||||
])
|
|
||||||
case 'morden-test-network':
|
case 'morden-test-network':
|
||||||
return h('.network-indicator', [
|
return h('.network-indicator', [
|
||||||
h('.menu-icon.red-dot'),
|
h('.menu-icon.red-dot'),
|
||||||
|
60
ui/app/components/qr-code.js
Normal file
60
ui/app/components/qr-code.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
const CopyButton = require('./copyButton')
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps)(QrCodeView)
|
||||||
|
|
||||||
|
function mapStateToProps (state) {
|
||||||
|
return {
|
||||||
|
Qr: state.appState.Qr,
|
||||||
|
buyView: state.appState.buyView,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(QrCodeView, Component)
|
||||||
|
|
||||||
|
function QrCodeView () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
QrCodeView.prototype.render = function () {
|
||||||
|
var props = this.props
|
||||||
|
var Qr = props.Qr
|
||||||
|
return h('.main-container.flex-column', {
|
||||||
|
style: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: '45px',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
Array.isArray(Qr.message) ? h('.message-container', this.renderMultiMessage()) : h('h3', Qr.message),
|
||||||
|
h('#qr-container.flex-column', {
|
||||||
|
key: 'qr',
|
||||||
|
style: {
|
||||||
|
marginTop: '25px',
|
||||||
|
marginBottom: '15px',
|
||||||
|
},
|
||||||
|
dangerouslySetInnerHTML: {
|
||||||
|
__html: Qr.image,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
h('.flex-row', [
|
||||||
|
h('h3.ellip-address', {
|
||||||
|
style: {
|
||||||
|
width: '247px',
|
||||||
|
},
|
||||||
|
}, Qr.data),
|
||||||
|
h(CopyButton, {
|
||||||
|
value: Qr.data,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
QrCodeView.prototype.renderMultiMessage = function () {
|
||||||
|
var Qr = this.props.Qr
|
||||||
|
var multiMessage = Qr.message.map((message) => h('.qr-message', message))
|
||||||
|
return multiMessage
|
||||||
|
}
|
311
ui/app/components/shapeshift-form.js
Normal file
311
ui/app/components/shapeshift-form.js
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
|
||||||
|
const actions = require('../actions')
|
||||||
|
const Qr = require('./qr-code')
|
||||||
|
const isValidAddress = require('../util').isValidAddress
|
||||||
|
module.exports = connect(mapStateToProps)(ShapeshiftForm)
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
selectedAccount: state.selectedAccount,
|
||||||
|
warning: state.appState.warning,
|
||||||
|
isSubLoading: state.appState.isSubLoading,
|
||||||
|
qrRequested: state.appState.qrRequested,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(ShapeshiftForm, Component)
|
||||||
|
|
||||||
|
function ShapeshiftForm () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
ShapeshiftForm.prototype.render = function () {
|
||||||
|
return h(ReactCSSTransitionGroup, {
|
||||||
|
className: 'css-transition-group',
|
||||||
|
transitionName: 'main',
|
||||||
|
transitionEnterTimeout: 300,
|
||||||
|
transitionLeaveTimeout: 300,
|
||||||
|
}, [
|
||||||
|
this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain(),
|
||||||
|
])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.renderMain = function () {
|
||||||
|
const marketinfo = this.props.buyView.formView.marketinfo
|
||||||
|
const coinOptions = this.props.buyView.formView.coinOptions
|
||||||
|
var coin = marketinfo.pair.split('_')[0].toUpperCase()
|
||||||
|
|
||||||
|
return h('.flex-column', {
|
||||||
|
style: {
|
||||||
|
// marginTop: '10px',
|
||||||
|
padding: '25px',
|
||||||
|
width: '100%',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('.flex-row', {
|
||||||
|
style: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'baseline',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('img', {
|
||||||
|
src: coinOptions[coin].image,
|
||||||
|
width: '25px',
|
||||||
|
height: '25px',
|
||||||
|
style: {
|
||||||
|
marginRight: '5px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('.input-container', [
|
||||||
|
h('input#fromCoin.buy-inputs.ex-coins', {
|
||||||
|
type: 'text',
|
||||||
|
list: 'coinList',
|
||||||
|
style: {
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
|
onChange: this.handleLiveInput.bind(this),
|
||||||
|
defaultValue: 'BTC',
|
||||||
|
}),
|
||||||
|
|
||||||
|
this.renderCoinList(),
|
||||||
|
|
||||||
|
h('i.fa.fa-pencil-square-o.edit-text', {
|
||||||
|
style: {
|
||||||
|
fontSize: '12px',
|
||||||
|
color: '#F7861C',
|
||||||
|
position: 'relative',
|
||||||
|
bottom: '48px',
|
||||||
|
left: '106px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('.icon-control', [
|
||||||
|
h('i.fa.fa-refresh.fa-4.orange', {
|
||||||
|
style: {
|
||||||
|
position: 'relative',
|
||||||
|
bottom: '5px',
|
||||||
|
left: '5px',
|
||||||
|
color: '#F7861C',
|
||||||
|
},
|
||||||
|
onClick: this.updateCoin.bind(this),
|
||||||
|
}),
|
||||||
|
h('i.fa.fa-chevron-right.fa-4.orange', {
|
||||||
|
style: {
|
||||||
|
position: 'relative',
|
||||||
|
bottom: '26px',
|
||||||
|
left: '10px',
|
||||||
|
color: '#F7861C',
|
||||||
|
},
|
||||||
|
onClick: this.updateCoin.bind(this),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('#toCoin.ex-coins', marketinfo.pair.split('_')[1].toUpperCase()),
|
||||||
|
|
||||||
|
h('img', {
|
||||||
|
src: coinOptions[marketinfo.pair.split('_')[1].toUpperCase()].image,
|
||||||
|
width: '25px',
|
||||||
|
height: '25px',
|
||||||
|
style: {
|
||||||
|
marginLeft: '5px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
|
||||||
|
this.props.isSubLoading ? this.renderLoading() : null,
|
||||||
|
h('.flex-column', {
|
||||||
|
style: {
|
||||||
|
width: '235px',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
this.props.warning ? this.props.warning && h('span.error.flex-center', {
|
||||||
|
style: {
|
||||||
|
textAlign: 'center',
|
||||||
|
width: '229px',
|
||||||
|
height: '82px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
this.props.warning) : this.renderInfo(),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('.flex-row', {
|
||||||
|
style: {
|
||||||
|
padding: '10px',
|
||||||
|
paddingBottom: '2px',
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('div', 'Receiving address:'),
|
||||||
|
h('.ellip-address', this.props.buyView.buyAddress),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h(this.activeToggle('.input-container'), {
|
||||||
|
style: {
|
||||||
|
padding: '10px',
|
||||||
|
paddingTop: '0px',
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('div', `${coin} Address:`),
|
||||||
|
|
||||||
|
h('input#fromCoinAddress.buy-inputs', {
|
||||||
|
type: 'text',
|
||||||
|
placeholder: `Your ${coin} Refund Address`,
|
||||||
|
style: {
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
width: '278px',
|
||||||
|
height: '20px',
|
||||||
|
padding: ' 5px ',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('i.fa.fa-pencil-square-o.edit-text', {
|
||||||
|
style: {
|
||||||
|
fontSize: '12px',
|
||||||
|
color: '#F7861C',
|
||||||
|
position: 'relative',
|
||||||
|
bottom: '5px',
|
||||||
|
right: '11px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
h('.flex-row', {
|
||||||
|
style: {
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('button', {
|
||||||
|
onClick: this.shift.bind(this),
|
||||||
|
style: {
|
||||||
|
marginTop: '10px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'Submit'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.shift = function () {
|
||||||
|
var props = this.props
|
||||||
|
var withdrawal = this.props.buyView.buyAddress
|
||||||
|
var returnAddress = document.getElementById('fromCoinAddress').value
|
||||||
|
var pair = this.props.buyView.formView.marketinfo.pair
|
||||||
|
var data = {
|
||||||
|
'withdrawal': withdrawal,
|
||||||
|
'pair': pair,
|
||||||
|
'returnAddress': returnAddress,
|
||||||
|
}
|
||||||
|
var message = [
|
||||||
|
`Deposit Limit: ${props.buyView.formView.marketinfo.limit}`,
|
||||||
|
`Deposit Minimum:${props.buyView.formView.marketinfo.minimum}`,
|
||||||
|
]
|
||||||
|
if (isValidAddress(withdrawal)) {
|
||||||
|
this.props.dispatch(actions.coinShiftRquest(data, message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.renderCoinList = function () {
|
||||||
|
var list = Object.keys(this.props.buyView.formView.coinOptions).map((item) => {
|
||||||
|
return h('option', {
|
||||||
|
value: item,
|
||||||
|
}, item)
|
||||||
|
})
|
||||||
|
|
||||||
|
return h('datalist#coinList', {
|
||||||
|
onClick: (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
},
|
||||||
|
}, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.updateCoin = function (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const props = this.props
|
||||||
|
var coinOptions = this.props.buyView.formView.coinOptions
|
||||||
|
var coin = document.getElementById('fromCoin').value
|
||||||
|
|
||||||
|
if (!coinOptions[coin.toUpperCase()] || coin.toUpperCase() === 'ETH') {
|
||||||
|
var message = 'Not a valid coin'
|
||||||
|
return props.dispatch(actions.showWarning(message))
|
||||||
|
} else {
|
||||||
|
return props.dispatch(actions.pairUpdate(coin))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.handleLiveInput = function () {
|
||||||
|
const props = this.props
|
||||||
|
var coinOptions = this.props.buyView.formView.coinOptions
|
||||||
|
var coin = document.getElementById('fromCoin').value
|
||||||
|
|
||||||
|
if (!coinOptions[coin.toUpperCase()] || coin.toUpperCase() === 'ETH') {
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
return props.dispatch(actions.pairUpdate(coin))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.renderInfo = function () {
|
||||||
|
const marketinfo = this.props.buyView.formView.marketinfo
|
||||||
|
const coinOptions = this.props.buyView.formView.coinOptions
|
||||||
|
var coin = marketinfo.pair.split('_')[0].toUpperCase()
|
||||||
|
|
||||||
|
return h('span', {
|
||||||
|
style: {
|
||||||
|
marginTop: '15px',
|
||||||
|
marginBottom: '15px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('h3.flex-row.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
color: '#AEAEAE',
|
||||||
|
paddingTop: '4px',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: '14px',
|
||||||
|
},
|
||||||
|
}, `Market Info for ${marketinfo.pair.replace('_', ' to ').toUpperCase()}:`),
|
||||||
|
h('.marketinfo', ['Status : ', `${coinOptions[coin].status}`]),
|
||||||
|
h('.marketinfo', ['Exchange Rate: ', `${marketinfo.rate}`]),
|
||||||
|
h('.marketinfo', ['Limit: ', `${marketinfo.limit}`]),
|
||||||
|
h('.marketinfo', ['Minimum : ', `${marketinfo.minimum}`]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.handleAddress = function (event) {
|
||||||
|
this.props.dispatch(actions.updateBuyAddress(event.target.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.activeToggle = function (elementType) {
|
||||||
|
if (!this.props.buyView.formView.response || this.props.warning) return elementType
|
||||||
|
return `${elementType}.inactive`
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeshiftForm.prototype.renderLoading = function () {
|
||||||
|
return h('span', {
|
||||||
|
style: {
|
||||||
|
position: 'absolute',
|
||||||
|
left: '70px',
|
||||||
|
bottom: '194px',
|
||||||
|
background: 'transparent',
|
||||||
|
width: '229px',
|
||||||
|
height: '82px',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('img', {
|
||||||
|
style: {
|
||||||
|
width: '60px',
|
||||||
|
},
|
||||||
|
src: 'images/loading.svg',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
@ -471,3 +471,124 @@ input.large-input {
|
|||||||
.eth-warning{
|
.eth-warning{
|
||||||
transition: opacity 400ms ease-in, transform 400ms ease-in;
|
transition: opacity 400ms ease-in, transform 400ms ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.buy-subview{
|
||||||
|
transition: opacity 400ms ease-in, transform 400ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-container:hover .edit-text{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buy-inputs{
|
||||||
|
font-family: 'Montserrat Light';
|
||||||
|
font-size: 13px;
|
||||||
|
height: 20px;
|
||||||
|
background: transparent;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: solid;
|
||||||
|
border-color: transparent;
|
||||||
|
border-width: 0.5px;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.input-container:hover .buy-inputs{
|
||||||
|
box-sizing: inherit;
|
||||||
|
border: solid;
|
||||||
|
border-color: #F7861C;
|
||||||
|
border-width: 0.5px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buy-inputs:focus{
|
||||||
|
border: solid;
|
||||||
|
border-color: #F7861C;
|
||||||
|
border-width: 0.5px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeForm {
|
||||||
|
background: #F7F7F7;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px 8px 0px 0px;
|
||||||
|
width: 50%;
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.inactiveForm {
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px 8px 0px 0px;
|
||||||
|
width: 50%;
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ex-coins {
|
||||||
|
font-family: 'Montserrat Regular';
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 33px;
|
||||||
|
width: 118px;
|
||||||
|
height: 42px;
|
||||||
|
padding: 1px;
|
||||||
|
color: #4D4D4D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marketinfo{
|
||||||
|
font-family: 'Montserrat light';
|
||||||
|
color: #AEAEAE;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fromCoin::-webkit-calendar-picker-indicator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#coinList {
|
||||||
|
width: 400px;
|
||||||
|
height: 500px;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-control .fa-refresh{
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-control:hover .fa-refresh{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-control:hover .fa-chevron-right{
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inactive {
|
||||||
|
color: #AEAEAE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inactive button{
|
||||||
|
background: #AEAEAE;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ellip-address {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 5em;
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: "Montserrat Light";
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-message {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #F7861C;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.message-container > div:first-child {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #4D4D4D;
|
||||||
|
}
|
||||||
|
@ -35,9 +35,10 @@ EthStoreWarning.prototype.render = function () {
|
|||||||
margin: '10px 10px 10px 10px',
|
margin: '10px 10px 10px 10px',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
`MetaMask is currently in beta -
|
`The MetaMask team would like to
|
||||||
exercise caution while handling
|
remind you that MetaMask is currently in beta - so
|
||||||
and storing your ether.
|
don't store large
|
||||||
|
amounts of ether in MetaMask.
|
||||||
`),
|
`),
|
||||||
|
|
||||||
h('i.fa.fa-exclamation-triangle.fa-4', {
|
h('i.fa.fa-exclamation-triangle.fa-4', {
|
||||||
|
@ -317,6 +317,15 @@ function reduceApp (state, action) {
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
case actions.SHOW_SUB_LOADING_INDICATION:
|
||||||
|
return extend(appState, {
|
||||||
|
isSubLoading: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.HIDE_SUB_LOADING_INDICATION:
|
||||||
|
return extend(appState, {
|
||||||
|
isSubLoading: false,
|
||||||
|
})
|
||||||
case actions.CLEAR_SEED_WORD_CACHE:
|
case actions.CLEAR_SEED_WORD_CACHE:
|
||||||
return extend(appState, {
|
return extend(appState, {
|
||||||
transForward: true,
|
transForward: true,
|
||||||
@ -369,15 +378,102 @@ function reduceApp (state, action) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
case actions.SHOW_ETH_WARNING:
|
case actions.BUY_ETH_VIEW:
|
||||||
return extend(appState, {
|
return extend(appState, {
|
||||||
transForward: true,
|
transForward: true,
|
||||||
currentView: {
|
currentView: {
|
||||||
name: 'accountDetail',
|
name: 'buyEth',
|
||||||
context: appState.currentView.context,
|
context: appState.currentView.context,
|
||||||
},
|
},
|
||||||
accountDetail: {
|
buyView: {
|
||||||
subview: 'buy-eth-warning',
|
subview: 'buyForm',
|
||||||
|
amount: '5.00',
|
||||||
|
buyAddress: action.value,
|
||||||
|
formView: {
|
||||||
|
coinbase: true,
|
||||||
|
shapeshift: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.UPDATE_BUY_ADDRESS:
|
||||||
|
return extend(appState, {
|
||||||
|
buyView: {
|
||||||
|
subview: 'buyForm',
|
||||||
|
formView: {
|
||||||
|
coinbase: appState.buyView.formView.coinbase,
|
||||||
|
shapeshift: appState.buyView.formView.shapeshift,
|
||||||
|
},
|
||||||
|
buyAddress: action.value,
|
||||||
|
amount: appState.buyView.amount,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.UPDATE_COINBASE_AMOUNT:
|
||||||
|
return extend(appState, {
|
||||||
|
buyView: {
|
||||||
|
subview: 'buyForm',
|
||||||
|
formView: {
|
||||||
|
coinbase: true,
|
||||||
|
shapeshift: false,
|
||||||
|
},
|
||||||
|
buyAddress: appState.buyView.buyAddress,
|
||||||
|
amount: action.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.COINBASE_SUBVIEW:
|
||||||
|
return extend(appState, {
|
||||||
|
buyView: {
|
||||||
|
subview: 'buyForm',
|
||||||
|
formView: {
|
||||||
|
coinbase: true,
|
||||||
|
shapeshift: false,
|
||||||
|
},
|
||||||
|
buyAddress: appState.buyView.buyAddress,
|
||||||
|
amount: appState.buyView.amount,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.SHAPESHIFT_SUBVIEW:
|
||||||
|
return extend(appState, {
|
||||||
|
buyView: {
|
||||||
|
subview: 'buyForm',
|
||||||
|
formView: {
|
||||||
|
coinbase: false,
|
||||||
|
shapeshift: true,
|
||||||
|
marketinfo: action.value.marketinfo,
|
||||||
|
coinOptions: action.value.coinOptions,
|
||||||
|
},
|
||||||
|
buyAddress: appState.buyView.buyAddress,
|
||||||
|
amount: appState.buyView.amount,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.PAIR_UPDATE:
|
||||||
|
return extend(appState, {
|
||||||
|
buyView: {
|
||||||
|
subview: 'buyForm',
|
||||||
|
formView: {
|
||||||
|
coinbase: false,
|
||||||
|
shapeshift: true,
|
||||||
|
marketinfo: action.value.marketinfo,
|
||||||
|
coinOptions: appState.buyView.formView.coinOptions,
|
||||||
|
},
|
||||||
|
buyAddress: appState.buyView.buyAddress,
|
||||||
|
amount: appState.buyView.amount,
|
||||||
|
warning: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.SHOW_QR:
|
||||||
|
return extend(appState, {
|
||||||
|
qrRequested: true,
|
||||||
|
transForward: true,
|
||||||
|
Qr: {
|
||||||
|
message: action.value.message,
|
||||||
|
image: action.value.qr,
|
||||||
|
data: action.value.data,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
|
@ -10,6 +10,7 @@ function reduceMetamask (state, action) {
|
|||||||
var metamaskState = extend({
|
var metamaskState = extend({
|
||||||
isInitialized: false,
|
isInitialized: false,
|
||||||
isUnlocked: false,
|
isUnlocked: false,
|
||||||
|
isEthConfirmed: false,
|
||||||
currentDomain: 'example.com',
|
currentDomain: 'example.com',
|
||||||
rpcTarget: 'https://rawtestrpc.metamask.io/',
|
rpcTarget: 'https://rawtestrpc.metamask.io/',
|
||||||
identities: {},
|
identities: {},
|
||||||
@ -36,7 +37,7 @@ function reduceMetamask (state, action) {
|
|||||||
|
|
||||||
case actions.AGREE_TO_ETH_WARNING:
|
case actions.AGREE_TO_ETH_WARNING:
|
||||||
return extend(metamaskState, {
|
return extend(metamaskState, {
|
||||||
isEthConfirmed: true,
|
isEthConfirmed: !metamaskState.isEthConfirmed,
|
||||||
})
|
})
|
||||||
|
|
||||||
case actions.UNLOCK_METAMASK:
|
case actions.UNLOCK_METAMASK:
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
const createStore = require('redux').createStore
|
const createStore = require('redux').createStore
|
||||||
const applyMiddleware = require('redux').applyMiddleware
|
const applyMiddleware = require('redux').applyMiddleware
|
||||||
const thunkMiddleware = require('redux-thunk')
|
const thunkMiddleware = require('redux-thunk')
|
||||||
const createLogger = require('redux-logger')
|
|
||||||
const rootReducer = require('./reducers')
|
const rootReducer = require('./reducers')
|
||||||
|
const createLogger = require('redux-logger')
|
||||||
|
|
||||||
|
global.METAMASK_DEBUG = false
|
||||||
|
|
||||||
module.exports = configureStore
|
module.exports = configureStore
|
||||||
|
|
||||||
const loggerMiddleware = createLogger()
|
const loggerMiddleware = createLogger({
|
||||||
|
predicate: () => global.METAMASK_DEBUG,
|
||||||
|
})
|
||||||
|
|
||||||
const createStoreWithMiddleware = applyMiddleware(
|
const middlewares = [thunkMiddleware, loggerMiddleware]
|
||||||
thunkMiddleware,
|
|
||||||
loggerMiddleware
|
const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore)
|
||||||
)(createStore)
|
|
||||||
|
|
||||||
function configureStore (initialState) {
|
function configureStore (initialState) {
|
||||||
return createStoreWithMiddleware(rootReducer, initialState)
|
return createStoreWithMiddleware(rootReducer, initialState)
|
||||||
|
Loading…
Reference in New Issue
Block a user