Commit 82b4e93f authored by Bitcoin Please's avatar Bitcoin Please

Refactored `wallet` to individual `accounts` and `coins`.

parent 672bad47
......@@ -49,11 +49,13 @@ import { mapActions, mapGetters } from 'vuex'
import Email from './SigninEmail'
import Extensions from './SigninExtensions'
import Ledger from './SigninLedger'
import scrypt from 'scrypt-js'
import superagent from 'superagent'
import Swal from 'sweetalert2'
/* Import JQuery. */
// FIXME: Remove ALL jQuery dependencies.
const $ = window.jQuery
// const $ = window.jQuery
export default {
components: {
......@@ -69,6 +71,7 @@ export default {
computed: {
...mapGetters('profile', [
'getNickname',
'getSignedMessage',
]),
/**
......@@ -87,12 +90,142 @@ export default {
methods: {
...mapActions('profile', [
'destroyProfile',
'updateEmail',
'updateMasterSeed',
'updateNickname',
]),
...mapActions('utils', [
'toast',
]),
...mapActions('wallet', [
'initWallet',
]),
/**
* Is Email (Address) Valid
*/
isValidEmail(_email) {
/* Set regular express. */
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
/* Return test result. */
return re.test(_email)
},
/**
* Authorization
*/
async _authorize(_email, _password) {
/* Validate email. */
if (!this.isValidEmail(_email)) {
// this.toast(['Oops!', 'Invalid email. Please try again.', 'error'])
Swal.showValidationMessage(
`Invalid email. Please try again.`
)
return false
}
/* Validate password. */
// TODO: Improve "strong" password validation.
if (!_password) {
// this.toast(['Oops!', 'Invalid password. Please try again.', 'error'])
Swal.showValidationMessage(
`Invalid password. Please try again.`
)
return false
}
/* Disable sign in button. */
// this.canSignIn = false
// FIXME: We MUST check and update system.authHashes, if necessary.
/* Set password. */
const password = Buffer.from(_password.normalize('NFKC'))
/* Set salt (email address). */
const salt = Buffer.from(_email.normalize('NFKC'))
/* Set CPU (memory) cost. */
// NOTE: increasing this increases the overall difficulty.
// TODO: Test params on mobile devices (scale back, if necessary).
// const N = 16384 // 2^14 (original recommendation)
// const N = 32768 // 2^15 (safe recommendation)
const N = 65536 // 2^16 (JS-native recommendation)
// const N = 1048576 // 2^20 (optimal recommendation)
/* Set block size. */
// NOTE: Increasing this increases the dependency on memory
// latency and bandwidth.
const r = 8
/* Set parallelization cost. */
// NOTE: Increasing this increases the dependency on
// multi-processing.
const p = 1
/* Set derived key length (in bytes). */
const dkLen = 32
/* Compute key. */
const key = await scrypt
.scrypt(password, salt, N, r, p, dkLen)
/* Update master seed. */
this.updateMasterSeed(key)
/* Update email address. */
this.updateEmail(_email)
/* Set nickname. */
const nickname = _email.slice(0, _email.indexOf('@'))
/* Update nickname. */
this.updateNickname(nickname)
/* Initialize wallet. */
this.initWallet()
/* Set (current receiving) address. */
// const address = this.getAddress
// console.log('ADDRESS', address)
/* Enable sign in button. */
// this.canSignIn = true
/* Close modal. */
// $('.form-signin').fadeToggle()
// $('#signinForm').fadeToggle()
/* Set target. */
const target = 'https://api.causes.cash/v1/profiles'
const msg = {
action: 'SIGNIN_EMAIL',
email: _email,
}
/* Calculate auth signature. */
const signedMessage = this.getSignedMessage(JSON.stringify(msg))
console.log('SIGNED MESSAGE', signedMessage)
superagent
.post(target)
.send(signedMessage)
.end((err, res) => {
if (err) return console.error(err) // eslint-disable-line no-console
console.log('SIGN IN (response):', res)
})
return true
},
/**
* Sign In
*/
......@@ -100,24 +233,24 @@ export default {
// $('.form-signin').fadeToggle()
// $('#signinForm').fadeToggle()
const { value: formValues } = await Swal.fire({
title: 'Multiple inputs',
// const { value: formValues } = await Swal.fire({
await Swal.fire({
title: 'Sign In to Causes Cash',
html:
'<input id="swal-input1" class="swal2-input">' +
'<input id="swal-input2" class="swal2-input">',
`<input type="email" id="swal-email" class="swal2-input" placeholder="Enter your email">` +
`<input type="password" id="swal-password" class="swal2-input" placeholder="Enter your password">`,
focusConfirm: false,
preConfirm: () => {
return [
document.getElementById('swal-input1').value,
document.getElementById('swal-input2').value
]
preConfirm: async () => {
const email = document.getElementById('swal-email').value
const password = document.getElementById('swal-password').value
const isAuthorized = await this._authorize(email, password)
console.log('isAuthorized', isAuthorized)
// Swal.enableButtons()
// throw new Error('maybe try again?')
return isAuthorized
}
})
if (formValues) {
Swal.fire(JSON.stringify(formValues))
}
},
/**
......@@ -140,12 +273,12 @@ export default {
//
},
mounted: function () {
$('.form-signin').on('click', function (e) {
e.preventDefault()
$(this).fadeToggle()
$(this).parent().find('#signinForm').fadeToggle()
})
// $('.form-signin').on('click', function (e) {
// e.preventDefault()
//
// $(this).fadeToggle()
// $(this).parent().find('#signinForm').fadeToggle()
// })
},
}
</script>
......
......@@ -5,10 +5,10 @@ import superagent from 'superagent'
* Add Payout
*/
const addPayout = async ({ rootGetters }, _payout) => {
// console.log('ADD PAYOUT:', _payout)
console.log('ADD PAYOUT:', _payout)
const signedPkg = rootGetters['profile/getSignedMessage'](JSON.stringify(_payout))
// console.log('SIGNED PACKAGE', signedPkg)
console.log('SIGNED PACKAGE', signedPkg)
/* Set api target. */
const target = 'http://localhost:6767/v1/payouts'
......@@ -17,7 +17,7 @@ const addPayout = async ({ rootGetters }, _payout) => {
const result = await superagent
.post(target)
.send(signedPkg)
// console.log('RESULT', result)
console.log('RESULT', result)
/* Return result. */
return result
......
......@@ -6,22 +6,20 @@ import Nito from 'nitojs'
* Get Signed Message
*/
const getSignedMessage = (state, getters, rootState, rootGetters) => (_message) => {
console.log('DEBUG', _message)
/* Validate message. */
if (!_message || !(typeof _message === 'string')) {
throw new Error('Signed message MUST be a string.')
}
/* Validate wallet. */
if (!rootGetters['wallet/getWallet']) {
console.log('ROOT GETTERS', rootGetters['wallet/getAccounts'])
/* Validate accounts. */
if (!rootGetters['wallet/getAccounts']) {
return null
}
/* Initialize wallet. */
const wallet = rootGetters['wallet/getWallet']
// console.log('GET ADDRESS (wallet):', wallet)
/* Set accounts. */
const accounts = wallet.accounts
/* Request accounts. */
const accounts = rootGetters['wallet/getAccounts']
/* Validate accounts. */
if (!accounts) {
......@@ -30,14 +28,12 @@ const getSignedMessage = (state, getters, rootState, rootGetters) => (_message)
/* Set profile index. */
const profileIndex = 0
// console.log('GET ADDRESS (profileIndex):', profileIndex)
/* Set chain. */
const chain = 0 // receiving account
/* Set derivation path. */
const path = rootGetters['wallet/getDerivationPath'](chain, profileIndex)
// console.log('GET ADDRESS (path)', path)
/* Initialize HD node. */
const hdNode = rootGetters['wallet/getHDNode']
......@@ -47,15 +43,12 @@ const getSignedMessage = (state, getters, rootState, rootGetters) => (_message)
/* Set (profile) address. */
const address = Nito.Address.toCashAddress(childNode)
// console.log('GET SIGNED MESSAGE (address):', address)
/* Set WIF. */
const wif = childNode.privateKey.toWIF()
// console.log('GET SIGNED MESSAGE (wif):', wif)
/* Set nonce. */
const nonce = moment().unix()
// console.log('NONCE', nonce)
/* Request signature. */
const signature = Nito.Message.sign(`${_message}:${nonce}`, wif)
......
......@@ -6,48 +6,60 @@
const addCoin = ({ commit, getters }, _pkg) => {
console.info('Adding new coin...', _pkg) // eslint-disable-line no-console
/* Set chain id. */
const chainId = _pkg.chainId
// console.log('ADD NEW COIN (chainid):', chainId)
/* Set coin. */
const coin = _pkg.coin
// console.log('ADD NEW COIN (coin):', coin)
/* Set wallet. */
const wallet = getters.getWallet
// console.log('ADD NEW COIN (wallet):', wallet)
/* Request accounts. */
const accounts = getters.getAccounts
// console.log('ADD NEW COIN (accounts):', accounts)
/* Validate wallet. */
if (!wallet) {
/* Validate accounts. */
if (!accounts) {
return
}
/* Add coin to wallet. */
wallet.coins[`${coin.txid}:${coin.vout}`] = coin
/* Set chain id. */
const chainId = _pkg.chainId
// console.log('ADD NEW COIN (chainid):', chainId)
/* Increment deposit account. */
switch(chainId) {
case 0:
/* Increment deposit index. */
wallet.accounts.deposit++
accounts.deposit++
break
case 1:
/* Increment change index. */
wallet.accounts.change++
accounts.change++
break
case 6767:
/* Increment causes index. */
wallet.accounts.causes++
accounts.causes++
break
case 7867:
/* Increment nito index. */
wallet.accounts.nito++
accounts.nito++
break
}
/* Commit updated wallet`. */
commit('setWallet', wallet)
/* Request coins. */
const coins = getters.getCoins
// console.log('ADD NEW COIN (coins):', coins)
/* Validate coins. */
if (!coins) {
return
}
/* Set coin. */
const coin = _pkg.coin
// console.log('ADD NEW COIN (coin):', coin)
/* Add coin to wallet. */
coins[`${coin.txid}:${coin.vout}`] = coin
/* Commit updated accounts`. */
commit('setAccounts', accounts)
/* Commit updated coins`. */
commit('setCoins', coins)
}
/* Export module. */
......
......@@ -22,8 +22,11 @@ const initWallet = ({ commit }) => {
nito: 0,
}
/* Commit accounts. */
commit('setAccounts', accountsModel)
/**
* Wallet Model
* Coins Model
*
* Coins are (UTXO) objects containing:
* - txid
......@@ -43,13 +46,10 @@ const initWallet = ({ commit }) => {
* NOTE: Reserved paths are used to "freeze" coins, for use with
* assurance contracts.
*/
const walletModel = {
accounts: accountsModel,
coins: {},
}
const coinsModel = {}
/* Commit wallet. */
commit('setWallet', walletModel)
/* Commit coins. */
commit('setCoins', coinsModel)
/* Return success. */
return true
......
......@@ -6,20 +6,20 @@
const updateCoin = ({ commit, getters }, _coin) => {
console.info('Updating coin...', _coin) // eslint-disable-line no-console
/* Set wallet. */
const wallet = getters.getWallet
// console.log('UPDATE COIN (wallet):', wallet)
/* Request coins. */
const coins = getters.getCoins
// console.log('UPDATE COIN (coins):', coins)
/* Validate wallet. */
if (!wallet) {
/* Validate coins. */
if (!coins) {
return
}
/* Add coin to session. */
wallet.coins[`${_coin.txid}:${_coin.vout}`] = _coin
coins[`${_coin.txid}:${_coin.vout}`] = _coin
/* Commit updated wallet. */
commit('setWallet', wallet)
commit('setCoins', coins)
}
/* Export module. */
......
......@@ -60,19 +60,15 @@ const updateStatus = (_coins, _meta, dispatch) => {
* Update Coins (for ALL sessions)
*/
const updateCoins = async ({ dispatch, getters, rootGetters }) => {
/* Set wallet. */
const wallet = getters.getWallet
// console.log('UPDATE COINS (wallet)', wallet)
/* Set coins. */
const coins = getters.getCoins
// console.log('UPDATE COINS (coins)', coins)
/* Validate wallet. */
if (!wallet || !wallet.coins) {
/* Validate coins. */
if (!coins) {
return
}
/* Set coins. */
const coins = wallet.coins
// console.log('UPDATE COINS (coins)', coins)
/* Retrieve metadata. */
const meta = await rootGetters['profile/getMeta']
console.log('UPDATE COINS (meta):', meta)
......
......@@ -7,23 +7,15 @@ import Nito from 'nitojs'
* Returns the next avaialble "receiving" address.
*/
const getAddress = (state, getters) => (_account) => {
/* Validate wallet. */
if (!getters.getWallet) {
return null
}
/* Initialize wallet. */
const wallet = getters.getWallet
// console.log('GET ADDRESS (wallet):', wallet)
/* Set accounts. */
const accounts = wallet.accounts
/* Validate accounts. */
if (!accounts) {
if (!getters.getAccounts) {
return null
}
/* Request accounts. */
const accounts = getters.getAccounts
// console.log('GET ADDRESS (accounts):', accounts)
/* Initialize current (coin) index. */
const currentIndex = accounts[_account]
// console.log('GET ADDRESS (currentIndex):', currentIndex)
......
......@@ -175,11 +175,12 @@ export default {
]),
...mapGetters('wallet', [
'getAccounts',
'getAddress',
'getBalance',
'getCoins',
'getDerivationPath',
'getHDNode',
'getWallet',
]),
/**
......@@ -473,32 +474,28 @@ export default {
* Transfers the pledge amount into a dedicated UTXO.
*/
async confirmFlipstarter() {
/* Initialize wallet. */
const wallet = this.getWallet
// console.log('WALLET', wallet)
/* Initialize meta. */
const meta = await this.getMeta
console.log('META', meta)
/* Set accounts. */
const accounts = wallet.accounts
/* Request accounts. */
const accounts = this.getAccounts
console.log('ACCOUNTS', accounts)
/* Set coins. */
const coins = wallet.coins
console.log('COINS', coins)
/* Validate accounts. */
if (!accounts) {
return null
}
/* Request coins. */
const coins = this.getCoins
console.log('COINS', coins)
/* Validate coins. */
if (!coins) {
return null
}
/* Request metadata. */
const meta = await this.getMeta
console.log('META', meta)
const spendable = Object.keys(coins).filter(coinid => {
return coins[coinid].status === 'active'
})
......
......@@ -229,8 +229,8 @@ export default {
...mapGetters('wallet', [
'getAddress',
'getBalance',
'getCoins',
'getMnemonic',
'getWallet',
]),
balanceDisplay() {
......@@ -255,10 +255,10 @@ export default {
/* Set table data. */
const tableData = []
/* Validate wallet. */
if (this.getWallet) {
/* Validate coins. */
if (this.getCoins) {
/* Initialize coins. */
const coins = this.getWallet.coins
const coins = this.getCoins
console.log('COINS TABLE (coins):', coins)
Object.keys(coins).forEach(async coinId => {
......@@ -402,6 +402,7 @@ export default {
},
addressDisplay(_type) {
console.log('this.getAddress(_type)', _type, this.getAddress(_type))
if (this.getAddress(_type).indexOf('bitcoincash:') !== -1) {
return this.getAddress(_type).slice(12)
} else {
......@@ -429,10 +430,10 @@ export default {
/* Initialize wallet balance. */
let balance = 0
/* Validate wallet. */
if (this.getWallet) {
/* Validate coins. */
if (this.getCoins) {
/* Initialize coins. */
const coins = this.getWallet.coins
const coins = this.getCoins
Object.keys(coins).forEach(async coinId => {
/* Initialize coin. */
......@@ -568,7 +569,7 @@ export default {