Commit 0bc4f11a authored by Bitcoin Please's avatar Bitcoin Please

Completed flipstarter pledge manager.

parent 59d35c30
......@@ -9,7 +9,7 @@ import getDerivationPath from './wallet/getters/getDerivationPath'
import getDustAmount from './wallet/getters/getDustAmount'
import getHDNode from './wallet/getters/getHDNode'
import getHistory from './wallet/getters/getHistory'
import getIndicies from './wallet/getters/getIndicies'
import getIndices from './wallet/getters/getIndices'
import getMnemonic from './wallet/getters/getMnemonic'
/* Import modules (actions). */
......@@ -23,7 +23,7 @@ import updateOutbox from './wallet/actions/updateOutbox'
/* Import modules (mutations). */
import setCoins from './wallet/mutations/setCoins'
import setEmptyWallet from './wallet/mutations/setEmptyWallet'
import setIndicies from './wallet/mutations/setIndicies'
import setIndices from './wallet/mutations/setIndices'
/* Initialize state. */
const state = {
......@@ -74,7 +74,7 @@ const getters = {
getDustAmount,
getHDNode,
getHistory,
getIndicies,
getIndices,
getMnemonic,
}
......@@ -92,7 +92,7 @@ const actions = {
const mutations = {
setCoins,
setEmptyWallet,
setIndicies,
setIndices,
}
/* Export. */
......
......@@ -6,12 +6,12 @@
const addCoin = ({ commit, getters }, _pkg) => {
console.info('Adding new coin...', _pkg) // eslint-disable-line no-console
/* Request accounts. */
const accounts = getters.getAccounts
// console.log('ADD NEW COIN (accounts):', accounts)
/* Request indices. */
const indices = getters.getIndices
// console.log('ADD NEW COIN (indices):', indices)
/* Validate accounts. */
if (!accounts) {
/* Validate indices. */
if (!indices) {
return
}
......@@ -23,19 +23,19 @@ const addCoin = ({ commit, getters }, _pkg) => {
switch(chainid) {
case 0:
/* Increment deposit index. */
accounts.deposit++
indices.deposit++
break
case 1:
/* Increment change index. */
accounts.change++
indices.change++
break
case 6767:
/* Increment causes index. */
accounts.causes++
indices.causes++
break
case 7867:
/* Increment nito index. */
accounts.nito++
indices.nito++
break
}
......@@ -55,8 +55,8 @@ const addCoin = ({ commit, getters }, _pkg) => {
/* Add coin to wallet. */
coins[`${coin.txid}:${coin.vout}`] = coin
/* Commit updated accounts`. */
commit('setAccounts', accounts)
/* Commit updated indices`. */
commit('setIndices', indices)
/* Commit updated coins`. */
commit('setCoins', coins)
......
......@@ -31,9 +31,9 @@ const initWallet = ({ commit }) => {
commit('setCoins', coinsModel)
/**
* Indicies Model
* Indices Model
*
* Manages the indicies of account (addresses) and their respective
* Manages the indices of account (addresses) and their respective
* derivation paths.
*
* Deposit : m/44'/145'/0'/0/<index>
......@@ -41,15 +41,15 @@ const initWallet = ({ commit }) => {
* Causes Cash : m/44'/145'/0'/6767/<index>
* Nito Cash : m/44'/145'/0'/7867/<index>
*/
const indiciesModel = {
const indicesModel = {
deposit: 0,
change: 0,
causes: 0,
nito: 0,
}
/* Commit indicies. */
commit('setIndicies', indiciesModel)
/* Commit indices. */
commit('setIndices', indicesModel)
/* Return success. */
return true
......
......@@ -33,7 +33,7 @@ const updateStatus = (_coins, _meta, dispatch) => {
}
} else {
/* Validate metadata coins. */
if (!_meta || !_meta.coins[coinid]) {
if (!_meta || !_meta.coins || !_meta.coins[coinid]) {
return
}
......
......@@ -41,32 +41,32 @@ const loadPath = (_getters, _accounts, _chainid, _acctIdx) => {
*/
const getAccounts = (state, getters) => {
/* Validate state. */
if (!state || !state.indicies) {
throw new Error('Current state is invalid. Missing `wallet.indicies`.')
if (!state || !state.indices) {
throw new Error('Current state is invalid. Missing `wallet.indices`.')
}
/* Initialize accounts. */
const accounts = []
/* Initialize account indicies. */
const acctIndexes = msgpack.decode(Buffer.from(state.indicies, 'hex'))
/* Initialize account indices. */
const acctIndexes = msgpack.decode(Buffer.from(state.indices, 'hex'))
/* Loop through ALL (deposit) indicies (inclusive). */
/* Loop through ALL (deposit) indices (inclusive). */
for (let i = 0; i <= acctIndexes.deposit; i++) {
loadPath(getters, accounts, 0, i)
}
/* Loop through ALL (change) indicies (inclusive). */
/* Loop through ALL (change) indices (inclusive). */
for (let i = 0; i <= acctIndexes.change; i++) {
loadPath(getters, accounts, 1, i)
}
/* Loop through ALL (causes) indicies (inclusive). */
/* Loop through ALL (causes) indices (inclusive). */
for (let i = 0; i <= acctIndexes.causes; i++) {
loadPath(getters, accounts, 6767, i)
}
/* Loop through ALL (nito) indicies (inclusive). */
/* Loop through ALL (nito) indices (inclusive). */
for (let i = 0; i <= acctIndexes.nito; i++) {
loadPath(getters, accounts, 7867, i)
}
......
......@@ -12,12 +12,12 @@ const getAddress = (state, getters) => (_account) => {
return null
}
/* Request indicies. */
const indicies = getters.getIndicies
// console.log('GET ADDRESS (indicies):', indicies)
/* Request indices. */
const indices = getters.getIndices
// console.log('GET ADDRESS (indices):', indices)
/* Initialize current (coin) index. */
const currentIndex = indicies[_account]
const currentIndex = indices[_account]
// console.log('GET ADDRESS (currentIndex):', currentIndex)
/* Initialize chain. */
......
......@@ -2,20 +2,20 @@
import msgpack from 'msgpack-lite'
/**
* Get Indicies
* Get Indices
*/
const getIndicies = (state) => {
const getIndices = (state) => {
/* Validate state. */
if (!state || !state.indicies) {
if (!state || !state.indices) {
return null
}
/* Initialize indicies. */
const indicies = msgpack.decode(Buffer.from(state.indicies, 'hex'))
/* Initialize indices. */
const indices = msgpack.decode(Buffer.from(state.indices, 'hex'))
/* Return indicies. */
return indicies
/* Return indices. */
return indices
}
/* Export module. */
export default getIndicies
export default getIndices
......@@ -2,12 +2,12 @@
import msgpack from 'msgpack-lite'
/**
* Set Indicies
* Set Indices
*/
const setIndicies = (state, _indicies) => {
/* Set indicies. */
state.indicies = msgpack.encode(_indicies).toString('hex')
const setIndices = (state, _indices) => {
/* Set indices. */
state.indices = msgpack.encode(_indices).toString('hex')
}
/* Export module. */
export default setIndicies
export default setIndices
......@@ -124,20 +124,20 @@
</div>
</div>
<div class="col-8">
<h3>QR COde Payment Request</h3>
<div class="col-7">
<h3>Payment Request</h3>
<div class="qr-code m-3" v-html="qr" @click="copyAddress" />
</div>
<div class="col-4">
<h3>Wallet balance: $0.00</h3>
<div class="col-5">
<h3>Wallet Balance</h3>
<input
class="mt-3 mb-2"
type="text"
placeholder="Fiat wallet value"
v-model="walletContribution"
v-model="fiatContribution"
disabled
/>
......@@ -145,7 +145,7 @@
class="mt-3 mb-2"
type="text"
placeholder="Satoshi wallet value"
v-model="walletContribution"
v-model="satoshiContribution"
disabled
/>
......@@ -156,12 +156,35 @@
>
Apply to pledge
</a>
<a
href="javascript://"
class="btn-warning btn-block mt-3"
@click="updateCoins"
>
Update coins
</a>
</div>
<div v-if="pledgeAuth" class="col-12">
<textarea
class="pledge-auth mt-3"
v-model="pledgeAuth">
</textarea>
<a
href="javascript://"
class="btn-primary mt-3"
@click="copyAuth"
>
Copy authorization to clipboard
</a>
</div>
</div>
<hr v-if="userPledge" />
<hr v-if="pledgeAuth" />
<div v-if="userPledge" class="row">
<div v-if="pledgeAuth" class="row">
<div class="col">
<h3>STEP 4: Submit pledge authorization</h3>
......@@ -202,7 +225,8 @@ export default {
data: () => {
return {
usd: null,
walletContribution: null,
fiatContribution: null,
satoshiContribution: null,
pledgeDetails: null,
pledgeAuth: null,
......@@ -213,14 +237,14 @@ export default {
'getHelp',
]),
...mapGetters('profile', [
'getMeta',
]),
...mapGetters('wallet', [
'getAccounts',
'getAddress',
'getBalance',
'getCoins',
'getDerivationPath',
'getHDNode',
'getIndices',
]),
/**
......@@ -380,14 +404,11 @@ export default {
/* Calculate pledge amount (in BCH). */
const amount = parseFloat(this.userPledge.donation.amount / 100000000.0)
console.log('AMOUNT', amount);
/* Set payment URL. */
const paymentUrl = `${this.getAddress('causes')}?amount=${amount}`
console.log('PAYMENT URL', paymentUrl);
QRCode.toString(paymentUrl, params, (err, value) => {
// QRCode.toString(this.getAddress('causes'), params, (err, value) => {
if (err) {
return console.error('QR Code ERROR:', err)
}
......@@ -407,6 +428,7 @@ export default {
]),
...mapActions('utils', [
'setClipboard',
'toast',
]),
......@@ -429,20 +451,14 @@ export default {
/* Initialize value. */
let value = null
/* Set campaign value. */
this.campaignValue = this.userPledge.outputs[0].value
// console.log('Campaign value:', this.campaignValue)
/* Set value. */
value = Nito.Utils.encodeNumber(this.campaignValue)
value = Nito.Utils
.encodeNumber(this.userPledge.outputs[0].value)
// console.log('Encoded value:', value)
/* Set campaign address. */
this.campaignAddress = this.userPledge.outputs[0].address
// console.log('Campaign address:', this.campaignAddress)
/* Set locking script. */
const locking_script = Nito.Address.toPubKeyHash(this.campaignAddress)
const locking_script = Nito.Address
.toPubKeyHash(this.userPledge.outputs[0].address)
// console.log('Campaign (locking_script):', locking_script)
/* Set current output. */
......@@ -490,15 +506,8 @@ export default {
const nSequence = Buffer.from('FFFFFFFF', 'hex')
/* Set hash outputs. */
// const hashOutputs = bitbox.Crypto.hash256(
// Buffer.concat(transactionOutpoints)
// )
const hashOutputs = Nito.Crypto.hash(
Buffer.concat(transactionOutpoints), 'sha256sha256'
)
// console.log('transactionOutpoints', transactionOutpoints);
// console.log('transactionOutpoints (concat)', Buffer.concat(transactionOutpoints).toString('hex'));
// console.log('hashOutputs', hashOutputs.toString('hex'));
const hashOutputs = Nito.Crypto
.hash(Buffer.concat(transactionOutpoints), 'sha256sha256')
/* Set locktime. */
const nLocktime = Buffer.from('00000000', 'hex')
......@@ -506,17 +515,6 @@ export default {
/* Set signature hash type. */
const sighashType = Buffer.from('c1000000', 'hex')
// console.log('nVersion', nVersion);
// console.log('hashPrevouts', hashPrevouts);
// console.log('hashSequence', hashSequence);
// console.log('outpoint', outpoint);
// console.log('scriptCode', scriptCode);
// console.log('value', value);
// console.log('nSequence', nSequence);
// console.log('hashOutputs', hashOutputs);
// console.log('nLocktime', nLocktime);
// console.log('sighashType', sighashType);
/* Construct signature hash message. */
const sighashMessage = Buffer.concat([
nVersion,
......@@ -540,100 +538,32 @@ export default {
return sighashDigest
},
/**
* Confirm Flipstarter (Pledge)
*
* Transfers the pledge amount into a dedicated UTXO.
*/
async confirmFlipstarter() {
/* Request accounts. */
const accounts = this.getAccounts
console.log('ACCOUNTS', accounts)
/* 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('BACKING (meta):', meta)
const spendable = Object.keys(coins).filter(coinid => {
return coins[coinid].status === 'active'
})
console.log('SPENDABLE', spendable)
const locked = Object.keys(coins).filter(coinid => {
return coins[coinid].status === 'locked'
})
console.log('LOCKED', locked)
/* Initialize source coin. */
let sourceCoin = null
/* Set donation amount. */
const donation = this.userPledge.donation.amount
console.log('DONATION', donation)
/* Loop through all locked. */
locked.forEach(coinid => {
if (coins[coinid].satoshis === donation) {
/* Set source coin. */
sourceCoin = coins[coinid]
}
})
/* Loop through all spendables. */
// FIXME FOR DEVELOPMENT ONLY
spendable.forEach(coinid => {
if (coins[coinid].satoshis === donation) {
/* Set source coin. */
sourceCoin = coins[coinid]
}
})
console.log('SOURCE COIN', sourceCoin);
/* Make pledge. */
// this.makePledge(sourceCoin)
},
/**
* Make Pledge
*/
async makePledge(_coin) {
/* Initialize verification key. */
const verificationKey = Nito.Purse.fromWIF(_coin.wif)
console.log('verificationKey', verificationKey, _coin.wif)
// console.log('verificationKey', verificationKey, _coin.wif)
/* Set public key. */
const publicKey = verificationKey.publicKey.toString()
console.log('\nPublic key:', publicKey)
// console.log('\nPublic key:', publicKey)
/* Set cash address. */
const cashAddress = Nito.Address.toCashAddress(verificationKey)
console.log('FLIPSTARTER (pledge address)', cashAddress)
// console.log('FLIPSTARTER (pledge address)', cashAddress)
console.log('USER PLEDGE', this.userPledge)
// console.log('USER PLEDGE', this.userPledge)
const alias = this.userPledge.data.alias
console.log('ALIAS:', alias)
// console.log('ALIAS:', alias)
const comment = this.userPledge.data.comment
console.log('COMMENT:', comment)
// console.log('COMMENT:', comment)
const expires = this.userPledge.expires
console.log('EXPIRES:', expires)
// console.log('EXPIRES:', expires)
if (!_coin.txid || !_coin.satoshis) {
return console.error('No UTXO available for pledge.')
......@@ -641,21 +571,26 @@ export default {
const previousTransactionHash = _coin.txid
const previousTransactionOutputValue = Nito.Utils.encodeNumber(_coin.satoshis)
// const previousTransactionOutputIndex = '00000000'
const previousTransactionOutputIndex = Nito.Utils.encodeNumber(_coin.vout)
// const previousTransactionOutputIndex = '01000000'
const previousTransactionOutputIndex = Buffer.allocUnsafe(4)
previousTransactionOutputIndex.writeUIntLE(_coin.vout, 0, 4)
console.log('PREVIOUS TX OUT IDX', previousTransactionOutputIndex)
console.log('PREVIOUS TX OUT IDX (hex)', previousTransactionOutputIndex.toString('hex'))
const inputLockScript = Nito.Address.toPubKeyHash(cashAddress)
/* Validate commitment signature. */
const verificationMessage = this.assembleSighashDigest(
Buffer.from(previousTransactionHash, 'hex'),
Buffer.from(previousTransactionOutputIndex, 'hex'),
// Buffer.from(previousTransactionOutputIndex, 'hex'),
previousTransactionOutputIndex,
Buffer.from(previousTransactionOutputValue, 'hex'),
Buffer.from(inputLockScript, 'hex')
)
console.log('verificationMessage', verificationMessage.toString('hex'))
// console.log('verificationMessage', verificationMessage.toString('hex'))
const pledgeSig = Nito.Account.sign(verificationMessage, verificationKey)
console.log('PLEDGE SIGNATURE', pledgeSig.toString())
// console.log('PLEDGE SIGNATURE', pledgeSig.toString())
const previous_output_transaction_hash = previousTransactionHash
// const previous_output_index = 0
......@@ -668,7 +603,7 @@ export default {
'c1' + // NOTE: sigHashType
'21' +
publicKey
console.log('UNLOCKING SCRIPT:', unlocking_script)
// console.log('UNLOCKING SCRIPT:', unlocking_script)
const assuranceOutput = {
inputs: [{
......@@ -683,7 +618,7 @@ export default {
},
data_signature: null
}
console.log('ASSURANCE OUTPUT:', assuranceOutput)
console.info('Assurance output:', assuranceOutput)
/* Encode assurance pledge. */
const encodedPledge = Buffer.from(JSON.stringify(assuranceOutput)).toString('base64')
......@@ -718,7 +653,8 @@ export default {
}
/* Update metadata. */
this.updateMeta(meta)
const metaUpdate = await this.updateMeta(meta)
console.log('FLIPSTARTER (metaUpdate):', metaUpdate)
/* Set message. */
const message = `Your coin has been locked!`
......@@ -730,26 +666,88 @@ export default {
/**
* Apply Balance
*/
applyBalance() {
this.toast(['Oops!', 'Your wallet balance is too low', 'error'])
// Swal.fire({
// title: 'Are you sure?',
// text: "You won't be able to revert this!",
// icon: 'warning',
// showCancelButton: true,
// confirmButtonColor: '#3085d6',
// cancelButtonColor: '#d33',
// confirmButtonText: 'Yes, delete it!'
// }).then((result) => {