feat: login and send commands to HWW
This commit is contained in:
parent
b7c4a411b1
commit
a0d56a7e06
4 changed files with 336 additions and 98 deletions
|
|
@ -44,6 +44,13 @@ new Vue({
|
||||||
config: {}
|
config: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hww: {
|
||||||
|
password: null,
|
||||||
|
authenticated: false,
|
||||||
|
showPasswordDialog: false,
|
||||||
|
showConsole: false
|
||||||
|
},
|
||||||
|
|
||||||
formDialog: {
|
formDialog: {
|
||||||
show: false,
|
show: false,
|
||||||
data: {}
|
data: {}
|
||||||
|
|
@ -512,6 +519,67 @@ new Vue({
|
||||||
LNbits.utils.notifyApiError(err)
|
LNbits.utils.notifyApiError(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
extractTxFromPsbt: async function (psbtBase64) {
|
||||||
|
const wallet = this.g.user.wallets[0]
|
||||||
|
try {
|
||||||
|
const {data} = await LNbits.api.request(
|
||||||
|
'PUT',
|
||||||
|
'/watchonly/api/v1/psbt/extract',
|
||||||
|
wallet.adminkey,
|
||||||
|
{
|
||||||
|
psbtBase64,
|
||||||
|
inputs: this.payment.tx.inputs
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return data
|
||||||
|
} catch (error) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Cannot finalize PSBT!',
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
LNbits.utils.notifyApiError(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateSignedPsbt: async function (value) {
|
||||||
|
this.payment.psbtBase64Signed = value
|
||||||
|
|
||||||
|
const data = await this.extractTxFromPsbt(this.payment.psbtBase64Signed)
|
||||||
|
if (data) {
|
||||||
|
this.payment.signedTx = JSON.parse(data.tx_json)
|
||||||
|
this.payment.signedTxHex = data.tx_hex
|
||||||
|
} else {
|
||||||
|
this.payment.signedTx = null
|
||||||
|
this.payment.signedTxHex = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
broadcastTransaction: async function () {
|
||||||
|
console.log('### broadcastTransaction', this.payment.signedTxHex)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const wallet = this.g.user.wallets[0]
|
||||||
|
const {data} = await LNbits.api.request(
|
||||||
|
'POST',
|
||||||
|
'/watchonly/api/v1/tx',
|
||||||
|
wallet.adminkey,
|
||||||
|
{tx_hex: this.payment.signedTxHex}
|
||||||
|
)
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Transaction broadcasted!',
|
||||||
|
caption: `${data}`,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Failed to broadcast!',
|
||||||
|
caption: `${error}`,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//################### SERIAL PORT ###################
|
||||||
checkSerialPortSupported: function () {
|
checkSerialPortSupported: function () {
|
||||||
if (!navigator.serial) {
|
if (!navigator.serial) {
|
||||||
this.$q.notify({
|
this.$q.notify({
|
||||||
|
|
@ -586,23 +654,6 @@ new Vue({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sendPsbtToSerialPort: async function () {
|
|
||||||
try {
|
|
||||||
await this.serial.writer.write(this.payment.psbtBase64 + '\n')
|
|
||||||
this.$q.notify({
|
|
||||||
type: 'positive',
|
|
||||||
message: 'Data sent to serial port device!',
|
|
||||||
timeout: 5000
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
this.$q.notify({
|
|
||||||
type: 'warning',
|
|
||||||
message: 'Failed to send data to serial port!',
|
|
||||||
caption: `${error}`,
|
|
||||||
timeout: 10000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
startSerialPortReading: async function () {
|
startSerialPortReading: async function () {
|
||||||
const port = this.serial.selectedPort
|
const port = this.serial.selectedPort
|
||||||
|
|
@ -620,8 +671,7 @@ new Vue({
|
||||||
const {value, done} = await readStringUntil('\n')
|
const {value, done} = await readStringUntil('\n')
|
||||||
console.log('### value', value)
|
console.log('### value', value)
|
||||||
if (value) {
|
if (value) {
|
||||||
const isPsbt = value.startsWith(PSBT_BASE64_PREFIX)
|
this.handleSerialPortResponse(value)
|
||||||
if (isPsbt) this.updateSignedPsbt(value)
|
|
||||||
this.updateSerialPortConsole(value)
|
this.updateSerialPortConsole(value)
|
||||||
}
|
}
|
||||||
console.log('### startSerialPortReading DONE', done)
|
console.log('### startSerialPortReading DONE', done)
|
||||||
|
|
@ -638,43 +688,14 @@ new Vue({
|
||||||
}
|
}
|
||||||
console.log('### startSerialPortReading port', port)
|
console.log('### startSerialPortReading port', port)
|
||||||
},
|
},
|
||||||
extractTxFromPsbt: async function (psbtBase64) {
|
|
||||||
const wallet = this.g.user.wallets[0]
|
handleSerialPortResponse: function (value) {
|
||||||
try {
|
const msg = value.split(' ')
|
||||||
const {data} = await LNbits.api.request(
|
if (msg[0] == COMMAND_SIGN_PSBT) this.handleSignResponse(msg[1])
|
||||||
'PUT',
|
else if (msg[0] == COMMAND_PASSWORD) this.handleLoginResponse(msg[1])
|
||||||
'/watchonly/api/v1/psbt/extract',
|
else if (msg[0] == COMMAND_PASSWORD_CLEAR)
|
||||||
wallet.adminkey,
|
this.handleLogoutResponse(msg[1])
|
||||||
{
|
else console.log('### handleSerialPortResponse', value)
|
||||||
psbtBase64,
|
|
||||||
inputs: this.payment.tx.inputs
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return data
|
|
||||||
} catch (error) {
|
|
||||||
this.$q.notify({
|
|
||||||
type: 'warning',
|
|
||||||
message: 'Cannot finalize PSBT!',
|
|
||||||
timeout: 10000
|
|
||||||
})
|
|
||||||
LNbits.utils.notifyApiError(error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateSignedPsbt: async function (value) {
|
|
||||||
this.payment.psbtBase64Signed = value
|
|
||||||
this.$q.notify({
|
|
||||||
type: 'positive',
|
|
||||||
message: 'PSBT received from serial port device!',
|
|
||||||
timeout: 10000
|
|
||||||
})
|
|
||||||
const data = await this.extractTxFromPsbt(this.payment.psbtBase64Signed)
|
|
||||||
if (data) {
|
|
||||||
this.payment.signedTx = JSON.parse(data.tx_json)
|
|
||||||
this.payment.signedTxHex = data.tx_hex
|
|
||||||
} else {
|
|
||||||
this.payment.signedTx = null
|
|
||||||
this.payment.signedTxHex = null
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
updateSerialPortConsole: function (value) {
|
updateSerialPortConsole: function (value) {
|
||||||
this.serial.receivedData += value + '\n'
|
this.serial.receivedData += value + '\n'
|
||||||
|
|
@ -686,34 +707,115 @@ new Vue({
|
||||||
sharePsbtWithAnimatedQRCode: async function () {
|
sharePsbtWithAnimatedQRCode: async function () {
|
||||||
console.log('### sharePsbtWithAnimatedQRCode')
|
console.log('### sharePsbtWithAnimatedQRCode')
|
||||||
},
|
},
|
||||||
|
//################### HARDWARE WALLET ###################
|
||||||
broadcastTransaction: async function () {
|
hwwLogin: async function () {
|
||||||
console.log('### broadcastTransaction', this.payment.signedTxHex)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const wallet = this.g.user.wallets[0]
|
await this.serial.writer.write(
|
||||||
const {data} = await LNbits.api.request(
|
COMMAND_PASSWORD + ' ' + this.hww.password + '\n'
|
||||||
'POST',
|
|
||||||
'/watchonly/api/v1/tx',
|
|
||||||
wallet.adminkey,
|
|
||||||
{tx_hex: this.payment.signedTxHex}
|
|
||||||
)
|
)
|
||||||
this.$q.notify({
|
|
||||||
type: 'positive',
|
|
||||||
message: 'Transaction broadcasted!',
|
|
||||||
caption: `${data}`,
|
|
||||||
timeout: 10000
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$q.notify({
|
this.$q.notify({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: 'Failed to broadcast!',
|
message: 'Failed to send password to hardware wallet!',
|
||||||
|
caption: `${error}`,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
this.hww.showPasswordDialog = false
|
||||||
|
this.hww.password = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleLoginResponse: function (res = '') {
|
||||||
|
this.hww.authenticated = res.trim() === '1'
|
||||||
|
if (this.hww.authenticated) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Login successfull!',
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Wrong password, try again!',
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hwwLogout: async function () {
|
||||||
|
try {
|
||||||
|
await this.serial.writer.write(COMMAND_PASSWORD_CLEAR + '\n')
|
||||||
|
} catch (error) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Failed to logout from Hardware Wallet!',
|
||||||
caption: `${error}`,
|
caption: `${error}`,
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleLogoutResponse: function (res = '') {
|
||||||
|
this.hww.authenticated = !(res.trim() === '1')
|
||||||
|
if (this.hww.authenticated) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Failed to logout from Hardware Wallet',
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hwwToggleAuth: function () {
|
||||||
|
if (this.hww.authenticated) {
|
||||||
|
this.hwwLogout()
|
||||||
|
} else {
|
||||||
|
this.hww.showPasswordDialog = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hwwSendPsbt: async function () {
|
||||||
|
try {
|
||||||
|
await this.serial.writer.write(
|
||||||
|
COMMAND_SEND_PSBT + ' ' + this.payment.psbtBase64 + '\n'
|
||||||
|
)
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Data sent to serial port device!',
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Failed to send data to serial port!',
|
||||||
|
caption: `${error}`,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hwwSignPsbt: async function () {
|
||||||
|
try {
|
||||||
|
await this.serial.writer.write(COMMAND_SIGN_PSBT + '\n')
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'PSBT signed!',
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Failed to sign PSBT!',
|
||||||
|
caption: `${error}`,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSignResponse: function (res = '') {
|
||||||
|
this.updateSignedPsbt(res)
|
||||||
|
if (this.hww.authenticated) {
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Transaction Signed',
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
//################### UTXOs ###################
|
//################### UTXOs ###################
|
||||||
scanAllAddresses: async function () {
|
scanAllAddresses: async function () {
|
||||||
await this.refreshAddresses()
|
await this.refreshAddresses()
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,7 @@ const tableData = {
|
||||||
},
|
},
|
||||||
fee: 0,
|
fee: 0,
|
||||||
txSize: 0,
|
txSize: 0,
|
||||||
|
tx: null,
|
||||||
psbtBase64: '',
|
psbtBase64: '',
|
||||||
psbtBase64Signed: '',
|
psbtBase64Signed: '',
|
||||||
signedTx: null,
|
signedTx: null,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
const PSBT_BASE64_PREFIX = 'cHNidP8'
|
const PSBT_BASE64_PREFIX = 'cHNidP8'
|
||||||
|
const COMMAND_PASSWORD = '/password'
|
||||||
|
const COMMAND_PASSWORD_CLEAR = '/password-clear'
|
||||||
|
const COMMAND_SEND_PSBT = '/psbt'
|
||||||
|
const COMMAND_SIGN_PSBT = '/sign'
|
||||||
|
|
||||||
const blockTimeToDate = blockTime =>
|
const blockTimeToDate = blockTime =>
|
||||||
blockTime ? moment(blockTime * 1000).format('LLL') : ''
|
blockTime ? moment(blockTime * 1000).format('LLL') : ''
|
||||||
|
|
@ -105,8 +109,7 @@ const readFromSerialPort = serial => {
|
||||||
let fulliness = []
|
let fulliness = []
|
||||||
|
|
||||||
const readStringUntil = async (separator = '\n') => {
|
const readStringUntil = async (separator = '\n') => {
|
||||||
console.log('### fulliness', fulliness)
|
if (fulliness.length) return fulliness.shift().trim()
|
||||||
if (fulliness.length) return fulliness.shift()
|
|
||||||
const chunks = []
|
const chunks = []
|
||||||
if (partialChunk) {
|
if (partialChunk) {
|
||||||
// leftovers from previous read
|
// leftovers from previous read
|
||||||
|
|
@ -115,7 +118,7 @@ const readFromSerialPort = serial => {
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
const {value, done} = await serial.reader.read()
|
const {value, done} = await serial.reader.read()
|
||||||
console.log('### value 1', value)
|
console.log('### serial read', value)
|
||||||
if (value) {
|
if (value) {
|
||||||
const values = value.split(separator)
|
const values = value.split(separator)
|
||||||
// found one or more separators
|
// found one or more separators
|
||||||
|
|
@ -123,11 +126,11 @@ const readFromSerialPort = serial => {
|
||||||
chunks.push(values.shift()) // first element
|
chunks.push(values.shift()) // first element
|
||||||
partialChunk = values.pop() // last element
|
partialChunk = values.pop() // last element
|
||||||
fulliness = values // full lines
|
fulliness = values // full lines
|
||||||
return {value: chunks.join(''), done: false}
|
return {value: chunks.join('').trim(), done: false}
|
||||||
}
|
}
|
||||||
chunks.push(value)
|
chunks.push(value)
|
||||||
}
|
}
|
||||||
if (done) return {value: chunks.join(''), done: true}
|
if (done) return {value: chunks.join('').trim(), done: true}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return readStringUntil
|
return readStringUntil
|
||||||
|
|
|
||||||
|
|
@ -1015,13 +1015,14 @@
|
||||||
<div class="row items-center no-wrap q-mb-md">
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
<div class="col-3 q-pr-lg">
|
<div class="col-3 q-pr-lg">
|
||||||
<q-btn unelevated color="secondary" type="submit"
|
<q-btn unelevated color="secondary" type="submit"
|
||||||
>Create PSBT</q-btn
|
>Check Transaction</q-btn
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<q-input v-model="payment.psbtBase64" filled />
|
<q-input v-model="payment.psbtBase64" filled />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<q-separator v-if="payment.psbtBase64"></q-separator>
|
||||||
<div
|
<div
|
||||||
v-if="payment.psbtBase64"
|
v-if="payment.psbtBase64"
|
||||||
class="row items-center no-wrap q-mb-md"
|
class="row items-center no-wrap q-mb-md"
|
||||||
|
|
@ -1037,12 +1038,11 @@
|
||||||
></q-option-group>
|
></q-option-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-separator></q-separator>
|
<q-separator v-if="payment.psbtBase64 && payment.signMode === 'serial-port'"></q-separator>
|
||||||
<div
|
<div
|
||||||
v-if="payment.psbtBase64 && payment.signMode === 'serial-port'"
|
v-if="payment.psbtBase64 && payment.signMode === 'serial-port'"
|
||||||
class="row items-center no-wrap q-mb-md q-mt-lg"
|
class="row items-center no-wrap q-mb-md q-mt-lg"
|
||||||
>
|
>
|
||||||
<!-- <div class="col-3"></div> -->
|
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!serial.selectedPort"
|
v-if="!serial.selectedPort"
|
||||||
|
|
@ -1059,29 +1059,118 @@
|
||||||
>Disconnect</q-btn
|
>Disconnect</q-btn
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-3">
|
||||||
<q-toggle
|
<q-toggle
|
||||||
label="Advanced"
|
label="Advanced"
|
||||||
|
disabled
|
||||||
color="secodary float-left"
|
color="secodary float-left"
|
||||||
class="q-ml-lg"
|
class="q-ml-lg"
|
||||||
v-model="serial.showAdvancedConfig"
|
v-model="serial.showAdvancedConfig"
|
||||||
></q-toggle>
|
></q-toggle>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6"></div>
|
||||||
|
</div>
|
||||||
|
<q-separator v-if="payment.psbtBase64 && payment.signMode === 'serial-port'"></q-separator>
|
||||||
|
<div
|
||||||
|
v-if="payment.psbtBase64 && payment.signMode === 'serial-port'"
|
||||||
|
class="row items-center no-wrap q-mb-md q-mt-lg"
|
||||||
|
>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<q-btn
|
<q-btn-dropdown
|
||||||
v-if="serial.selectedPort"
|
v-if="serial.selectedPort"
|
||||||
@click="sendPsbtToSerialPort()"
|
split
|
||||||
unelevated
|
class="glossy float-left"
|
||||||
color="secondary float-right"
|
color="secondary"
|
||||||
>Send PSBT to Device</q-btn
|
:label="hww.authenticated ? 'Logout' : 'Login'"
|
||||||
|
@click="hwwToggleAuth()"
|
||||||
>
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-if="!hww.authenticated"
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="hww.showPasswordDialog = true"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Login</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Enter password for HWW.</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item
|
||||||
|
v-if="hww.authenticated"
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="hwwLogout()"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Logout</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Clear password for HWW.</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item
|
||||||
|
:disabled="!hww.authenticated"
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="hww.showPasswordDialog = true"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Sign</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Sign PSBT on Hardware Wallet.</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item clickable v-close-popup>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Restore</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Restore wallet from existing word
|
||||||
|
list.</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item clickable v-close-popup>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Wipe</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Clean-up the wallet. New random
|
||||||
|
seed.</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item clickable v-close-popup>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Help</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>View available comands.</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<q-toggle
|
||||||
|
v-if="serial.selectedPort"
|
||||||
|
label="Show Console"
|
||||||
|
color="secodary float-left"
|
||||||
|
class="q-ml-lg"
|
||||||
|
v-model="hww.showConsole"
|
||||||
|
></q-toggle>
|
||||||
|
</div>
|
||||||
|
<div class="col-3"></div>
|
||||||
|
<div class="col-3"></div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="serial.showAdvancedConfig"
|
v-if="hww.showConsole"
|
||||||
class="row items-center no-wrap q-mb-md"
|
class="row items-center no-wrap q-mb-md"
|
||||||
>
|
>
|
||||||
<div class="col-3 q-pr-lg">Message from device</div>
|
<div class="col-3 q-pr-lg"></div>
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<q-input
|
<q-input
|
||||||
for="watchonly-serial-port-data-input"
|
for="watchonly-serial-port-data-input"
|
||||||
|
|
@ -1091,19 +1180,34 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<q-separator v-if="hww.authenticated"></q-separator>
|
||||||
<div
|
<div
|
||||||
v-if="payment.psbtBase64Signed"
|
v-if="hww.authenticated"
|
||||||
class="row items-center no-wrap q-mb-md"
|
class="row items-center no-wrap q-mb-md"
|
||||||
>
|
>
|
||||||
<div class="col-3 q-pr-lg">PSBT from device</div>
|
<div class="col-3 q-pr-lg">
|
||||||
<div class="col-9">
|
<q-btn @click="hwwSendPsbt()" unelevated color="secondary"
|
||||||
<q-input
|
>Sign</q-btn
|
||||||
v-model="payment.psbtBase64Signed"
|
>
|
||||||
filled
|
</div>
|
||||||
readonly
|
|
||||||
/>
|
<div class="col-6">
|
||||||
|
<q-badge color="blue"
|
||||||
|
>Please check transaction data on the Hardware Wallet
|
||||||
|
Display</q-badge
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<q-btn
|
||||||
|
@click="hwwSignPsbt()"
|
||||||
|
unelevated
|
||||||
|
color="green"
|
||||||
|
class="float-right text-subtitle1"
|
||||||
|
>Confirm</q-btn
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<q-separator v-if="payment.signedTx"></q-separator>
|
||||||
<div
|
<div
|
||||||
v-if="payment.signedTx"
|
v-if="payment.signedTx"
|
||||||
class="row items-center no-wrap q-mb-md"
|
class="row items-center no-wrap q-mb-md"
|
||||||
|
|
@ -1338,6 +1442,34 @@
|
||||||
<div class="row q-mt-lg q-gutter-sm"></div>
|
<div class="row q-mt-lg q-gutter-sm"></div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
|
<q-dialog v-model="hww.showPasswordDialog" position="top">
|
||||||
|
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||||
|
<q-form @submit="hwwLogin" class="q-gutter-md">
|
||||||
|
<span>Enter password for Hardware Wallet</span>
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model.trim="hww.password"
|
||||||
|
type="password"
|
||||||
|
label="Password"
|
||||||
|
></q-input>
|
||||||
|
|
||||||
|
<div class="row q-mt-lg">
|
||||||
|
<q-btn
|
||||||
|
unelevated
|
||||||
|
color="primary"
|
||||||
|
:disable="!serial.selectedPort"
|
||||||
|
type="submit"
|
||||||
|
>Login</q-btn
|
||||||
|
>
|
||||||
|
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
||||||
|
>Cancel</q-btn
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</q-form>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue