feat: improve on create wallet frontend and api. (BREAKING CHANGE) (#3635)
This commit is contained in:
parent
3af3838995
commit
5f86627eae
13 changed files with 101 additions and 71 deletions
|
|
@ -197,11 +197,14 @@ async def api_delete_wallet(
|
||||||
|
|
||||||
@wallet_router.post("")
|
@wallet_router.post("")
|
||||||
async def api_create_wallet(
|
async def api_create_wallet(
|
||||||
data: CreateWallet,
|
data: CreateWallet, account_id: AccountId = Depends(check_account_id_exists)
|
||||||
key_info: WalletTypeInfo = Depends(require_admin_key),
|
|
||||||
) -> Wallet:
|
) -> Wallet:
|
||||||
if data.wallet_type == WalletType.LIGHTNING:
|
|
||||||
return await create_wallet(user_id=key_info.wallet.user, wallet_name=data.name)
|
if data.wallet_type not in list(WalletType):
|
||||||
|
raise HTTPException(
|
||||||
|
HTTPStatus.BAD_REQUEST,
|
||||||
|
f"Wallet type {data.wallet_type} does not exist.",
|
||||||
|
)
|
||||||
|
|
||||||
if data.wallet_type == WalletType.LIGHTNING_SHARED:
|
if data.wallet_type == WalletType.LIGHTNING_SHARED:
|
||||||
if not data.shared_wallet_id:
|
if not data.shared_wallet_id:
|
||||||
|
|
@ -210,11 +213,9 @@ async def api_create_wallet(
|
||||||
"Shared wallet ID is required for shared wallets.",
|
"Shared wallet ID is required for shared wallets.",
|
||||||
)
|
)
|
||||||
return await create_lightning_shared_wallet(
|
return await create_lightning_shared_wallet(
|
||||||
user_id=key_info.wallet.user,
|
user_id=account_id.id,
|
||||||
source_wallet_id=data.shared_wallet_id,
|
source_wallet_id=data.shared_wallet_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
raise HTTPException(
|
# default WalletType.LIGHTNING:
|
||||||
HTTPStatus.BAD_REQUEST,
|
return await create_wallet(user_id=account_id.id, wallet_name=data.name)
|
||||||
f"Unknown wallet type: {data.wallet_type}.",
|
|
||||||
)
|
|
||||||
|
|
|
||||||
2
lnbits/static/bundle-components.min.js
vendored
2
lnbits/static/bundle-components.min.js
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -129,14 +129,12 @@ window._lnbitsApi = {
|
||||||
getWallet(wallet) {
|
getWallet(wallet) {
|
||||||
return this.request('get', '/api/v1/wallet', wallet.inkey)
|
return this.request('get', '/api/v1/wallet', wallet.inkey)
|
||||||
},
|
},
|
||||||
createWallet(wallet, name, walletType, ops = {}) {
|
createWallet(name, walletType, opts = {}) {
|
||||||
return this.request('post', '/api/v1/wallet', wallet.adminkey, {
|
return this.request('post', '/api/v1/wallet', null, {
|
||||||
name: name,
|
name: name,
|
||||||
wallet_type: walletType,
|
wallet_type: walletType,
|
||||||
...ops
|
...opts
|
||||||
}).then(res => {
|
}).catch(LNbits.utils.notifyApiError)
|
||||||
window.location = '/wallet?wal=' + res.data.id
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
updateWallet(name, wallet) {
|
updateWallet(name, wallet) {
|
||||||
return this.request('patch', '/api/v1/wallet', wallet.adminkey, {
|
return this.request('patch', '/api/v1/wallet', wallet.adminkey, {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,13 @@ window.app.component('lnbits-manage-wallet-list', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
openNewWalletDialog() {
|
||||||
|
if (this.g.user.walletInvitesCount) {
|
||||||
|
this.g.newWalletType = 'lightning-shared'
|
||||||
|
} else {
|
||||||
|
this.g.newWalletType = 'lightning'
|
||||||
|
}
|
||||||
|
},
|
||||||
onWebsocketMessage(ev) {
|
onWebsocketMessage(ev) {
|
||||||
const data = JSON.parse(ev.data)
|
const data = JSON.parse(ev.data)
|
||||||
if (!data.payment) {
|
if (!data.payment) {
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,27 @@ window.app.component('lnbits-wallet-new', {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
walletTypes: [{label: 'Lightning Wallet', value: 'lightning'}],
|
walletTypes: [{label: 'Lightning Wallet', value: 'lightning'}],
|
||||||
newWallet: {name: '', sharedWalletId: ''}
|
wallet: {name: '', sharedWalletId: ''},
|
||||||
|
showNewWalletDialog: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'g.newWalletType'(val) {
|
||||||
|
if (val === null) return
|
||||||
|
this.showNewWalletDialog = true
|
||||||
|
},
|
||||||
|
showNewWalletDialog(val) {
|
||||||
|
if (val === true) return
|
||||||
|
this.reset()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
isLightning() {
|
||||||
|
return this.g.newWalletType === 'lightning'
|
||||||
|
},
|
||||||
|
isLightningShared() {
|
||||||
|
return this.g.newWalletType === 'lightning-shared'
|
||||||
|
},
|
||||||
inviteWalletOptions() {
|
inviteWalletOptions() {
|
||||||
return (this.g.user?.extra?.wallet_invite_requests || []).map(i => ({
|
return (this.g.user?.extra?.wallet_invite_requests || []).map(i => ({
|
||||||
label: `${i.to_wallet_name} (from ${i.from_user_name})`,
|
label: `${i.to_wallet_name} (from ${i.from_user_name})`,
|
||||||
|
|
@ -16,11 +33,16 @@ window.app.component('lnbits-wallet-new', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
reset() {
|
||||||
|
this.showNewWalletDialog = false
|
||||||
|
this.g.newWalletType = null
|
||||||
|
this.wallet = {name: '', sharedWalletId: ''}
|
||||||
|
},
|
||||||
async submitRejectWalletInvitation() {
|
async submitRejectWalletInvitation() {
|
||||||
try {
|
try {
|
||||||
const inviteRequests = this.g.user.extra.wallet_invite_requests || []
|
const inviteRequests = this.g.user.extra.wallet_invite_requests || []
|
||||||
const invite = inviteRequests.find(
|
const invite = inviteRequests.find(
|
||||||
invite => invite.to_wallet_id === this.newWallet.sharedWalletId
|
invite => invite.to_wallet_id === this.wallet.sharedWalletId
|
||||||
)
|
)
|
||||||
if (!invite) {
|
if (!invite) {
|
||||||
Quasar.Notify.create({
|
Quasar.Notify.create({
|
||||||
|
|
@ -46,8 +68,8 @@ window.app.component('lnbits-wallet-new', {
|
||||||
LNbits.utils.notifyApiError(err)
|
LNbits.utils.notifyApiError(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async submitAddWallet() {
|
submitAddWallet() {
|
||||||
const data = this.newWallet
|
const data = this.wallet
|
||||||
if (this.g.newWalletType === 'lightning' && !data.name) {
|
if (this.g.newWalletType === 'lightning' && !data.name) {
|
||||||
this.$q.notify({
|
this.$q.notify({
|
||||||
message: 'Please enter a name for the wallet',
|
message: 'Please enter a name for the wallet',
|
||||||
|
|
@ -55,7 +77,6 @@ window.app.component('lnbits-wallet-new', {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.g.newWalletType === 'lightning-shared' && !data.sharedWalletId) {
|
if (this.g.newWalletType === 'lightning-shared' && !data.sharedWalletId) {
|
||||||
this.$q.notify({
|
this.$q.notify({
|
||||||
message: 'Missing a shared wallet ID',
|
message: 'Missing a shared wallet ID',
|
||||||
|
|
@ -63,19 +84,20 @@ window.app.component('lnbits-wallet-new', {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
LNbits.api
|
||||||
await LNbits.api.createWallet(
|
.createWallet(data.name, this.g.newWalletType, {
|
||||||
this.g.user.wallets[0],
|
|
||||||
data.name,
|
|
||||||
this.g.newWalletType,
|
|
||||||
{
|
|
||||||
shared_wallet_id: data.sharedWalletId
|
shared_wallet_id: data.sharedWalletId
|
||||||
}
|
})
|
||||||
)
|
.then(res => {
|
||||||
} catch (e) {
|
this.$q.notify({
|
||||||
console.warn(e)
|
message: 'Wallet created successfully',
|
||||||
LNbits.utils.notifyApiError(e)
|
color: 'positive'
|
||||||
}
|
})
|
||||||
|
this.reset()
|
||||||
|
this.g.user.wallets.push(LNbits.map.wallet(res.data))
|
||||||
|
this.g.lastWalletId = res.data.id
|
||||||
|
this.$router.push(`/wallet/${res.data.id}`)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ window.g = Vue.reactive({
|
||||||
fiatTracking: false,
|
fiatTracking: false,
|
||||||
payments: [],
|
payments: [],
|
||||||
walletEventListeners: [],
|
walletEventListeners: [],
|
||||||
showNewWalletDialog: false,
|
|
||||||
newWalletType: 'lightning',
|
|
||||||
updatePayments: false, // used for updating the lnbits-payment-list
|
updatePayments: false, // used for updating the lnbits-payment-list
|
||||||
updatePaymentsHash: false, // used for closing the receive dialog
|
updatePaymentsHash: false, // used for closing the receive dialog
|
||||||
currencies: WINDOW_SETTINGS.LNBITS_CURRENCIES ?? [],
|
currencies: WINDOW_SETTINGS.LNBITS_CURRENCIES ?? [],
|
||||||
|
|
@ -57,7 +55,8 @@ window.g = Vue.reactive({
|
||||||
ads: WINDOW_SETTINGS.AD_SPACE.split(',').map(ad => ad.split(';')),
|
ads: WINDOW_SETTINGS.AD_SPACE.split(',').map(ad => ad.split(';')),
|
||||||
denomination: WINDOW_SETTINGS.LNBITS_DENOMINATION,
|
denomination: WINDOW_SETTINGS.LNBITS_DENOMINATION,
|
||||||
isSatsDenomination: WINDOW_SETTINGS.LNBITS_DENOMINATION == 'sats',
|
isSatsDenomination: WINDOW_SETTINGS.LNBITS_DENOMINATION == 'sats',
|
||||||
scanner: null
|
scanner: null,
|
||||||
|
newWalletType: null
|
||||||
})
|
})
|
||||||
|
|
||||||
window.dateFormat = 'YYYY-MM-DD HH:mm'
|
window.dateFormat = 'YYYY-MM-DD HH:mm'
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1 @@
|
||||||
window.windowMixin = {
|
window.windowMixin = {}
|
||||||
methods: {
|
|
||||||
openNewWalletDialog(walletType = 'lightning') {
|
|
||||||
this.g.newWalletType = walletType
|
|
||||||
this.g.showNewWalletDialog = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
<q-card-section class="flex flex-center column full-height text-center">
|
<q-card-section class="flex flex-center column full-height text-center">
|
||||||
<div>
|
<div>
|
||||||
<q-btn
|
<q-btn
|
||||||
@click="openNewWalletDialog()"
|
@click="g.newWalletType = 'lightning'"
|
||||||
round
|
round
|
||||||
color="primary"
|
color="primary"
|
||||||
icon="add"
|
icon="add"
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<div>
|
<div>
|
||||||
<q-badge
|
<q-badge
|
||||||
v-if="g.user.walletInvitesCount"
|
v-if="g.user.walletInvitesCount"
|
||||||
@click="openNewWalletDialog('lightning-shared')"
|
@click="g.newWalletType = 'lightning-shared'"
|
||||||
dense
|
dense
|
||||||
outline
|
outline
|
||||||
class="q-mt-sm"
|
class="q-mt-sm"
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,7 @@
|
||||||
></q-item-label>
|
></q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item
|
<q-item clickable @click="openNewWalletDialog">
|
||||||
clickable
|
|
||||||
@click="
|
|
||||||
g.user.walletInvitesCount
|
|
||||||
? openNewWalletDialog('lightning-shared')
|
|
||||||
: openNewWalletDialog('lightning')
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<q-item-section side>
|
<q-item-section side>
|
||||||
<q-icon name="add" color="grey-5" size="md"></q-icon>
|
<q-icon name="add" color="grey-5" size="md"></q-icon>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template id="lnbits-wallet-new">
|
<template id="lnbits-wallet-new">
|
||||||
<q-dialog v-model="g.showNewWalletDialog" position="top">
|
<q-dialog v-model="showNewWalletDialog" position="top">
|
||||||
<q-card class="q-pa-lg q-pt-md lnbits__dialog-card">
|
<q-card class="q-pa-lg q-pt-md lnbits__dialog-card">
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div class="text-h6">
|
<div class="text-h6">
|
||||||
|
|
@ -33,18 +33,17 @@
|
||||||
dense
|
dense
|
||||||
></q-select>
|
></q-select>
|
||||||
<q-input
|
<q-input
|
||||||
v-if="g.newWalletType == 'lightning'"
|
v-if="isLightning"
|
||||||
dense
|
dense
|
||||||
v-model="newWallet.name"
|
v-model="wallet.name"
|
||||||
:label="$t('wallet_name')"
|
:label="$t('wallet_name')"
|
||||||
autofocus
|
autofocus
|
||||||
@keyup.enter="submitAddWallet()"
|
@keyup.enter="submitAddWallet()"
|
||||||
class="q-mt-md"
|
class="q-mt-md"
|
||||||
></q-input>
|
></q-input>
|
||||||
|
|
||||||
<q-select
|
<q-select
|
||||||
v-if="g.newWalletType == 'lightning-shared'"
|
v-if="isLightningShared"
|
||||||
v-model="newWallet.sharedWalletId"
|
v-model="wallet.sharedWalletId"
|
||||||
:label="$t('shared_wallet_id')"
|
:label="$t('shared_wallet_id')"
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
map-options
|
||||||
|
|
@ -52,7 +51,7 @@
|
||||||
:options="inviteWalletOptions"
|
:options="inviteWalletOptions"
|
||||||
class="q-mt-md"
|
class="q-mt-md"
|
||||||
></q-select>
|
></q-select>
|
||||||
<div v-if="g.newWalletType == 'lightning-shared'" class="q-mt-md">
|
<div v-if="isLightningShared" class="q-mt-md">
|
||||||
<span v-text="$t('shared_wallet_desc')" class="q-mt-lg"></span>
|
<span v-text="$t('shared_wallet_desc')" class="q-mt-lg"></span>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
@ -69,8 +68,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="g.newWalletType == 'lightning-shared'"
|
v-if="isLightningShared"
|
||||||
:disabled="!newWallet.sharedWalletId"
|
:disabled="!wallet.sharedWalletId"
|
||||||
flat
|
flat
|
||||||
:label="$t('reject_wallet')"
|
:label="$t('reject_wallet')"
|
||||||
v-close-popup
|
v-close-popup
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="row items-center justify-between q-gutter-xs">
|
<div class="row items-center justify-between q-gutter-xs">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-btn
|
<q-btn
|
||||||
@click="openNewWalletDialog()"
|
@click="g.newWalletType = 'lightning'"
|
||||||
:label="$t('add_wallet')"
|
:label="$t('add_wallet')"
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,28 @@ async def test_create_account(client, settings: Settings):
|
||||||
# check POST and DELETE /api/v1/wallet with adminkey and user token:
|
# check POST and DELETE /api/v1/wallet with adminkey and user token:
|
||||||
# create additional wallet and delete it
|
# create additional wallet and delete it
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
async def test_create_wallet_and_delete(
|
async def test_create_wallet_and_delete(client, user_headers_from):
|
||||||
client, adminkey_headers_from, user_headers_from
|
tiny_id = shortuuid.uuid()[:8]
|
||||||
):
|
|
||||||
response = await client.post(
|
response = await client.post(
|
||||||
"/api/v1/wallet", json={"name": "test"}, headers=adminkey_headers_from
|
"/api/v1/auth/register",
|
||||||
|
json={
|
||||||
|
"username": f"u21.{tiny_id}",
|
||||||
|
"password": "secret1234",
|
||||||
|
"password_repeat": "secret1234",
|
||||||
|
"email": f"u21.{tiny_id}@lnbits.com",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
client.cookies.clear()
|
||||||
|
|
||||||
|
access_token = response.json().get("access_token")
|
||||||
|
assert response.status_code == 200, "User created."
|
||||||
|
assert response.json().get("access_token") is not None
|
||||||
|
|
||||||
|
response = await client.post(
|
||||||
|
"/api/v1/wallet",
|
||||||
|
json={"name": "test"},
|
||||||
|
headers={"Authorization": f"Bearer {access_token}"},
|
||||||
)
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
|
@ -58,6 +75,7 @@ async def test_create_wallet_and_delete(
|
||||||
assert "id" in result
|
assert "id" in result
|
||||||
assert "adminkey" in result
|
assert "adminkey" in result
|
||||||
|
|
||||||
|
# should not work with admin key only with user
|
||||||
invalid_response = await client.delete(
|
invalid_response = await client.delete(
|
||||||
f"/api/v1/wallet/{result['id']}",
|
f"/api/v1/wallet/{result['id']}",
|
||||||
headers={
|
headers={
|
||||||
|
|
@ -69,7 +87,7 @@ async def test_create_wallet_and_delete(
|
||||||
|
|
||||||
response = await client.delete(
|
response = await client.delete(
|
||||||
f"/api/v1/wallet/{result['id']}",
|
f"/api/v1/wallet/{result['id']}",
|
||||||
headers=user_headers_from,
|
headers={"Authorization": f"Bearer {access_token}"},
|
||||||
)
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue