新增:充值二维码

This commit is contained in:
lanxi 2026-03-09 15:02:12 +08:00
parent 50e451e892
commit fe1c6e8ad0
4 changed files with 106 additions and 6 deletions

2
.env
View File

@ -1,6 +1,6 @@
# API 基础地址,不设置时默认 https://api.xtrader.vip
# 连接测试服务器 192.168.3.21:8888 时复制本文件为 .env 或 .env.local 并取消下一行注释:
# VITE_API_BASE_URL=http://10.117.63.212:8888
VITE_API_BASE_URL=http://localhost:8888
# SSH 部署npm run deploy可选覆盖
# DEPLOY_HOST=38.246.250.238

View File

@ -158,7 +158,7 @@ function encodeFunctionCall(abiFragment: string, args: any[]): string {
data += addr.padStart(64, '0');
// 数量参数补零到32字节
let amount = BigInt(args[1]).toString(16);
const amount = BigInt(args[1]).toString(16);
data += amount.padStart(64, '0');
return data;

51
src/api/wallet.ts Normal file
View File

@ -0,0 +1,51 @@
import { get } from './request'
export interface DepositAddressData {
address?: string
depositAddress?: string
tokenAddress?: string
walletAddress?: string
[key: string]: unknown
}
export interface DepositAddressResponse {
code: number
data?: DepositAddressData
msg?: string
}
export interface GetDepositAddressParams {
chain: string
tokenSymbol?: string
}
function pickAddress(d: DepositAddressData | undefined): string | undefined {
if (!d) return undefined
return (
(d.walletAddress as string | undefined) ??
(d.externalWalletAddress as string | undefined) ??
(d.depositAddress as string | undefined) ??
(d.tokenAddress as string | undefined) ??
(d.address as string | undefined)
)
}
export async function getDepositAddress(
params: GetDepositAddressParams,
config?: { headers?: Record<string, string> },
): Promise<{ ok: boolean; address?: string; raw?: DepositAddressResponse }> {
const paths = ['/pmset/getDepositAddress', '/wallet/getDepositAddress', '/pmset/getDepositAddressClient']
for (const p of paths) {
try {
const res = await get<DepositAddressResponse>(p, params as any, config)
const codeOk = res.code === 0 || res.code === 200
const addr = pickAddress(res.data)
if (codeOk && addr && typeof addr === 'string' && addr.length > 0) {
return { ok: true, address: addr, raw: res }
}
} catch {
}
}
return { ok: false }
}

View File

@ -147,6 +147,8 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { getDepositAddress } from '@/api/wallet'
import { useUserStore } from '@/stores/user'
const { t } = useI18n()
const props = withDefaults(
@ -158,7 +160,10 @@ const props = withDefaults(
)
const emit = defineEmits<{ 'update:modelValue': [value: boolean] }>()
const DEPOSIT_ADDRESS = '0x742d35Cc6634C0532925a3b844Bc454e4438f44e'
const userStore = useUserStore()
const depositAddress = ref('')
const loading = ref(false)
const loadError = ref('')
const step = ref<'method' | 'crypto' | 'exchange'>('method')
const selectedNetwork = ref('ethereum')
@ -174,12 +179,12 @@ const networks = [
]
const depositAddressShort = computed(() => {
const a = DEPOSIT_ADDRESS
const a = depositAddress.value
return a ? `${a.slice(0, 6)}...${a.slice(-4)}` : ''
})
const qrCodeUrl = computed(() => {
return `https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${encodeURIComponent(DEPOSIT_ADDRESS)}`
return `https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${encodeURIComponent(depositAddress.value)}`
})
function close() {
@ -189,11 +194,13 @@ function close() {
function selectMethod(m: 'crypto' | 'exchange') {
step.value = m
if (m === 'exchange') exchangeConnected.value = false
if (m === 'crypto') fetchAddress()
}
async function copyAddress() {
try {
await navigator.clipboard.writeText(DEPOSIT_ADDRESS)
if (!depositAddress.value) return
await navigator.clipboard.writeText(depositAddress.value)
copied.value = true
setTimeout(() => {
copied.value = false
@ -219,15 +226,57 @@ async function connectMetaMask() {
}
}
async function fetchAddress() {
loading.value = true
loadError.value = ''
try {
if (!userStore.user) {
await userStore.fetchUserInfo?.()
}
const u = userStore.user as Record<string, unknown> | null
const userAddr =
(u?.walletAddress as string | undefined) ||
(u?.externalWalletAddress as string | undefined)
if (userAddr && typeof userAddr === 'string' && userAddr.length > 0) {
depositAddress.value = userAddr
return
}
const headers = userStore.getAuthHeaders?.()
const resApi = await getDepositAddress(
{ chain: selectedNetwork.value, tokenSymbol: 'USDC' },
headers ? { headers } : undefined,
)
if (resApi.ok && resApi.address) {
depositAddress.value = resApi.address
return
}
depositAddress.value = ''
loadError.value = 'failed'
} catch {
loadError.value = 'failed'
} finally {
loading.value = false
}
}
watch(
() => props.modelValue,
(open) => {
if (!open) {
step.value = 'method'
exchangeConnected.value = false
depositAddress.value = ''
loadError.value = ''
loading.value = false
} else {
if (step.value === 'crypto') fetchAddress()
}
},
)
watch(selectedNetwork, () => {
if (step.value === 'crypto') fetchAddress()
})
</script>
<style scoped>