feat: broadcast transaction (partial solution)

This commit is contained in:
Vlad Stan 2022-07-15 09:02:50 +03:00
parent 6098b8308e
commit 367faf437a
5 changed files with 101 additions and 17 deletions

View file

@ -82,7 +82,7 @@ class CreatePsbt(BaseModel):
class ExtractPsbt(BaseModel):
psbtBase64 = ""
psbtBase64 = "" # // todo snake case
class SignedTransaction(BaseModel):
@ -90,6 +90,10 @@ class SignedTransaction(BaseModel):
tx_json: Optional[str]
class BroadcastTransaction(BaseModel):
tx_hex: str
class Config(BaseModel):
mempool_endpoint = "https://mempool.space"
receive_gap_limit = 20

View file

@ -639,8 +639,10 @@ new Vue({
)
if (data) {
this.payment.signedTx = JSON.parse(data.tx_json)
this.payment.signedTxHex = data.tx_hex
} else {
this.payment.signedTx = null
his.payment.signedTxHex = null
}
}
} else {
@ -688,6 +690,27 @@ new Vue({
console.log('### sharePsbtWithAnimatedQRCode')
},
broadcastTransaction: async function () {
console.log('### broadcastTransaction', this.payment.signedTxHex)
try {
const wallet = this.g.user.wallets[0]
await LNbits.api.request(
'POST',
'/watchonly/api/v1/tx',
wallet.adminkey,
{tx_hex: this.payment.signedTxHex}
)
} catch (error) {
this.$q.notify({
type: 'warning',
message: 'Failed to broadcast!',
caption: `${error}`,
timeout: 10000
})
}
},
//################### UTXOs ###################
scanAllAddresses: async function () {
await this.refreshAddresses()

View file

@ -262,6 +262,8 @@ const tableData = {
psbtBase64: '',
psbtBase64Signed: '',
signedTx: null,
signedTxHex: null,
sentTxId: null,
utxoSelectionModes: [
'Manual',
'Random',

View file

@ -182,14 +182,13 @@
:disabled="scan.scanning == true"
>Scan Blockchain</q-btn
>
</div>
<div class="col-6">
<q-spinner
v-if="scan.scanning == true"
color="primary"
size="2.55em"
></q-spinner>
v-if="scan.scanning == true"
color="primary"
size="2.55em"
></q-spinner>
</div>
<div class="col-3 q-pr-md">
<q-btn
@ -997,8 +996,8 @@
class="text-subtitle2"
color="green"
>
{{payment.changeAmount ? satBtc(payment.changeAmount):
'no change'}}
{{payment.changeAmount ?
satBtc(payment.changeAmount): 'no change'}}
</q-badge>
<q-badge
v-if="payment.changeAmount > 0 && payment.changeAmount < DUST_LIMIT"
@ -1065,7 +1064,7 @@
>Disconnect</q-btn
>
</div>
<div class="col-5">
<div class="col-6">
<q-toggle
label="Advanced Config"
color="secodary float-left"
@ -1073,7 +1072,7 @@
v-model="serial.showAdvancedConfig"
></q-toggle>
</div>
<div class="col-3 ">
<div class="col-3">
<q-btn
v-if="serial.selectedPort"
@click="sendPsbtToSerialPort()"
@ -1113,16 +1112,50 @@
<div class="row items-center no-wrap q-mb-sm">
<div class="col-3 q-pr-lg">Fee</div>
<div class="col-9">
<q-badge color="orange">{{satBtc(payment.signedTx.fee)}} </q-badge></div>
<q-badge color="orange"
>{{satBtc(payment.signedTx.fee)}}
</q-badge>
</div>
</div>
<q-separator class="q-mb-lg"></q-separator>
<div v-for="out in payment.signedTx.outputs" class="row items-center no-wrap q-mb-sm">
<div class="col-3 q-pr-lg"> <q-badge color="orange">{{satBtc(out.amount)}}</div>
<div
v-for="out in payment.signedTx.outputs"
class="row items-center no-wrap q-mb-sm"
>
<div class="col-3 q-pr-lg">
<q-badge color="orange"
>{{satBtc(out.amount)}}</q-badge
>
</div>
<div class="col-9">
<q-badge outline color="blue">{{out.address}}</q-badge></div>
<q-badge outline color="blue"
>{{out.address}}</q-badge
>
</div>
</div>
</div>
</div>
<div
v-if="payment.psbtBase64Signed"
class="row items-center no-wrap q-mb-md"
>
<div class="col-3 q-pr-lg">
<q-btn
v-if="payment.signedTx"
@click="broadcastTransaction()"
unelevated
color="secondary"
>Send Payment</q-btn
>
</div>
<div class="col-9">
<q-input
v-if="payment.sentTxId"
v-model="payment.sentTxId"
filled
readonly
/>
</div>
</div>
</q-card-section>
@ -1301,7 +1334,6 @@
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<style>
.btn-full {
width: 100%;
}

View file

@ -1,4 +1,5 @@
from http import HTTPStatus
import httpx
import json
from fastapi import Query, Request
@ -33,6 +34,7 @@ from .crud import (
update_config,
)
from .models import (
BroadcastTransaction,
SignedTransaction,
CreateWallet,
CreatePsbt,
@ -304,6 +306,27 @@ async def api_psbt_extract_tx(
return res.dict()
@watchonly_ext.post("/api/v1/tx")
async def api_psbt_extract_tx(
data: BroadcastTransaction, w: WalletTypeInfo = Depends(require_admin_key)
):
print("### data", data)
try:
config = await get_config(w.wallet.user)
if not config:
raise ValueError("Cannot broadcast transaction. Mempool endpoint not defined!")
x = bytes.fromhex(data.tx_hex)
print('### x', x)
async with httpx.AsyncClient() as client:
r = await client.post(
config.mempool_endpoint + "/api/tx",
data=x
)
tx_id = r.json()
return tx_id
except Exception as e:
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=str(e))
#############################CONFIG##########################