feat: extract signed transaction
This commit is contained in:
parent
d5cc8d9187
commit
32486d62bf
7 changed files with 133 additions and 72 deletions
|
|
@ -186,8 +186,13 @@
|
|||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="col-9">
|
||||
<q-spinner v-if="showChecking" color="primary"></q-spinner>
|
||||
<q-spinner
|
||||
v-if="showChecking"
|
||||
size="2.55em"
|
||||
color="primary"
|
||||
></q-spinner>
|
||||
<q-badge
|
||||
v-if="changeAmount < 0"
|
||||
class="text-subtitle2 float-right"
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ async function payment(path) {
|
|||
|
||||
if (this.psbtBase64) {
|
||||
await this.serialSignerRef.hwwSendPsbt(this.psbtBase64)
|
||||
await this.serialSignerRef.isSendingPsbt()
|
||||
}
|
||||
|
||||
console.log('### hwwSendPsbt')
|
||||
|
|
@ -189,6 +190,77 @@ async function payment(path) {
|
|||
}
|
||||
this.selectChangeAddress(this.changeWallet)
|
||||
},
|
||||
updateSignedPsbt: async function (psbtBase64) {
|
||||
console.log('### payment updateSignedPsbt psbtBase64', psbtBase64)
|
||||
|
||||
const data = await this.extractTxFromPsbt(psbtBase64)
|
||||
if (data) {
|
||||
this.signedTx = JSON.parse(data.tx_json)
|
||||
this.signedTxHex = data.tx_hex
|
||||
} else {
|
||||
this.signedTx = null
|
||||
this.signedTxHex = null
|
||||
}
|
||||
},
|
||||
extractTxFromPsbt: async function (psbtBase64) {
|
||||
console.log('### extractTxFromPsbt psbtBase64', psbtBase64)
|
||||
try {
|
||||
const {data} = await LNbits.api.request(
|
||||
'PUT',
|
||||
'/watchonly/api/v1/psbt/extract',
|
||||
this.adminkey,
|
||||
{
|
||||
psbtBase64,
|
||||
inputs: this.tx.inputs
|
||||
}
|
||||
)
|
||||
console.log('### extractTxFromPsbt data', data)
|
||||
return data
|
||||
} catch (error) {
|
||||
console.log('### error', error)
|
||||
this.$q.notify({
|
||||
type: 'warning',
|
||||
message: 'Cannot finalize PSBT!',
|
||||
timeout: 10000
|
||||
})
|
||||
LNbits.utils.notifyApiError(error)
|
||||
}
|
||||
},
|
||||
broadcastTransaction: async function () {
|
||||
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.payment.sentTxId = data
|
||||
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Transaction broadcasted!',
|
||||
caption: `${data}`,
|
||||
timeout: 10000
|
||||
})
|
||||
|
||||
this.hww.psbtSent = false
|
||||
this.payment.psbtBase64Signed = null
|
||||
this.payment.signedTxHex = null
|
||||
this.payment.signedTx = null
|
||||
this.payment.psbtBase64 = null
|
||||
|
||||
await this.scanAddressWithAmount()
|
||||
} catch (error) {
|
||||
this.payment.sentTxId = null
|
||||
this.$q.notify({
|
||||
type: 'warning',
|
||||
message: 'Failed to broadcast!',
|
||||
caption: `${error}`,
|
||||
timeout: 10000
|
||||
})
|
||||
}
|
||||
},
|
||||
fetchTxHex: async function (txId) {
|
||||
const {
|
||||
bitcoin: {transactions: transactionsAPI}
|
||||
|
|
|
|||
|
|
@ -136,6 +136,35 @@
|
|||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="hww.psbtSent" position="top">
|
||||
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||
<q-form @submit="hwwSignPsbt" class="q-gutter-md">
|
||||
<div class="row q-mt-lg">
|
||||
<div class="col-12">
|
||||
<span>Check transaction on your hardware device</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row q-mt-lg">
|
||||
<!-- todo: disable until all data is confirmed -->
|
||||
<q-btn
|
||||
unelevated
|
||||
color="green"
|
||||
:disable="!selectedPort"
|
||||
type="submit"
|
||||
label="Confirm"
|
||||
>
|
||||
<q-spinner v-if="hww.signingPsbt" color="primary"></q-spinner>
|
||||
</q-btn>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
||||
>Cancel</q-btn
|
||||
>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="hww.showWipeDialog" position="top">
|
||||
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||
<q-form @submit="hwwWipe" class="q-gutter-md">
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ async function serialSigner(path) {
|
|||
showPasswordDialog: false,
|
||||
showWipeDialog: false,
|
||||
showRestoreDialog: false,
|
||||
showConfirmationDialog: false,
|
||||
showConsole: false,
|
||||
showSignedPsbt: false,
|
||||
sendingPsbt: false,
|
||||
signingPsbt: false,
|
||||
psbtSent: false
|
||||
psbtSent: false,
|
||||
psbtSentResolve: null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -113,6 +115,12 @@ async function serialSigner(path) {
|
|||
isAuthenticated: function () {
|
||||
return this.hww.authenticated
|
||||
},
|
||||
isSendingPsbt: async function () {
|
||||
if (!this.hww.sendingPsbt) return false
|
||||
return new Promise(resolve => {
|
||||
this.psbtSentResolve = resolve
|
||||
})
|
||||
},
|
||||
|
||||
checkSerialPortSupported: function () {
|
||||
if (!navigator.serial) {
|
||||
|
|
@ -281,6 +289,7 @@ async function serialSigner(path) {
|
|||
timeout: 5000
|
||||
})
|
||||
} catch (error) {
|
||||
this.hww.sendingPsbt = false
|
||||
this.$q.notify({
|
||||
type: 'warning',
|
||||
message: 'Failed to send data to serial port!',
|
||||
|
|
@ -292,9 +301,11 @@ async function serialSigner(path) {
|
|||
handleSendPsbtResponse: function (res = '') {
|
||||
this.hww.psbtSent = true
|
||||
this.hww.sendingPsbt = false
|
||||
this.psbtSentResolve()
|
||||
},
|
||||
hwwSignPsbt: async function () {
|
||||
try {
|
||||
this.hww.psbtSent = false
|
||||
this.hww.signingPsbt = true
|
||||
await this.writer.write(COMMAND_SIGN_PSBT + '\n')
|
||||
this.$q.notify({
|
||||
|
|
@ -407,6 +418,9 @@ async function serialSigner(path) {
|
|||
this.hww.password = null
|
||||
this.hww.showPassword = false
|
||||
}
|
||||
},
|
||||
updateSignedPsbt: async function (value) {
|
||||
this.$emit('signed:psbt', value)
|
||||
}
|
||||
},
|
||||
created: async function () {}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,9 @@ const watchOnly = async () => {
|
|||
showAddress: false,
|
||||
addressNote: '',
|
||||
showPayment: false,
|
||||
fetchedUtxos: false
|
||||
fetchedUtxos: false,
|
||||
signedTx: null,
|
||||
signedTxHex: null
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -202,75 +204,11 @@ const watchOnly = async () => {
|
|||
|
||||
//################### PSBT ###################
|
||||
|
||||
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 (psbtBase64) {
|
||||
console.log('### updateSignedPsbt psbtBase64', psbtBase64)
|
||||
this.$refs.paymentRef.updateSignedPsbt(psbtBase64)
|
||||
},
|
||||
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 () {
|
||||
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.payment.sentTxId = data
|
||||
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Transaction broadcasted!',
|
||||
caption: `${data}`,
|
||||
timeout: 10000
|
||||
})
|
||||
|
||||
this.hww.psbtSent = false
|
||||
this.payment.psbtBase64Signed = null
|
||||
this.payment.signedTxHex = null
|
||||
this.payment.signedTx = null
|
||||
this.payment.psbtBase64 = null
|
||||
|
||||
await this.scanAddressWithAmount()
|
||||
} catch (error) {
|
||||
this.payment.sentTxId = null
|
||||
this.$q.notify({
|
||||
type: 'warning',
|
||||
message: 'Failed to broadcast!',
|
||||
caption: `${error}`,
|
||||
timeout: 10000
|
||||
})
|
||||
}
|
||||
},
|
||||
//################### SERIAL PORT ###################
|
||||
|
||||
//################### HARDWARE WALLET ###################
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ const readFromSerialPort = reader => {
|
|||
}
|
||||
while (true) {
|
||||
const {value, done} = await reader.read()
|
||||
console.log('### serial read', value)
|
||||
if (value) {
|
||||
const values = value.split(separator)
|
||||
// found one or more separators
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@
|
|||
:adminkey="g.user.wallets[0].adminkey"
|
||||
>
|
||||
<template v-slot:serial>
|
||||
<serial-signer ref="serialSigner"></serial-signer>
|
||||
<serial-signer
|
||||
ref="serialSigner"
|
||||
@signed:psbt="updateSignedPsbt"
|
||||
></serial-signer>
|
||||
</template>
|
||||
</wallet-config>
|
||||
|
||||
|
|
@ -113,6 +116,7 @@
|
|||
</q-card>
|
||||
<div class="q-pt-sm">
|
||||
<payment
|
||||
ref="paymentRef"
|
||||
v-show="showPayment"
|
||||
:accounts="walletAccounts"
|
||||
:addresses="addresses"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue