Commit a53c0cb7 authored by Bitcoin Please's avatar Bitcoin Please
Browse files

Enabled coin updates.

parent e1dec817
/* Import modules (getters). */
import getAccounts from './wallet/getters/getAccounts'
import getAddress from './wallet/getters/getAddress'
import getBalance from './wallet/getters/getBalance'
import getChangeAddress from './wallet/getters/getChangeAddress'
......@@ -11,9 +12,13 @@ import getMnemonic from './wallet/getters/getMnemonic'
import getWallet from './wallet/getters/getWallet'
/* Import modules (actions). */
import addCoin from './wallet/actions/addCoin'
import destroyWallet from './wallet/actions/destroyWallet'
import initWallet from './wallet/actions/initWallet'
import updateWallet from './wallet/actions/updateWallet'
import updateCoin from './wallet/actions/updateCoin'
import updateCoins from './wallet/actions/updateCoins'
import updateMeta from './wallet/actions/updateMeta'
import updateOutbox from './wallet/actions/updateOutbox'
/* Import modules (mutations). */
import setEmptyWallet from './wallet/mutations/setEmptyWallet'
......@@ -38,6 +43,11 @@ const state = {
*/
meta: null,
/**
* Coins waiting to be sent out from the wallet.
*/
outbox: null,
/**
* Wallet Accounts
*
......@@ -55,6 +65,7 @@ const state = {
/* Getters. */
const getters = {
getAccounts,
getAddress,
getBalance,
getChangeAddress,
......@@ -69,9 +80,13 @@ const getters = {
/* Actions. */
const actions = {
addCoin,
destroyWallet,
initWallet,
updateWallet,
updateCoin,
updateCoins,
updateMeta,
updateOutbox,
}
/* Mutations. */
......
/**
* Add Coin
*
* Adds new coin details to its respective session.
*/
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)
/* Validate wallet. */
if (!wallet) {
return
}
/* Add coin to wallet. */
wallet.coins[`${coin.txid}:${coin.vout}`] = coin
/* Increment deposit account. */
switch(chainId) {
case 0:
/* Increment deposit index. */
wallet.accounts.deposit++
break
case 1:
/* Increment change index. */
wallet.accounts.change++
break
case 6767:
/* Increment causes index. */
wallet.accounts.causes++
break
case 7867:
/* Increment nito index. */
wallet.accounts.nito++
break
}
/* Commit updated wallet`. */
commit('setWallet', wallet)
}
/* Export module. */
export default addCoin
......@@ -13,14 +13,16 @@ const initWallet = ({ commit }) => {
* Manages the indexes of account (addresses) and their respective
* derivation paths.
*
* Deposit : m/44'/145'/0'/0/<index>
* Change : m/44'/145'/0'/1/<index>
* Causes : m/44'/145'/0'/6767/<index>
* Deposit : m/44'/145'/0'/0/<index>
* Change : m/44'/145'/0'/1/<index>
* Causes Cash : m/44'/145'/0'/6767/<index>
* Nito Cash : m/44'/145'/0'/7867/<index>
*/
const accountsModel = {
deposit: 0,
change: 0,
causes: 0,
nito: 0,
}
/**
......
/**
* Update Coin
*
* Updates the status of a coin in its respective session.
*/
const updateCoin = ({ commit, getters }, _pkg) => {
console.info('Updating coin...', _pkg) // eslint-disable-line no-console
/* Set session id. */
const sessionId = _pkg.sessionId
console.log('UPDATE COIN (sessionid):', sessionId)
/* Set coin. */
const coin = _pkg.coin
console.log('UPDATE COIN (coin):', coin)
/* Set sessions. */
const sessions = getters.getSessions
console.log('UPDATE COIN (sessions):', sessions)
/* Validate session id. */
if (!sessions[sessionId]) {
return
}
/* Add coin to session. */
sessions[sessionId].coins[`${coin.txid}:${coin.vout}`] = coin
/* Commit updated sessions. */
commit('setSessions', sessions)
}
/* Export module. */
export default updateCoin
/* Import components. */
const Nito = require('nitojs')
/**
* Update Status
*/
const updateStatus = (_coins, dispatch) => {
Object.keys(_coins).forEach(async coinId => {
/* Set txid. */
const txid = coinId.split(':')[0]
// console.log('UPDATE STATUS (txid)', txid)
/* Set vout. */
const vout = coinId.split(':')[1]
// console.log('UPDATE STATUS (vout)', vout)
/* Query spent status. */
const isSpent = await Nito.Blockchain.Query.isSpent(txid, vout)
// console.log('UPDATE STATUS (isSpent)', isSpent, txid, vout)
/* Validate spent. */
if (isSpent) {
/* Set coin. */
const coin = _coins[coinId]
/* Validate status. */
if (coin && coin.status !== 'disabled') {
/* Set status. */
coin.status = 'disabled'
/* Request coin update. */
dispatch('updateCoin', coin)
}
}
})
}
/**
* Update Coins (for ALL sessions)
*/
const updateCoins = async ({ dispatch, getters }) => {
/* Set wallet. */
const wallet = getters.getWallet
console.log('UPDATE COINS (wallet)', wallet)
/* Validate wallet. */
if (!wallet || !wallet.coins) {
return
}
/* Set coins. */
const coins = wallet.coins
console.log('UPDATE COINS (coins)', coins)
/* Update status. */
updateStatus(coins, dispatch)
/* Retrieve accounts. */
const accounts = getters.getAccounts
console.log('UPDATE COINS (accounts)', accounts)
/* Validate accounts. */
if (accounts === null) {
return
}
/* Build search array. */
const addresses = accounts.map(obj => {
return obj.address
})
console.log('UPDATE COINS (addresses)', addresses)
/* Initialize search details. */
const searchDetails = []
/* Compile addresses. */
// FIXME: We do not use for-each with callback here because of async.
for (let i = 0; i < addresses.length; i++) {
const address = addresses[i]
/* Retrieve address details. */
const details = await Nito.Address.details(address)
// console.log('UPDATE COINS (address details)', details)
/* Validate details. */
if (!details) {
return
}
/* Map transactions. */
const transactions = details.map(detail => {
return detail.tx_hash
})
// console.log('UPDATE COINS (transactions)', transactions)
searchDetails.push({
transactions,
legacyAddress: Nito.Address.toLegacyAddress(address),
cashAddress: address,
})
// console.log('UPDATE COINS (searchDetails)', searchDetails)
}
/* Process search details. */
searchDetails.forEach(addrDetails => {
const searchAddr = addrDetails.cashAddress
// console.log('UPDATE COINS (searchAddr)', searchAddr)
const txs = addrDetails.transactions
// console.log('UPDATE COINS (addrDetails.txs)', txs)
txs.forEach(async txid => {
/* Retrieve transaction details. */
const txDetails = await Nito.Transaction.details(txid)
// console.log('UPDATE COINS (tx details)', txDetails)
/* Set outputs. */
const outputs = txDetails.outputs
/* Handle all transaction outputs. */
outputs.forEach((output, index) => {
// console.log('UPDATE COINS (output)', output)
/* Set satoshi (amount). */
const satoshis = output.satoshis
// console.log('UPDATE COINS (satoshis)', satoshis)
/* Set script public key. */
const scriptPubKey = output.script
/* Validate script. */
if (!scriptPubKey) {
return
}
/* Set cash addresses. */
const cashAddrs = Nito.Address.toCashAddress(scriptPubKey)
// console.log('UPDATE COINS (cashAddrs)', cashAddrs)
/* Initialize WIF. */
let chainId = null
/* Initialize WIF. */
let wif = null
/* Find the WIF. */
for (let i = 0; i < accounts.length; i++) {
if (accounts[i].address === searchAddr) {
/* Set chain id. */
chainId = accounts[i].chainId
/* Set WIF. */
wif = accounts[i].wif
break
}
}
/* Validate search address. */
if (cashAddrs.includes(searchAddr)) {
/**
* Coin
*
* Status codes:
* active: Coin is ready to receive OR spend funds.
* disabled: Already received and spent funds (MUST be empty).
* locked: Coin is reserved OR has received funds currently
* being held in reserve for a later use.
* (eg. CashShuffle, CashFusion, ANYONECANPAY, etc)
*/
const coin = {
status: 'active',
txid,
vout: index,
satoshis,
wif,
cashAddress: searchAddr,
legacyAddress: Nito.Address.toLegacyAddress(searchAddr),
}
// console.log('UPDATE COINS (coin)', coin)
// const coins = getters.getCoinsBySessionId(sessionId)
// console.log('COINS', sessionId, coins)
/* Validate new coin. */
if (coins && !coins[`${coin.txid}:${coin.vout}`]) {
/* Create coin package. */
const pkg = {
// sessionId,
chainId,
coin,
}
/* Add new coin. */
dispatch('addCoin', pkg)
try {
/* Initialize media. */
const media = new Audio(require('@/media/coins.wav'))
/* Play media. */
// WARNING: This action may fail on several browsers;
// so it's best to do this last to avoid any
// unforseen side-effects.
media.play()
} catch (err) {
console.error(err) // eslint-disable-line no-console
}
} else {
console.error('Coin already exists in the purse.')
}
}
})
})
})
}
/* Export module. */
export default updateCoins
/**
* Update Metadata
*/
const updateMeta = ({ commit }, _meta) => {
/* Commit metadata. */
commit('setMeta', _meta)
}
/* Export module. */
export default updateMeta
/**
* Update Outbox
*/
const updateOutbox = ({ commit }, _outbox) => {
/* Commit outbox. */
commit('setOutbox', _outbox)
}
/* Export module. */
export default updateOutbox
/**
* Update Wallet
*/
const updateWallet = ({ commit, getters }, _params) => {
console.info('Updating wallet...', _params)
/* Set wallet. */
const wallet = _params.wallet
console.log('WALLET', wallet)
/* Set (account) action. */
const action = _params.action
console.log('ACCOUNT ACTION', action)
/* Set (account) indexes. */
const indexes = _params.indexes
console.log('ACCOUNT INDEXES', indexes)
/* Retreive accounts. */
const accounts = getters.getAccounts
console.log('ALL ACCOUNTS', accounts)
/* Retrieve wallet accounts. */
const walletAccounts = getters.getAccountsByWallet(wallet)
console.log('WALLET ACCOUNTS', walletAccounts)
/* Disable applicable account indexes. */
// FIXME: Do we verify here, OR in `sendCrypto`??
indexes.forEach(index => {
switch(action) {
case 'activate':
walletAccounts[index].s = 'a'
break
case 'disable':
walletAccounts[index].s = 'd'
break
case 'lock':
walletAccounts[index].s = 'l'
break
}
})
/* Update accounts. */
accounts[wallet] = walletAccounts
/* Commit updated accounts. */
commit('setAccounts', accounts)
}
/* Export module. */
export default updateWallet
/* Import modules. */
const Nito = require('nitojs')
/**
* Load (Derivation) Path
*/
const loadPath = (_getters, _accounts, _chainId, _acctIdx) => {
/* Initialize HD node. */
const hdNode = _getters.getHDNode
/* Set derivation path. */
const path = _getters.getDerivationPath(_chainId, _acctIdx)
// console.log('GET ACCOUNTS (path)', path)
/* Initialize child node. */
const childNode = hdNode.deriveChild(path)
/* Set WIF. */
const wif = childNode.privateKey.toWIF()
/* Set account (address). */
const address = Nito.Address.toCashAddress(childNode)
// console.log('GET ACCOUNTS (address)', address)
/* Add to all receiving (pool). */
_accounts.push({
chainId: _chainId,
address,
wif,
})
}
/**
* Get Accounts
*
* Returns the full accounts for the wallet. This will return coin details
* (incl. index and WIF) for ALL derivation paths in-use for a wallet.
*/
const getAccounts = (state, getters) => {
/* Initialize accounts. */
const accounts = []
/* Validate wallet. */
if (!getters.getWallet) {
return null
}
/* Initialize wallet. */
const wallet = getters.getWallet
// console.log('GET ACCOUNTS (wallet):', wallet)
/* Loop through ALL (deposit) indexes (inclusive). */
for (let i = 0; i <= wallet.accounts.deposit; i++) {
loadPath(getters, accounts, 0, i)
}
/* Loop through ALL (change) indexes (inclusive). */
for (let i = 0; i <= wallet.accounts.change; i++) {
loadPath(getters, accounts, 1, i)
}
/* Loop through ALL (change) indexes (inclusive). */
for (let i = 0; i <= wallet.accounts.change; i++) {
loadPath(getters, accounts, 6767, i)
}
/* Loop through ALL (change) indexes (inclusive). */
for (let i = 0; i <= wallet.accounts.change; i++) {
loadPath(getters, accounts, 7867, i)
}
// console.log('GET ACCOUNTS (accounts):', accounts)
/* Return accounts. */
return accounts
}
/* Export module. */
export default getAccounts
......@@ -42,6 +42,9 @@ const getAddress = (state, getters) => (_account) => {
case 'causes':
chain = 6767
break
case 'nito':
chain = 7867
break
}
/* Validate chain. */
......
......@@ -12,29 +12,20 @@ const Nito = require('nitojs')
const getBalanceBySessionId = (
state, getters, rootState, rootGetters
) => async (_currency) => {
/* Initialize (search) addresses. */
const addresses = []
/* Retrieve accounts. */
const accounts = getters.getAccounts
console.log('GET BALANCE (accounts)', accounts)
// const wallet = getters.getWallet
// console.log('GET BALANCE (wallet)', wallet)
// FIXME: We currently ONLY retrieve balances for index 0.
/* Set deposit address. */
addresses.push(getters.getAddress('deposit'))
/* Set change address. */
addresses.push(getters.getAddress('change'))
/* Set Causes address. */
addresses.push(getters.getAddress('causes'))
/* Validate accounts. */
if (accounts === null) {
return
}
/* Add all active receiving account (addresses) to pool. */
// Object.keys(coins).forEach(txid => {
// /* Add to all receiving (pool). */
// addresses.push(coins[txid].cashAddress)
// })
// console.log('GET BALANCE (all accounts)', addresses)
/* Build search array. */
const addresses = accounts.map(obj => {
return