新增: 充值二维码
This commit is contained in:
parent
50e451e892
commit
eeb1aac86c
2
.env
2
.env
@ -1,6 +1,6 @@
|
|||||||
# API 基础地址,不设置时默认 https://api.xtrader.vip
|
# API 基础地址,不设置时默认 https://api.xtrader.vip
|
||||||
# 连接测试服务器 192.168.3.21:8888 时复制本文件为 .env 或 .env.local 并取消下一行注释:
|
# 连接测试服务器 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),可选覆盖
|
# SSH 部署(npm run deploy),可选覆盖
|
||||||
# DEPLOY_HOST=38.246.250.238
|
# DEPLOY_HOST=38.246.250.238
|
||||||
|
|||||||
@ -158,7 +158,7 @@ function encodeFunctionCall(abiFragment: string, args: any[]): string {
|
|||||||
data += addr.padStart(64, '0');
|
data += addr.padStart(64, '0');
|
||||||
|
|
||||||
// 数量参数(补零到32字节)
|
// 数量参数(补零到32字节)
|
||||||
let amount = BigInt(args[1]).toString(16);
|
const amount = BigInt(args[1]).toString(16);
|
||||||
data += amount.padStart(64, '0');
|
data += amount.padStart(64, '0');
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
51
src/api/wallet.ts
Normal file
51
src/api/wallet.ts
Normal 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 }
|
||||||
|
}
|
||||||
|
|
||||||
@ -147,6 +147,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { getDepositAddress } from '@/api/wallet'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
@ -158,7 +160,10 @@ const props = withDefaults(
|
|||||||
)
|
)
|
||||||
const emit = defineEmits<{ 'update:modelValue': [value: boolean] }>()
|
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 step = ref<'method' | 'crypto' | 'exchange'>('method')
|
||||||
const selectedNetwork = ref('ethereum')
|
const selectedNetwork = ref('ethereum')
|
||||||
@ -174,12 +179,12 @@ const networks = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const depositAddressShort = computed(() => {
|
const depositAddressShort = computed(() => {
|
||||||
const a = DEPOSIT_ADDRESS
|
const a = depositAddress.value
|
||||||
return a ? `${a.slice(0, 6)}...${a.slice(-4)}` : ''
|
return a ? `${a.slice(0, 6)}...${a.slice(-4)}` : ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const qrCodeUrl = computed(() => {
|
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() {
|
function close() {
|
||||||
@ -189,11 +194,13 @@ function close() {
|
|||||||
function selectMethod(m: 'crypto' | 'exchange') {
|
function selectMethod(m: 'crypto' | 'exchange') {
|
||||||
step.value = m
|
step.value = m
|
||||||
if (m === 'exchange') exchangeConnected.value = false
|
if (m === 'exchange') exchangeConnected.value = false
|
||||||
|
if (m === 'crypto') fetchAddress()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyAddress() {
|
async function copyAddress() {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(DEPOSIT_ADDRESS)
|
if (!depositAddress.value) return
|
||||||
|
await navigator.clipboard.writeText(depositAddress.value)
|
||||||
copied.value = true
|
copied.value = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
copied.value = false
|
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(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(open) => {
|
(open) => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
step.value = 'method'
|
step.value = 'method'
|
||||||
exchangeConnected.value = false
|
exchangeConnected.value = false
|
||||||
|
depositAddress.value = ''
|
||||||
|
loadError.value = ''
|
||||||
|
loading.value = false
|
||||||
|
} else {
|
||||||
|
if (step.value === 'crypto') fetchAddress()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch(selectedNetwork, () => {
|
||||||
|
if (step.value === 'crypto') fetchAddress()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user