Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
564b016f47 | ||
|
|
82932ce7c8 | ||
|
|
33600d5c1c | ||
|
|
7640f5d74d | ||
|
|
35052661f8 | ||
|
|
5f1c8bee4b |
@@ -1,6 +1,6 @@
|
||||
import { ServiceUnavailableException } from '@nestjs/common';
|
||||
import type { ConfigService } from '@nestjs/config';
|
||||
import { BitcoinWalletSyncStatus } from '../types/BitcoinWalletSyncStatus';
|
||||
import { WalletSyncStatus } from '../../../types/wallet/WalletSyncStatus';
|
||||
import type { ElectrumWalletRpcClient } from './ElectrumWalletRpcClient';
|
||||
import { BitcoinWalletAdminService } from './BitcoinWalletAdminService';
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('BitcoinWalletAdminService', () => {
|
||||
rpcVersion: '4.8.1',
|
||||
blockHeight: 900_000,
|
||||
serverHeight: 900_000,
|
||||
syncStatus: BitcoinWalletSyncStatus.Synced,
|
||||
syncStatus: WalletSyncStatus.Synced,
|
||||
balanceBtc: '0.00150000',
|
||||
confirmedBalanceBtc: '0.00150000'
|
||||
})
|
||||
@@ -63,7 +63,7 @@ describe('BitcoinWalletAdminService', () => {
|
||||
|
||||
const status = await service.getStatus();
|
||||
|
||||
expect(status.syncStatus).toBe(BitcoinWalletSyncStatus.Syncing);
|
||||
expect(status.syncStatus).toBe(WalletSyncStatus.Syncing);
|
||||
});
|
||||
|
||||
it('throws when RPC calls fail', async () => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Injectable, ServiceUnavailableException } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { convertBtcAtomicToBtc } from '../../../utils/bitcoin/convertBtcAtomicToBtc';
|
||||
import type { Config } from '../../../types/Config';
|
||||
import { BitcoinWalletSyncStatus } from '../types/BitcoinWalletSyncStatus';
|
||||
import { WalletSyncStatus } from '../../../types/wallet/WalletSyncStatus';
|
||||
import type { BitcoinWalletStatusView } from '../types/BitcoinWalletStatusView';
|
||||
import { ElectrumWalletRpcClient } from './ElectrumWalletRpcClient';
|
||||
|
||||
@@ -47,15 +47,15 @@ export class BitcoinWalletAdminService {
|
||||
isSynchronized: boolean,
|
||||
blockHeight: number | null,
|
||||
serverHeight: number | null
|
||||
): BitcoinWalletSyncStatus {
|
||||
): WalletSyncStatus {
|
||||
if (isSynchronized) {
|
||||
return BitcoinWalletSyncStatus.Synced;
|
||||
return WalletSyncStatus.Synced;
|
||||
}
|
||||
|
||||
if (blockHeight === null || serverHeight === null) {
|
||||
return BitcoinWalletSyncStatus.Unknown;
|
||||
return WalletSyncStatus.Unknown;
|
||||
}
|
||||
|
||||
return BitcoinWalletSyncStatus.Syncing;
|
||||
return WalletSyncStatus.Syncing;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ElectrumNetwork } from '../../../types/ElectrumNetwork';
|
||||
import { BitcoinWalletSyncStatus } from './BitcoinWalletSyncStatus';
|
||||
import { WalletSyncStatus } from '../../../types/wallet/WalletSyncStatus';
|
||||
|
||||
export interface BitcoinWalletStatusView {
|
||||
network: ElectrumNetwork;
|
||||
rpcVersion: string;
|
||||
blockHeight: number | null;
|
||||
serverHeight: number | null;
|
||||
syncStatus: BitcoinWalletSyncStatus;
|
||||
syncStatus: WalletSyncStatus;
|
||||
balanceBtc: string;
|
||||
confirmedBalanceBtc: string;
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export enum BitcoinWalletSyncStatus {
|
||||
Synced = 'synced',
|
||||
Syncing = 'syncing',
|
||||
Unknown = 'unknown'
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { BadRequestException, ServiceUnavailableException } from '@nestjs/common
|
||||
import type { ConfigService } from '@nestjs/config';
|
||||
import axios from 'axios';
|
||||
import type { AuthService } from '../../auth/services/AuthService';
|
||||
import { MoneroWalletSyncStatus } from '../types/MoneroWalletSyncStatus';
|
||||
import { WalletSyncStatus } from '../../../types/wallet/WalletSyncStatus';
|
||||
import type { MoneroWalletRpcClient } from './MoneroWalletRpcClient';
|
||||
import { MoneroWalletAdminService } from './MoneroWalletAdminService';
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('MoneroWalletAdminService', () => {
|
||||
rpcVersion: '0.18.3.1',
|
||||
walletHeight: 3_000_000,
|
||||
daemonHeight: 3_000_000,
|
||||
syncStatus: MoneroWalletSyncStatus.Synced,
|
||||
syncStatus: WalletSyncStatus.Synced,
|
||||
balanceXmr: '2.00000000',
|
||||
unlockedBalanceXmr: '1.00000000'
|
||||
})
|
||||
@@ -137,7 +137,7 @@ describe('MoneroWalletAdminService', () => {
|
||||
|
||||
const status = await service.getStatus();
|
||||
|
||||
expect(status.syncStatus).toBe(MoneroWalletSyncStatus.Unknown);
|
||||
expect(status.syncStatus).toBe(WalletSyncStatus.Unknown);
|
||||
expect(status.daemonHeight).toBeNull();
|
||||
});
|
||||
|
||||
@@ -149,7 +149,7 @@ describe('MoneroWalletAdminService', () => {
|
||||
|
||||
const status = await service.getStatus();
|
||||
|
||||
expect(status.syncStatus).toBe(MoneroWalletSyncStatus.Synced);
|
||||
expect(status.syncStatus).toBe(WalletSyncStatus.Synced);
|
||||
});
|
||||
|
||||
it('throws when reveal seed RPC fails', async () => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { Config } from '../../../types/Config';
|
||||
import type { MoneroDaemonGetInfoResult } from '../types/MoneroDaemonGetInfoResult';
|
||||
import type { MoneroWalletRevealSeedResult } from '../types/MoneroWalletRevealSeedResult';
|
||||
import type { MoneroWalletStatusView } from '../types/MoneroWalletStatusView';
|
||||
import { MoneroWalletSyncStatus } from '../types/MoneroWalletSyncStatus';
|
||||
import { WalletSyncStatus } from '../../../types/wallet/WalletSyncStatus';
|
||||
import type { MoneroWalletWithdrawResult } from '../types/MoneroWalletWithdrawResult';
|
||||
import { MoneroWalletRpcClient } from './MoneroWalletRpcClient';
|
||||
|
||||
@@ -72,7 +72,7 @@ export class MoneroWalletAdminService {
|
||||
throw new BadRequestException('No unlocked balance to withdraw.');
|
||||
}
|
||||
|
||||
if (this.resolveSyncStatus(walletHeight, daemonHeight) !== MoneroWalletSyncStatus.Synced) {
|
||||
if (this.resolveSyncStatus(walletHeight, daemonHeight) !== WalletSyncStatus.Synced) {
|
||||
throw new BadRequestException('Wallet is still syncing. Try again after sync completes.');
|
||||
}
|
||||
|
||||
@@ -125,11 +125,11 @@ export class MoneroWalletAdminService {
|
||||
}
|
||||
}
|
||||
|
||||
private resolveSyncStatus(walletHeight: number, daemonHeight: number | null): MoneroWalletSyncStatus {
|
||||
private resolveSyncStatus(walletHeight: number, daemonHeight: number | null): WalletSyncStatus {
|
||||
if (daemonHeight === null) {
|
||||
return MoneroWalletSyncStatus.Unknown;
|
||||
return WalletSyncStatus.Unknown;
|
||||
}
|
||||
|
||||
return walletHeight >= daemonHeight - 1 ? MoneroWalletSyncStatus.Synced : MoneroWalletSyncStatus.Syncing;
|
||||
return walletHeight >= daemonHeight - 1 ? WalletSyncStatus.Synced : WalletSyncStatus.Syncing;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { MoneroNetwork } from '../../../types/MoneroNetwork';
|
||||
import { MoneroWalletSyncStatus } from './MoneroWalletSyncStatus';
|
||||
import { WalletSyncStatus } from '../../../types/wallet/WalletSyncStatus';
|
||||
|
||||
export interface MoneroWalletStatusView {
|
||||
network: MoneroNetwork;
|
||||
rpcVersion: string;
|
||||
walletHeight: number;
|
||||
daemonHeight: number | null;
|
||||
syncStatus: MoneroWalletSyncStatus;
|
||||
syncStatus: WalletSyncStatus;
|
||||
balanceXmr: string;
|
||||
unlockedBalanceXmr: string;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
export enum MoneroWalletSyncStatus {
|
||||
export enum WalletSyncStatus {
|
||||
Synced = 'synced',
|
||||
Syncing = 'syncing',
|
||||
Unknown = 'unknown'
|
||||
Vendored
+2
-1
@@ -11,6 +11,7 @@ export {}
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
BitcoinWallet: typeof import('./components/wallet/BitcoinWallet.vue')['default']
|
||||
CmsListPagination: typeof import('./components/CmsListPagination.vue')['default']
|
||||
CreateOrEditCategoryModal: typeof import('./components/CreateOrEditCategoryModal.vue')['default']
|
||||
CreateOrEditDiscountCodeModal: typeof import('./components/CreateOrEditDiscountCodeModal.vue')['default']
|
||||
@@ -56,9 +57,9 @@ declare module 'vue' {
|
||||
MoneroWallet: typeof import('./components/wallet/MoneroWallet.vue')['default']
|
||||
OrderCartPanel: typeof import('./components/OrderCartPanel.vue')['default']
|
||||
OrderChatPanel: typeof import('./components/OrderChatPanel.vue')['default']
|
||||
OrderInvoicePaymentPanel: typeof import('./components/OrderInvoicePaymentPanel.vue')['default']
|
||||
OrderLineAutoFulfillmentModal: typeof import('./components/OrderLineAutoFulfillmentModal.vue')['default']
|
||||
OrderManualShippingQuotePanel: typeof import('./components/OrderManualShippingQuotePanel.vue')['default']
|
||||
OrderMoneroPaymentPanel: typeof import('./components/OrderMoneroPaymentPanel.vue')['default']
|
||||
OrderPaymentPanel: typeof import('./components/OrderPaymentPanel.vue')['default']
|
||||
OrderSummaryPanel: typeof import('./components/OrderSummaryPanel.vue')['default']
|
||||
RichTextEditor: typeof import('./components/RichTextEditor.vue')['default']
|
||||
|
||||
+20
-12
@@ -8,14 +8,12 @@
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="Expected total">
|
||||
<span class="mono"
|
||||
>{{ invoice.expectedTotalCrypto }} {{ paymentMethodCryptoCurrency[invoice.paymentMethod] }}</span
|
||||
>
|
||||
<span class="mono">{{ invoice.expectedTotalCrypto }} {{ invoice.paymentLabel }}</span>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item v-if="fiatPerXmrAtCreation !== undefined" :label="`Rate at ${rateLabel}`">
|
||||
{{ formatFiatPrice(fiatPerXmrAtCreation, config.shopFiatCurrency) }} /
|
||||
{{ paymentMethodCryptoCurrency[invoice.paymentMethod] }}
|
||||
<el-descriptions-item v-if="fiatPerCryptoAtCreation !== undefined" :label="`Rate at ${rateLabel}`">
|
||||
{{ formatFiatPrice(fiatPerCryptoAtCreation, config.shopFiatCurrency) }} /
|
||||
{{ invoice.paymentLabel }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
@@ -37,9 +35,7 @@
|
||||
|
||||
<el-table-column label="Amount" width="140">
|
||||
<template #default="{ row }">
|
||||
<span class="mono"
|
||||
>{{ row.amountCrypto }} {{ paymentMethodCryptoCurrency[invoice.paymentMethod] }}</span
|
||||
>
|
||||
<span class="mono">{{ row.amountCrypto }} {{ invoice.paymentLabel }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -69,7 +65,7 @@
|
||||
import { computed, type PropType } from 'vue';
|
||||
import { config } from '@/config';
|
||||
import type { InvoiceExtended } from '@/types/payment/InvoiceExtended';
|
||||
import { paymentMethodCryptoCurrency } from '@/types/payment/PaymentMethod';
|
||||
import { PaymentMethod } from '@/types/payment/PaymentMethod';
|
||||
import { formatDate } from '@/utils/formatDate';
|
||||
import { formatFiatPrice } from '@/utils/formatFiatPrice';
|
||||
import { resolveInvoiceStatusTagType } from '@/utils/order/resolveInvoiceStatusTagType';
|
||||
@@ -85,13 +81,25 @@ const props = defineProps({
|
||||
},
|
||||
emptyText: {
|
||||
type: String,
|
||||
default: 'No Monero payment session.'
|
||||
default: 'No payment session.'
|
||||
}
|
||||
});
|
||||
|
||||
const payments = computed(() => props.invoice?.payments ?? []);
|
||||
|
||||
const fiatPerXmrAtCreation = computed(() => props.invoice?.moneroDetails?.fiatPerXmrAtCreation);
|
||||
const fiatPerCryptoAtCreation = computed(() => {
|
||||
const invoice = props.invoice;
|
||||
|
||||
if (!invoice) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (invoice.paymentMethod === PaymentMethod.Btc) {
|
||||
return invoice.btcDetails?.fiatPerBtcAtCreation;
|
||||
}
|
||||
|
||||
return invoice.moneroDetails?.fiatPerXmrAtCreation;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -53,10 +53,9 @@
|
||||
</el-descriptions>
|
||||
|
||||
<template v-if="order.shippingInvoice">
|
||||
<order-monero-payment-panel
|
||||
<order-invoice-payment-panel
|
||||
:invoice="order.shippingInvoice"
|
||||
rate-label="quote"
|
||||
empty-text="Shipping payment session not created yet."
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<span>Order payment</span>
|
||||
</template>
|
||||
|
||||
<order-monero-payment-panel
|
||||
<order-invoice-payment-panel
|
||||
:invoice="order.checkoutInvoice"
|
||||
rate-label="checkout"
|
||||
empty-text="No checkout payment session."
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="detail-loading-host" element-loading-text="Loading wallet…">
|
||||
<el-empty v-if="!loading && loadError" description="Failed to load wallet status" />
|
||||
|
||||
<template v-if="!loading && !loadError && walletStatus">
|
||||
<div v-if="walletStatus.syncStatus !== WalletSyncStatus.Synced" class="mb-16">
|
||||
<el-alert type="warning" :closable="false" show-icon title="Wallet is syncing. Please wait." />
|
||||
</div>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between gap-16">
|
||||
<span>Status</span>
|
||||
<el-button type="default" :loading="refreshing" @click="refreshStatus">Refresh</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="Network">{{ walletStatus.network }}</el-descriptions-item>
|
||||
<el-descriptions-item label="RPC version">{{ walletStatus.rpcVersion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Block height">
|
||||
{{ walletStatus.blockHeight ?? 'Unavailable' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="Server height">
|
||||
{{ walletStatus.serverHeight ?? 'Unavailable' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="Sync">
|
||||
<el-tag :type="resolveWalletSyncStatusTagType(walletStatus.syncStatus)" size="small">
|
||||
{{ resolveWalletSyncStatusLabel(walletStatus.syncStatus) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="Total balance">{{ walletStatus.balanceBtc }} BTC</el-descriptions-item>
|
||||
<el-descriptions-item label="Confirmed balance">
|
||||
{{ walletStatus.confirmedBalanceBtc }} BTC
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { onBeforeMount, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { WalletSyncStatus } from '@/types/wallet/WalletSyncStatus';
|
||||
import { useBitcoinWalletStore } from '@/stores/bitcoinWallet';
|
||||
import { resolveAxiosErrorMessage } from '@/utils/resolveAxiosErrorMessage';
|
||||
import { resolveWalletSyncStatusLabel } from '@/utils/wallet/resolveWalletSyncStatusLabel';
|
||||
import { resolveWalletSyncStatusTagType } from '@/utils/wallet/resolveWalletSyncStatusTagType';
|
||||
|
||||
const bitcoinWalletStore = useBitcoinWalletStore();
|
||||
|
||||
const { status: walletStatus } = storeToRefs(bitcoinWalletStore);
|
||||
|
||||
const { fetchStatus } = bitcoinWalletStore;
|
||||
|
||||
const loading = ref(true);
|
||||
const loadError = ref(false);
|
||||
const refreshing = ref(false);
|
||||
|
||||
onBeforeMount(async () => {
|
||||
loading.value = true;
|
||||
|
||||
await loadWalletStatus();
|
||||
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
const loadWalletStatus = async (): Promise<void> => {
|
||||
loadError.value = false;
|
||||
|
||||
try {
|
||||
await fetchStatus();
|
||||
} catch (error) {
|
||||
loadError.value = true;
|
||||
|
||||
ElMessage.error(resolveAxiosErrorMessage(error, 'Failed to load wallet status'));
|
||||
}
|
||||
};
|
||||
|
||||
const refreshStatus = async (): Promise<void> => {
|
||||
refreshing.value = true;
|
||||
|
||||
try {
|
||||
await loadWalletStatus();
|
||||
|
||||
ElMessage.success('Wallet status refreshed');
|
||||
} finally {
|
||||
refreshing.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-empty v-if="!loading && loadError" description="Failed to load wallet status" />
|
||||
|
||||
<template v-if="!loading && !loadError && walletStatus">
|
||||
<div v-if="walletStatus.syncStatus !== MoneroWalletSyncStatus.Synced" class="mb-16">
|
||||
<div v-if="walletStatus.syncStatus !== WalletSyncStatus.Synced" class="mb-16">
|
||||
<el-alert type="warning" :closable="false" show-icon title="Wallet is syncing. Please wait." />
|
||||
</div>
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
{{ walletStatus.daemonHeight ?? 'Unavailable' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="Sync">
|
||||
<el-tag :type="resolveMoneroWalletSyncStatusTagType(walletStatus.syncStatus)" size="small">
|
||||
{{ resolveMoneroWalletSyncStatusLabel(walletStatus.syncStatus) }}
|
||||
<el-tag :type="resolveWalletSyncStatusTagType(walletStatus.syncStatus)" size="small">
|
||||
{{ resolveWalletSyncStatusLabel(walletStatus.syncStatus) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="Total balance">{{ walletStatus.balanceXmr }} XMR</el-descriptions-item>
|
||||
@@ -90,10 +90,12 @@
|
||||
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
|
||||
import { computed, onBeforeMount, reactive, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { MoneroWalletSyncStatus } from '@/types/moneroWallet/MoneroWalletSyncStatus';
|
||||
import { WalletSyncStatus } from '@/types/wallet/WalletSyncStatus';
|
||||
import { useMoneroWalletStore } from '@/stores/moneroWallet';
|
||||
import { isMoneroStandardAddress } from '@/utils/monero/isMoneroStandardAddress';
|
||||
import { resolveAxiosErrorMessage } from '@/utils/resolveAxiosErrorMessage';
|
||||
import { resolveWalletSyncStatusLabel } from '@/utils/wallet/resolveWalletSyncStatusLabel';
|
||||
import { resolveWalletSyncStatusTagType } from '@/utils/wallet/resolveWalletSyncStatusTagType';
|
||||
|
||||
const moneroWalletStore = useMoneroWalletStore();
|
||||
|
||||
@@ -125,7 +127,7 @@ const withdrawFormRules = computed<FormRules>(() => ({
|
||||
destinationAddress: [
|
||||
{
|
||||
validator: (_rule, value, callback) => {
|
||||
if (walletStatus.value?.syncStatus !== MoneroWalletSyncStatus.Synced) {
|
||||
if (walletStatus.value?.syncStatus !== WalletSyncStatus.Synced) {
|
||||
callback(new Error('Wait until the wallet finishes syncing before withdrawing'));
|
||||
|
||||
return;
|
||||
@@ -287,26 +289,4 @@ const onRevealSeedClick = async (): Promise<void> => {
|
||||
const clearSeed = (): void => {
|
||||
revealedMnemonic.value = '';
|
||||
};
|
||||
|
||||
const resolveMoneroWalletSyncStatusLabel = (syncStatus: MoneroWalletSyncStatus): string => {
|
||||
switch (syncStatus) {
|
||||
case MoneroWalletSyncStatus.Synced:
|
||||
return 'Synced';
|
||||
case MoneroWalletSyncStatus.Syncing:
|
||||
return 'Syncing';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
};
|
||||
|
||||
const resolveMoneroWalletSyncStatusTagType = (syncStatus: MoneroWalletSyncStatus): 'success' | 'warning' | 'info' => {
|
||||
switch (syncStatus) {
|
||||
case MoneroWalletSyncStatus.Synced:
|
||||
return 'success';
|
||||
case MoneroWalletSyncStatus.Syncing:
|
||||
return 'warning';
|
||||
default:
|
||||
return 'info';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -7,7 +7,8 @@ export const ROUTE_NAMES = {
|
||||
DiscountCodes: 'DiscountCodes',
|
||||
ShopSettings: 'ShopSettings',
|
||||
Notifications: 'Notifications',
|
||||
Wallet: 'Wallet',
|
||||
MoneroWallet: 'MoneroWallet',
|
||||
BitcoinWallet: 'BitcoinWallet',
|
||||
Orders: 'Orders',
|
||||
OrderDetail: 'OrderDetail'
|
||||
} as const;
|
||||
|
||||
+18
-3
@@ -57,9 +57,10 @@ const router = createRouter({
|
||||
path: '/settings',
|
||||
component: () => import('../views/CmsSettingsLayout.vue'),
|
||||
meta: { requiresAuth: true, title: 'CMS - Settings', activeMenu: '/settings' },
|
||||
redirect: { name: ROUTE_NAMES.ShopSettings },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
path: 'shop',
|
||||
name: ROUTE_NAMES.ShopSettings,
|
||||
component: () => import('../views/CmsShopSettingsView.vue'),
|
||||
meta: { requiresAuth: true, title: 'CMS - Shop settings', activeMenu: '/settings' }
|
||||
@@ -74,9 +75,23 @@ const router = createRouter({
|
||||
},
|
||||
{
|
||||
path: '/wallet',
|
||||
name: ROUTE_NAMES.Wallet,
|
||||
component: () => import('../views/CmsWalletView.vue'),
|
||||
meta: { requiresAuth: true, title: 'CMS - Wallet' }
|
||||
meta: { requiresAuth: true, title: 'CMS - Wallet', activeMenu: '/wallet' },
|
||||
redirect: { name: ROUTE_NAMES.MoneroWallet },
|
||||
children: [
|
||||
{
|
||||
path: 'monero',
|
||||
name: ROUTE_NAMES.MoneroWallet,
|
||||
component: () => import('../components/wallet/MoneroWallet.vue'),
|
||||
meta: { requiresAuth: true, title: 'CMS - Monero wallet', activeMenu: '/wallet' }
|
||||
},
|
||||
{
|
||||
path: 'bitcoin',
|
||||
name: ROUTE_NAMES.BitcoinWallet,
|
||||
component: () => import('../components/wallet/BitcoinWallet.vue'),
|
||||
meta: { requiresAuth: true, title: 'CMS - Bitcoin wallet', activeMenu: '/wallet' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref } from 'vue';
|
||||
import { api } from '@/plugins/axios';
|
||||
import type { BitcoinWalletStatus } from '@/types/bitcoinWallet/BitcoinWalletStatus';
|
||||
|
||||
export const useBitcoinWalletStore = defineStore('bitcoinWallet', () => {
|
||||
const status = ref<BitcoinWalletStatus | null>(null);
|
||||
|
||||
const fetchStatus = async (): Promise<BitcoinWalletStatus> => {
|
||||
const { data } = await api.get<BitcoinWalletStatus>('/bitcoin-wallet');
|
||||
|
||||
status.value = data;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
return {
|
||||
status,
|
||||
fetchStatus
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
export type BitcoinNetwork = 'mainnet' | 'testnet4';
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { BitcoinNetwork } from './BitcoinNetwork';
|
||||
import type { WalletSyncStatus } from '../wallet/WalletSyncStatus';
|
||||
|
||||
export interface BitcoinWalletStatus {
|
||||
network: BitcoinNetwork;
|
||||
rpcVersion: string;
|
||||
blockHeight: number | null;
|
||||
serverHeight: number | null;
|
||||
syncStatus: WalletSyncStatus;
|
||||
balanceBtc: string;
|
||||
confirmedBalanceBtc: string;
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { MoneroNetwork } from './MoneroNetwork';
|
||||
import type { MoneroWalletSyncStatus } from './MoneroWalletSyncStatus';
|
||||
import type { WalletSyncStatus } from '../wallet/WalletSyncStatus';
|
||||
|
||||
export interface MoneroWalletStatus {
|
||||
network: MoneroNetwork;
|
||||
rpcVersion: string;
|
||||
walletHeight: number;
|
||||
daemonHeight: number | null;
|
||||
syncStatus: MoneroWalletSyncStatus;
|
||||
syncStatus: WalletSyncStatus;
|
||||
balanceXmr: string;
|
||||
unlockedBalanceXmr: string;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { InvoiceStatusLabel } from './InvoiceStatusLabel';
|
||||
|
||||
export type InvoiceExtended = Omit<Invoice, 'payments'> & {
|
||||
statusLabel: InvoiceStatusLabel | null;
|
||||
paymentLabel: string;
|
||||
expectedTotalCrypto: string;
|
||||
payments: InvoicePaymentExtended[];
|
||||
};
|
||||
|
||||
@@ -2,8 +2,3 @@ export enum PaymentMethod {
|
||||
Xmr = 'xmr',
|
||||
Btc = 'btc'
|
||||
}
|
||||
|
||||
export const paymentMethodCryptoCurrency: Record<PaymentMethod, string> = {
|
||||
[PaymentMethod.Xmr]: 'XMR',
|
||||
[PaymentMethod.Btc]: 'BTC'
|
||||
};
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
export interface BitcoinConfirmationTier {
|
||||
upToTotalFiat?: string;
|
||||
minConfirmations: number;
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
export interface MoneroConfirmationTier {
|
||||
export interface ConfirmationTier {
|
||||
upToTotalFiat?: string;
|
||||
minConfirmations: number;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { BitcoinConfirmationTier } from './BitcoinConfirmationTier';
|
||||
import type { ConfirmationTier } from './ConfirmationTier';
|
||||
|
||||
export interface ShopSettingsBitcoin {
|
||||
confirmationTiers: BitcoinConfirmationTier[];
|
||||
confirmationTiers: ConfirmationTier[];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { MoneroConfirmationTier } from './MoneroConfirmationTier';
|
||||
import type { ConfirmationTier } from './ConfirmationTier';
|
||||
|
||||
export interface ShopSettingsMonero {
|
||||
confirmationTiers: MoneroConfirmationTier[];
|
||||
confirmationTiers: ConfirmationTier[];
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
export enum MoneroWalletSyncStatus {
|
||||
export enum WalletSyncStatus {
|
||||
Synced = 'synced',
|
||||
Syncing = 'syncing',
|
||||
Unknown = 'unknown'
|
||||
@@ -0,0 +1,12 @@
|
||||
import { WalletSyncStatus } from '@/types/wallet/WalletSyncStatus';
|
||||
|
||||
export const resolveWalletSyncStatusLabel = (syncStatus: WalletSyncStatus): string => {
|
||||
switch (syncStatus) {
|
||||
case WalletSyncStatus.Synced:
|
||||
return 'Synced';
|
||||
case WalletSyncStatus.Syncing:
|
||||
return 'Syncing';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
import { WalletSyncStatus } from '@/types/wallet/WalletSyncStatus';
|
||||
|
||||
export const resolveWalletSyncStatusTagType = (syncStatus: WalletSyncStatus): 'success' | 'warning' | 'info' => {
|
||||
switch (syncStatus) {
|
||||
case WalletSyncStatus.Synced:
|
||||
return 'success';
|
||||
case WalletSyncStatus.Syncing:
|
||||
return 'warning';
|
||||
default:
|
||||
return 'info';
|
||||
}
|
||||
};
|
||||
@@ -37,7 +37,14 @@
|
||||
<el-descriptions-item label="Monero confirmation tiers">
|
||||
<ul class="m-0 pl-20">
|
||||
<li v-for="(tier, index) in settings.monero.confirmationTiers" :key="index">
|
||||
{{ formatMoneroConfirmationTier(tier, settings.shopFiatCurrency) }}
|
||||
{{ formatConfirmationTier(tier, settings.shopFiatCurrency) }}
|
||||
</li>
|
||||
</ul>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="Bitcoin confirmation tiers">
|
||||
<ul class="m-0 pl-20">
|
||||
<li v-for="(tier, index) in settings.bitcoin.confirmationTiers" :key="index">
|
||||
{{ formatConfirmationTier(tier, settings.shopFiatCurrency) }}
|
||||
</li>
|
||||
</ul>
|
||||
</el-descriptions-item>
|
||||
@@ -210,7 +217,7 @@
|
||||
<script setup lang="ts">
|
||||
import { config } from '@/config';
|
||||
import { useShopSettingsStore } from '@/stores/shopSettings';
|
||||
import type { MoneroConfirmationTier } from '@/types/shopSettings/MoneroConfirmationTier';
|
||||
import type { ConfirmationTier } from '@/types/shopSettings/ConfirmationTier';
|
||||
import { buildUploadHint } from '@/utils/upload/buildUploadHint';
|
||||
import { resolveAxiosErrorMessage } from '@/utils/resolveAxiosErrorMessage';
|
||||
import { resolveUploadPublicUrl } from '@/utils/upload/resolveUploadPublicUrl';
|
||||
@@ -460,7 +467,7 @@ const submitShippingNote = async (): Promise<void> => {
|
||||
}
|
||||
};
|
||||
|
||||
const formatMoneroConfirmationTier = (tier: MoneroConfirmationTier, currency: string): string => {
|
||||
const formatConfirmationTier = (tier: ConfirmationTier, currency: string): string => {
|
||||
const requirement = tier.minConfirmations === 0 ? '0 (tx-detected)' : `${tier.minConfirmations} confirmations`;
|
||||
|
||||
if (tier.upToTotalFiat === undefined) {
|
||||
|
||||
@@ -2,6 +2,31 @@
|
||||
<div>
|
||||
<h3 class="m-0 mb-16">Wallet</h3>
|
||||
|
||||
<monero-wallet />
|
||||
<el-tabs :model-value="activeTab" class="mb-24" @tab-change="onTabChange">
|
||||
<el-tab-pane label="Monero (XMR)" name="monero" />
|
||||
<el-tab-pane label="Bitcoin (BTC)" name="bitcoin" />
|
||||
</el-tabs>
|
||||
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ROUTE_NAMES } from '@/consts/routeNames';
|
||||
import { computed } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const activeTab = computed(() => (route.name === ROUTE_NAMES.BitcoinWallet ? 'bitcoin' : 'monero'));
|
||||
|
||||
const onTabChange = (tabName: string | number) => {
|
||||
if (tabName === 'bitcoin') {
|
||||
router.push({ name: ROUTE_NAMES.BitcoinWallet });
|
||||
return;
|
||||
}
|
||||
|
||||
router.push({ name: ROUTE_NAMES.MoneroWallet });
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user