feat: 更新钱包状态管理,优化资产获取逻辑,支持资金和交易账户的分离

This commit is contained in:
2025-12-24 05:28:49 +07:00
parent 64b455dfa6
commit dd1dbd485f
10 changed files with 109 additions and 40 deletions

View File

@@ -13,7 +13,9 @@ export type TreatyBody<T> = T extends (...args: any[]) => any
export type DepositFiatData = Treaty.Data<typeof client.api.deposit.fiat.post>;
export type BalancesData = Treaty.Data<typeof client.api.asset.balances.get>;
export type BalancesData = Treaty.Data<typeof client.api.wallet.balances.get>;
export type TotalAssetValue = Treaty.Data<typeof client.api.wallet.total_value.get>;
export type WithdrawBody = Omit<Parameters<typeof client.api.withdraw.post>[0], "assetCode" | "withdrawMethod"> & {
assetCode: AssetCodeEnum;

View File

@@ -13,8 +13,8 @@ const emit = defineEmits<{
const { t } = useI18n();
const walletStore = useWalletStore();
const { balances } = storeToRefs(walletStore);
const currentUSDTBalance = computed(() => balances.value[0].available);
const { fundingBalances } = storeToRefs(walletStore);
const currentUSDTBalance = computed(() => fundingBalances.value[0].available);
const num = ref<number | null>(null);

View File

@@ -1,36 +1,55 @@
import type { BalancesData, BankAccountsData, SupportBanksData } from "@/api/types";
import type { BalancesData, BankAccountsData, SupportBanksData, TotalAssetValue } from "@/api/types";
import { defineStore } from "pinia";
import { client, safeClient } from "@/api";
interface State {
balances: BalancesData;
totalAssetValue: TotalAssetValue;
fundingBalances: BalancesData;
tradingBalances: BalancesData;
bankAccounts: BankAccountsData["data"];
supportBanks: SupportBanksData["data"];
}
export const useWalletStore = defineStore("wallet", () => {
const state = reactive<State>({
balances: [],
totalAssetValue: {
fundingValueUsd: "0",
tradingValueUsd: "0",
totalValueUsd: "0",
},
fundingBalances: [],
tradingBalances: [],
bankAccounts: [],
supportBanks: [],
});
async function initializeWallet() {
updateBalances();
updateBankAccounts();
updateSupportBanks();
syncTotalAssetValue();
syncFundingBalances();
syncTradingBalances();
syncBankAccounts();
}
async function updateBalances(data?: BalancesData) {
if (data) {
state.balances = data;
return;
}
const { data: balances } = await safeClient(() => client.api.wallet.balances.get(), { silent: true });
state.balances = balances.value || [];
async function syncTotalAssetValue() {
const { data } = await safeClient(() => client.api.wallet.total_value.get(), { silent: true });
if (data.value)
state.totalAssetValue = data.value;
}
async function syncFundingBalances() {
const { data: balances } = await safeClient(() => client.api.wallet.balances.get({
query: { accountType: "funding" },
}), { silent: true });
state.fundingBalances = balances.value || [];
}
async function updateBankAccounts(data?: BankAccountsData["data"]) {
async function syncTradingBalances() {
const { data: balances } = await safeClient(() => client.api.wallet.balances.get({
query: { accountType: "trading" },
}), { silent: true });
state.tradingBalances = balances.value || [];
}
async function syncBankAccounts(data?: BankAccountsData["data"]) {
if (data) {
state.bankAccounts = data;
return;
@@ -39,7 +58,7 @@ export const useWalletStore = defineStore("wallet", () => {
state.bankAccounts = bankAccounts.value?.data || [];
}
async function updateSupportBanks() {
async function syncSupportBanks() {
const { data: banks } = await safeClient(() => client.api.bank_account.banks.get(), { silent: true });
state.supportBanks = banks.value?.data || [];
}
@@ -47,8 +66,9 @@ export const useWalletStore = defineStore("wallet", () => {
return {
...toRefs(state),
initializeWallet,
updateBalances,
updateBankAccounts,
updateSupportBanks,
syncFundingBalances,
syncTradingBalances,
syncBankAccounts,
syncSupportBanks,
};
});

View File

@@ -11,13 +11,13 @@ import { client, safeClient } from "@/api";
const { t } = useI18n();
const router = useRouter();
const { updateBankAccounts } = useWalletStore();
const { syncBankAccounts } = useWalletStore();
const { data, execute, onFetchResponse } = await safeClient(() => client.api.bank_account.get());
const bankCards = computed(() => data.value?.data || []);
onFetchResponse((data) => {
data?.data && updateBankAccounts(data.data);
data?.data && syncBankAccounts(data.data);
});
function handleAddCard() {

View File

@@ -1,17 +1,44 @@
<script lang='ts' setup>
import SolarDollarMinimalisticBoldDuotone from "~icons/solar/dollar-minimalistic-bold-duotone";
import SolarRoundTransferHorizontalBoldDuotone from "~icons/solar/round-transfer-horizontal-bold-duotone";
import { getCryptoIcon } from "@/config/crypto";
const walletStore = useWalletStore();
const { balances } = storeToRefs(walletStore);
const { fundingBalances, totalAssetValue } = storeToRefs(walletStore);
</script>
<template>
<div>
<ion-label class="text-xs font-medium text-text-300">
Asset Distribution
</ion-label>
<div class="grid grid-cols-2 gap-4 mt-2">
<div class="asset-card">
<div class="text-xs text-text-400 font-semibold flex items-center gap-1">
<SolarDollarMinimalisticBoldDuotone />
资金账户
</div>
<div class="font-bold">
${{ totalAssetValue.fundingValueUsd }}
</div>
</div>
<div class="asset-card">
<div class="text-xs text-text-400 font-semibold flex items-center gap-1">
<SolarRoundTransferHorizontalBoldDuotone />
交易账户
</div>
<div class="font-bold">
${{ totalAssetValue.tradingValueUsd }}
</div>
</div>
</div>
<ion-label class="text-xs font-medium text-text-300">
Asset
</ion-label>
<ion-list lines="none" class="space-y-5 mt-2!">
<ion-item v-for="asset, i in balances" :key="i" class="">
<ion-item v-for="asset, i in fundingBalances" :key="i" class="">
<div class="flex items-center space-x-3 flex-1">
<component :is="getCryptoIcon(asset.assetCode)" class="w-8 h-8" />
<div class="space-y-1">
@@ -32,7 +59,16 @@ const { balances } = storeToRefs(walletStore);
</template>
<style lang='css' scoped>
@reference "tailwindcss";
ion-item::part(native) {
--padding-start: 0;
}
.asset-card {
@apply flex flex-col justify-between py-2 px-4 bg-gray-100 rounded-lg mb-3 gap-2;
}
.ion-palette-dark .asset-card {
@apply bg-[#151515];
}
</style>

View File

@@ -8,12 +8,10 @@ import RechargeChannel from "./recharge-channel.vue";
const { t } = useI18n();
const router = useRouter();
const walletStore = useWalletStore();
const { balances } = storeToRefs(walletStore);
const { totalAssetValue } = storeToRefs(walletStore);
const rechargeInstance = ref<ModalInstance>();
const totalBalanceVisible = useStorage("total-balances-visible", true);
const totalBalance = computed(() => {
return balances.value.reduce((acc, item) => acc + Number(item.available), 0);
});
const totalAsset = computed(() => Number(totalAssetValue.value.totalValueUsd).toFixed(2));
function onCloseModal() {
rechargeInstance.value?.$el.dismiss(null, "confirm");
@@ -26,7 +24,8 @@ function handleBill() {
}
onMounted(() => {
walletStore.updateBalances();
walletStore.syncFundingBalances();
walletStore.syncTradingBalances();
});
</script>
@@ -38,7 +37,7 @@ onMounted(() => {
</div>
<div class="flex items-end gap-2">
<div class="text-2xl font-bold">
{{ totalBalanceVisible ? totalBalance : Array(totalBalance.toString().length).fill("*").join("") }}
{{ totalBalanceVisible ? totalAsset : Array(totalAsset.toString().length).fill("*").join("") }}
</div>
<div class="text-md font-bold">
USDT

View File

@@ -10,7 +10,7 @@ import { createWithdrawSchema } from "./rules";
const { t } = useI18n();
const router = useRouter();
const walletStore = useWalletStore();
const { balances, bankAccounts } = storeToRefs(walletStore);
const { fundingBalances, bankAccounts } = storeToRefs(walletStore);
const initialValues: WithdrawBody = {
assetCode: AssetCodeEnum.USDT,
@@ -22,7 +22,7 @@ const initialValues: WithdrawBody = {
};
const maxAmount = computed(() => {
const balance = balances.value?.find(item => item.assetCode === initialValues.assetCode);
const balance = fundingBalances.value?.find(item => item.assetCode === initialValues.assetCode);
return balance ? balance.available : "0";
});