diff --git a/src/components/DepositDialog.vue b/src/components/DepositDialog.vue index aaa42b6..75e2bad 100644 --- a/src/components/DepositDialog.vue +++ b/src/components/DepositDialog.vue @@ -7,192 +7,398 @@ content-class="deposit-dialog" @update:model-value="$emit('update:modelValue', $event)" > - +
-

{{ t('deposit.title') }}

-

{{ t('deposit.polymarketBalance') }} ${{ balance }}

- - mdi-close +
+

+ {{ + step === 'crypto' + ? t('deposit.transferCrypto') + : step === 'exchange' + ? t('deposit.connectExchange') + : t('deposit.title') + }} +

+ + mdi-check-circle + {{ t('deposit.connectedTipMetaMask') }} + +
+ + mdi-close
- + - + - + + + + +
diff --git a/src/components/WithdrawDialog.vue b/src/components/WithdrawDialog.vue index 6927dfb..5b67819 100644 --- a/src/components/WithdrawDialog.vue +++ b/src/components/WithdrawDialog.vue @@ -7,15 +7,15 @@ content-class="withdraw-dialog" @update:model-value="$emit('update:modelValue', $event)" > - +

{{ t('withdraw.title') }}

-

{{ t('withdraw.polymarketBalance') }} ${{ balance }}

- mdi-close + mdi-close
+

{{ t('withdraw.polymarketBalance') }} ${{ balance }}

- - - - - - - -
- -
- {{ t('withdraw.customAddressNotSupported') || 'Custom address is not supported for this withdrawal.' }} + +
+ + {{ t('withdraw.connectingWallet') }} +
+
+ mdi-check-circle + {{ shortAddress(connectedAddress) }} +
{{ amountError }}
{{ errorMessage }}
@@ -112,10 +85,13 @@ import { useI18n } from 'vue-i18n' import { BrowserProvider } from 'ethers' import { SiweMessage } from 'siwe' import { useUserStore } from '@/stores/user' +import { useToastStore } from '@/stores/toast' import { withdrawByWallet, usdcToAmount } from '@/api/pmset' +import { WALLET_PRIMARY_NETWORK_ID, useWalletNetworkGuard } from '@/composables/useWalletNetworkPolicy' const { t } = useI18n() const userStore = useUserStore() +const toastStore = useToastStore() const props = withDefaults( defineProps<{ modelValue: boolean @@ -126,9 +102,7 @@ const props = withDefaults( const emit = defineEmits<{ 'update:modelValue': [value: boolean]; success: [] }>() const amount = ref('') -const selectedNetwork = ref('polygon') -const destinationType = ref<'wallet' | 'address'>('wallet') -const customAddress = ref('') +const selectedNetwork = ref(WALLET_PRIMARY_NETWORK_ID) const connectedAddress = ref('') const connecting = ref(false) const submitting = ref(false) @@ -141,6 +115,17 @@ const networks = [ { id: 'optimism', label: 'Optimism' }, ] +const withdrawNetworkGuardActive = computed(() => props.modelValue) +const { onWalletNetworkChange } = useWalletNetworkGuard( + selectedNetwork, + withdrawNetworkGuardActive, + (msg, type) => { + toastStore.show(msg, type ?? 'warning') + }, + t, + 'deposit.networkNotSupportedYet', +) + const balanceNum = computed(() => parseFloat(props.balance) || 0) const amountNum = computed(() => parseFloat(amount.value) || 0) @@ -151,11 +136,8 @@ const amountError = computed(() => { return '' }) -/** 仅支持已连接钱包提现(需验签);自定义地址暂不支持 */ -const hasValidDestination = computed(() => { - if (destinationType.value === 'wallet') return !!connectedAddress.value - return false -}) +/** 仅提现到登录钱包:打开弹窗时已连接并校验地址 */ +const hasValidDestination = computed(() => !!connectedAddress.value) const canSubmit = computed( () => @@ -185,22 +167,44 @@ function allowDecimal(e: KeyboardEvent) { if (key !== '.' && !/^\d$/.test(key)) e.preventDefault() } -async function connectWallet() { +function resolveUserLoginWalletAddress(): string | undefined { + const u = userStore.user as Record | null + const raw = + (u?.externalWalletAddress as string | undefined) || (u?.walletAddress as string | undefined) + if (raw && /^0x[0-9a-fA-F]{40}$/.test(raw)) return raw + return undefined +} + +/** 打开弹窗时自动连接浏览器钱包,且必须与登录账户地址一致 */ +async function autoConnectWallet() { + connectedAddress.value = '' + errorMessage.value = '' if (!window.ethereum) { errorMessage.value = t('deposit.installMetaMask') return } connecting.value = true - errorMessage.value = '' try { - const accounts = (await window.ethereum.request({ method: 'eth_requestAccounts' })) as string[] - connectedAddress.value = accounts[0] || '' - if (!connectedAddress.value) { - errorMessage.value = t('withdraw.connectFailed') || 'Failed to connect wallet' + await userStore.fetchUserInfo() + const expected = resolveUserLoginWalletAddress() + if (!expected) { + errorMessage.value = t('withdraw.externalWalletRequired') + return } + const accounts = (await window.ethereum.request({ method: 'eth_requestAccounts' })) as string[] + const addr = accounts[0] || '' + if (!addr) { + errorMessage.value = t('withdraw.connectFailed') + return + } + if (addr.toLowerCase() !== expected.toLowerCase()) { + errorMessage.value = t('withdraw.walletMismatch') + return + } + connectedAddress.value = addr } catch (e) { console.error(e) - errorMessage.value = (e as Error)?.message || 'Failed to connect wallet' + errorMessage.value = (e as Error)?.message || t('withdraw.connectFailed') } finally { connecting.value = false } @@ -247,9 +251,9 @@ async function submitWithdraw() { errorMessage.value = t('withdraw.connectWalletFirst') || 'Please connect wallet first' return } - const walletAddr = userStore.user?.externalWalletAddress as string | undefined - if (!walletAddr || !/^0x[0-9a-fA-F]{40}$/.test(walletAddr)) { - errorMessage.value = t('withdraw.externalWalletRequired') || 'External wallet address is required' + const walletAddr = resolveUserLoginWalletAddress() + if (!walletAddr) { + errorMessage.value = t('withdraw.externalWalletRequired') return } submitting.value = true @@ -287,45 +291,70 @@ async function submitWithdraw() { watch( () => props.modelValue, - (open) => { + async (open) => { if (!open) { amount.value = '' - destinationType.value = 'wallet' - customAddress.value = '' + selectedNetwork.value = WALLET_PRIMARY_NETWORK_ID connectedAddress.value = '' errorMessage.value = '' + return } + await autoConnectWallet() }, )