mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2024-11-20 02:28:10 +01:00
feat: propagate config update only when explicitly updated
This commit is contained in:
parent
657ed7a37c
commit
4671954896
@ -18,6 +18,7 @@ class WalletAccount(BaseModel):
|
||||
address_no: int
|
||||
balance: int
|
||||
type: str = ""
|
||||
network: str = "Mainnet"
|
||||
|
||||
@classmethod
|
||||
def from_row(cls, row: Row) -> "WalletAccount":
|
||||
@ -100,3 +101,4 @@ class Config(BaseModel):
|
||||
receive_gap_limit = 20
|
||||
change_gap_limit = 5
|
||||
sats_denominated = True
|
||||
network = "Mainnet"
|
||||
|
@ -35,13 +35,14 @@ async function feeRate(path) {
|
||||
},
|
||||
|
||||
refreshRecommendedFees: async function () {
|
||||
const {
|
||||
bitcoin: {fees: feesAPI}
|
||||
} = mempoolJS({
|
||||
hostname: new URL(this.mempoolEndpoint).hostname
|
||||
})
|
||||
|
||||
const fn = async () => feesAPI.getFeesRecommended()
|
||||
const fn = async () => {
|
||||
const {
|
||||
bitcoin: {fees: feesAPI}
|
||||
} = mempoolJS({
|
||||
hostname: this.mempoolEndpoint
|
||||
})
|
||||
return feesAPI.getFeesRecommended()
|
||||
}
|
||||
this.recommededFees = await retryWithDelay(fn)
|
||||
},
|
||||
getFeeRateLabel: function (feeRate) {
|
||||
|
@ -2,7 +2,6 @@
|
||||
<q-form @submit="checkAndSend" ref="paymentFormRef" class="q-gutter-md">
|
||||
<q-card class="q-mt-lg">
|
||||
<q-card-section>
|
||||
|
||||
<send-to
|
||||
:data.sync="sendToList"
|
||||
:fee-rate="feeRate"
|
||||
@ -42,7 +41,11 @@
|
||||
<div v-show="showCustomFee" class="row items-center no-wrap q-mt-md">
|
||||
<div class="col-12">
|
||||
<q-separator class="q-mb-md"></q-separator>
|
||||
<fee-rate :fee-value="feeValue" :rate.sync="feeRate" :mempool-endpoint="mempoolEndpoint"></fee-rate>
|
||||
<fee-rate
|
||||
:fee-value="feeValue"
|
||||
:rate.sync="feeRate"
|
||||
:mempool-endpoint="mempoolEndpoint"
|
||||
></fee-rate>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
@ -292,7 +292,7 @@ async function payment(path) {
|
||||
const {
|
||||
bitcoin: {transactions: transactionsAPI}
|
||||
} = mempoolJS({
|
||||
hostname: new URL(this.mempoolEndpoint).hostname
|
||||
hostname: this.mempoolEndpoint
|
||||
})
|
||||
|
||||
try {
|
||||
|
@ -2,12 +2,7 @@
|
||||
<q-card>
|
||||
<div class="row items-center no-wrap q-mb-md">
|
||||
<div class="col-2 q-ml-lg">
|
||||
<q-btn
|
||||
unelevated
|
||||
@click="config.show = true"
|
||||
color="primary"
|
||||
icon="settings"
|
||||
>
|
||||
<q-btn unelevated @click="show = true" color="primary" icon="settings">
|
||||
</q-btn>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
@ -21,13 +16,13 @@
|
||||
</div>
|
||||
</q-card>
|
||||
|
||||
<q-dialog v-model="config.show" position="top">
|
||||
<q-dialog v-model="show" position="top">
|
||||
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||
<q-form @submit="updateConfig" class="q-gutter-md">
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="config.data.mempool_endpoint"
|
||||
v-model.trim="config.mempool_endpoint"
|
||||
type="text"
|
||||
label="Mempool Endpoint"
|
||||
>
|
||||
@ -36,7 +31,7 @@
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.number="config.data.receive_gap_limit"
|
||||
v-model.number="config.receive_gap_limit"
|
||||
type="number"
|
||||
min="0"
|
||||
label="Receive Gap Limit"
|
||||
@ -45,7 +40,7 @@
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.number="config.data.change_gap_limit"
|
||||
v-model.number="config.change_gap_limit"
|
||||
type="number"
|
||||
min="0"
|
||||
label="Change Gap Limit"
|
||||
@ -55,15 +50,15 @@
|
||||
filled
|
||||
dense
|
||||
emit-value
|
||||
v-model="config.data.network"
|
||||
v-model="config.network"
|
||||
:options="networOptions"
|
||||
label="Network"
|
||||
></q-select>
|
||||
|
||||
<q-toggle
|
||||
:label="config.data.sats_denominated ? 'sats denominated' : 'BTC denominated'"
|
||||
:label="config.sats_denominated ? 'sats denominated' : 'BTC denominated'"
|
||||
color="secodary"
|
||||
v-model="config.data.sats_denominated"
|
||||
v-model="config.sats_denominated"
|
||||
></q-toggle>
|
||||
|
||||
<div class="row q-mt-lg">
|
||||
@ -71,7 +66,7 @@
|
||||
unelevated
|
||||
color="primary"
|
||||
:disable="
|
||||
!config.data.mempool_endpoint "
|
||||
!config.mempool_endpoint "
|
||||
type="submit"
|
||||
>Update</q-btn
|
||||
>
|
||||
|
@ -4,24 +4,51 @@ async function walletConfig(path) {
|
||||
name: 'wallet-config',
|
||||
template: t,
|
||||
|
||||
props: ['total', 'config', 'adminkey'],
|
||||
props: ['total', 'config-data', 'adminkey'],
|
||||
data: function () {
|
||||
return {}
|
||||
return {
|
||||
networOptions: ['Mainnet', 'Testnet'],
|
||||
internalConfig: {
|
||||
mempool_endpoint: 'https://mempool.space',
|
||||
receive_gap_limit: 20,
|
||||
change_gap_limit: 5
|
||||
},
|
||||
show: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
config: {
|
||||
get() {
|
||||
console.log('### get config', this.internalConfig)
|
||||
return this.internalConfig
|
||||
},
|
||||
set(value) {
|
||||
value.isLoaded = true
|
||||
console.log('### set config', this.internalConfig)
|
||||
this.internalConfig = JSON.parse(JSON.stringify(value))
|
||||
this.$emit(
|
||||
'update:config-data',
|
||||
JSON.parse(JSON.stringify(this.internalConfig))
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
satBtc(val, showUnit = true) {
|
||||
return satOrBtc(val, showUnit, this.config.data.sats_denominated)
|
||||
return satOrBtc(val, showUnit, this.config.sats_denominated)
|
||||
},
|
||||
updateConfig: async function () {
|
||||
try {
|
||||
await LNbits.api.request(
|
||||
const {data} = await LNbits.api.request(
|
||||
'PUT',
|
||||
'/watchonly/api/v1/config',
|
||||
this.adminkey,
|
||||
this.config.data
|
||||
this.config
|
||||
)
|
||||
this.config.show = false
|
||||
this.show = false
|
||||
this.config = data
|
||||
} catch (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
}
|
||||
@ -33,7 +60,7 @@ async function walletConfig(path) {
|
||||
'/watchonly/api/v1/config',
|
||||
this.adminkey
|
||||
)
|
||||
this.config.data = data
|
||||
this.config = data
|
||||
} catch (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
}
|
||||
|
@ -168,15 +168,6 @@
|
||||
label="Account Extended Public Key; xpub, ypub, zpub; Bitcoin Descriptor"
|
||||
></q-input>
|
||||
|
||||
<q-select
|
||||
filled
|
||||
dense
|
||||
emit-value
|
||||
v-model="formDialog.data.network"
|
||||
:options="networOptions"
|
||||
label="Network"
|
||||
></q-select>
|
||||
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
unelevated
|
||||
|
@ -14,7 +14,6 @@ async function walletList(path) {
|
||||
data: {}
|
||||
},
|
||||
filter: '',
|
||||
networOptions: ['Mainnet', 'Testnet'],
|
||||
walletsTable: {
|
||||
columns: [
|
||||
{
|
||||
|
@ -31,15 +31,7 @@ const watchOnly = async () => {
|
||||
|
||||
tab: 'addresses',
|
||||
|
||||
config: {
|
||||
data: {
|
||||
mempool_endpoint: 'https://mempool.space',
|
||||
receive_gap_limit: 20,
|
||||
change_gap_limit: 5
|
||||
},
|
||||
|
||||
show: false
|
||||
},
|
||||
config: {sats_denominated: true},
|
||||
|
||||
qrCodeDialog: {
|
||||
show: false,
|
||||
@ -58,6 +50,16 @@ const watchOnly = async () => {
|
||||
fetchedUtxos: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
mempoolHostname() {
|
||||
if (!this.config.isLoaded) return
|
||||
const hostname = new URL(this.config.mempool_endpoint).hostname
|
||||
if (this.config.network === 'testnet') {
|
||||
hostname += '/testnet'
|
||||
}
|
||||
return hostname
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateAmountForAddress: async function (addressData, amount = 0) {
|
||||
@ -321,31 +323,32 @@ const watchOnly = async () => {
|
||||
|
||||
//################### MEMPOOL API ###################
|
||||
getAddressTxsDelayed: async function (addrData) {
|
||||
const {
|
||||
bitcoin: {addresses: addressesAPI}
|
||||
} = mempoolJS({
|
||||
hostname: new URL(this.config.data.mempool_endpoint).hostname
|
||||
})
|
||||
|
||||
const fn = async () =>
|
||||
addressesAPI.getAddressTxs({
|
||||
const fn = async () => {
|
||||
const {
|
||||
bitcoin: {addresses: addressesAPI}
|
||||
} = mempoolJS({
|
||||
hostname: this.mempoolHostname
|
||||
})
|
||||
return addressesAPI.getAddressTxs({
|
||||
address: addrData.address
|
||||
})
|
||||
}
|
||||
const addressTxs = await retryWithDelay(fn)
|
||||
return this.addressHistoryFromTxs(addrData, addressTxs)
|
||||
},
|
||||
|
||||
getAddressTxsUtxoDelayed: async function (address) {
|
||||
const {
|
||||
bitcoin: {addresses: addressesAPI}
|
||||
} = mempoolJS({
|
||||
hostname: new URL(this.config.data.mempool_endpoint).hostname
|
||||
})
|
||||
const fn = async () => {
|
||||
const {
|
||||
bitcoin: {addresses: addressesAPI}
|
||||
} = mempoolJS({
|
||||
hostname: this.mempoolHostname
|
||||
})
|
||||
|
||||
const fn = async () =>
|
||||
addressesAPI.getAddressTxsUtxo({
|
||||
return addressesAPI.getAddressTxsUtxo({
|
||||
address
|
||||
})
|
||||
}
|
||||
return retryWithDelay(fn)
|
||||
},
|
||||
|
||||
|
@ -4,13 +4,13 @@
|
||||
<div class="col-12 col-md-7 q-gutter-y-md">
|
||||
<wallet-config
|
||||
:total="utxos.total"
|
||||
:config="config"
|
||||
:config-data.sync="config"
|
||||
:adminkey="g.user.wallets[0].adminkey"
|
||||
>
|
||||
<template v-slot:serial>
|
||||
<serial-signer
|
||||
ref="serialSigner"
|
||||
:sats-denominated="config.data.sats_denominated"
|
||||
:sats-denominated="config.sats_denominated"
|
||||
@signed:psbt="updateSignedPsbt"
|
||||
></serial-signer>
|
||||
</template>
|
||||
@ -19,7 +19,7 @@
|
||||
<wallet-list
|
||||
:adminkey="g.user.wallets[0].adminkey"
|
||||
:inkey="g.user.wallets[0].inkey"
|
||||
:sats-denominated="config.data.sats_denominated"
|
||||
:sats-denominated="config.sats_denominated"
|
||||
:addresses="addresses"
|
||||
@accounts-update="updateAccounts"
|
||||
@new-receive-address="showAddressDetails"
|
||||
@ -76,7 +76,7 @@
|
||||
</div>
|
||||
</q-card>
|
||||
|
||||
<q-card>
|
||||
<q-card v-if="config.isLoaded">
|
||||
<q-card-section v-show="!showPayment">
|
||||
<q-tabs v-model="tab" no-caps class="bg-dark text-white shadow-2">
|
||||
<q-tab name="addresses" label="Addresses"></q-tab>
|
||||
@ -89,8 +89,8 @@
|
||||
ref="addressList"
|
||||
:addresses="addresses"
|
||||
:accounts="walletAccounts"
|
||||
:mempool-endpoint="config.data.mempool_endpoint"
|
||||
:sats-denominated="config.data.sats_denominated"
|
||||
:mempool-endpoint="mempoolHostname"
|
||||
:sats-denominated="config.sats_denominated"
|
||||
@scan:address="scanAddress"
|
||||
@show-address-details="showAddressDetails"
|
||||
@update:addresses="initUtxos"
|
||||
@ -101,29 +101,28 @@
|
||||
<q-tab-panel name="history">
|
||||
<history
|
||||
:history="history"
|
||||
:mempool-endpoint="config.data.mempool_endpoint"
|
||||
:sats-denominated="config.data.sats_denominated"
|
||||
:mempool-endpoint="mempoolHostname"
|
||||
:sats-denominated="config.sats_denominated"
|
||||
></history>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="utxos">
|
||||
<utxo-list
|
||||
:utxos="utxos.data"
|
||||
:mempool-endpoint="config.data.mempool_endpoint"
|
||||
:sats-denominated="config.data.sats_denominated"
|
||||
:mempool-endpoint="mempoolHostname"
|
||||
:sats-denominated="config.sats_denominated"
|
||||
></utxo-list>
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
<div class="q-pt-sm">
|
||||
{{config.data.mempool_endpoint}}
|
||||
<div v-if="config.isLoaded" class="q-pt-sm">
|
||||
<payment
|
||||
ref="paymentRef"
|
||||
v-show="showPayment"
|
||||
:accounts="walletAccounts"
|
||||
:addresses="addresses"
|
||||
:utxos="utxos.data"
|
||||
:mempool-endpoint="config.data.mempool_endpoint"
|
||||
:mempool-endpoint="mempoolHostname"
|
||||
:adminkey="g.user.wallets[0].adminkey"
|
||||
:serial-signer-ref="$refs.serialSigner"
|
||||
></payment>
|
||||
@ -168,7 +167,7 @@
|
||||
size="ms"
|
||||
icon="launch"
|
||||
type="a"
|
||||
:href="config.mempool_endpoint + '/address/' + currentAddress.address"
|
||||
:href="mempoolHostname + '/address/' + currentAddress.address"
|
||||
target="_blank"
|
||||
></q-btn>
|
||||
</p>
|
||||
|
@ -233,8 +233,9 @@ async def api_psbt_create(
|
||||
descriptors[masterpub.fingerprint] = parse_key(masterpub.public_key)
|
||||
|
||||
inputs_extra = []
|
||||
bip32_derivations = {}
|
||||
|
||||
for i, inp in enumerate(data.inputs):
|
||||
bip32_derivations = {}
|
||||
descriptor = descriptors[inp.masterpub_fingerprint][0]
|
||||
d = descriptor.derive(inp.address_index, inp.branch_index)
|
||||
for k in d.keys:
|
||||
@ -291,6 +292,7 @@ async def api_psbt_extract_tx(
|
||||
if not final_psbt:
|
||||
raise ValueError("PSBT cannot be finalized!")
|
||||
res.tx_hex = final_psbt.to_string()
|
||||
print('### hex', res.tx_hex)
|
||||
|
||||
transaction = Transaction.from_string(res.tx_hex)
|
||||
tx = {
|
||||
|
Loading…
Reference in New Issue
Block a user