mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-24 22:58:46 +01:00
feat: broadcast transaction (partial solution)
This commit is contained in:
parent
6098b8308e
commit
367faf437a
5 changed files with 101 additions and 17 deletions
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -262,6 +262,8 @@ const tableData = {
|
|||
psbtBase64: '',
|
||||
psbtBase64Signed: '',
|
||||
signedTx: null,
|
||||
signedTxHex: null,
|
||||
sentTxId: null,
|
||||
utxoSelectionModes: [
|
||||
'Manual',
|
||||
'Random',
|
||||
|
|
|
@ -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%;
|
||||
}
|
||||
|
|
|
@ -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##########################
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue