initial
This commit is contained in:
451
apps/client/pages/create/withdraw/[projectId]/[assetCode].vue
Normal file
451
apps/client/pages/create/withdraw/[projectId]/[assetCode].vue
Normal file
@@ -0,0 +1,451 @@
|
||||
<template>
|
||||
<form
|
||||
class="create-withdraw"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<Transition
|
||||
name="shift"
|
||||
mode="out-in"
|
||||
>
|
||||
<div
|
||||
v-if="!showSummary"
|
||||
class="withdraw-form"
|
||||
title="Withdrawal request"
|
||||
>
|
||||
<FormHeader
|
||||
class="withdraw-form__header"
|
||||
title="Withdrawal request"
|
||||
:back-link="`/projects/${$route.params.projectId}`"
|
||||
:back-text="$t('back_to', [project.name])"
|
||||
/>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-between mb-16">
|
||||
<CurrencyName
|
||||
:code="route.params.assetCode"
|
||||
name="Tether"
|
||||
class="create-withdraw__currency-name"
|
||||
/>
|
||||
|
||||
<p class="create-withdraw__balance">
|
||||
{{ balance }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="p-16 bg-clr-grey-200"
|
||||
style="border-radius: 16px"
|
||||
>
|
||||
<UiInput
|
||||
id="paymentAddress"
|
||||
rules="required"
|
||||
label="Withdrawal wallet"
|
||||
/>
|
||||
|
||||
<NetworkSelect
|
||||
id="network"
|
||||
:asset-code="route.params.assetCode"
|
||||
model-value="TRC20"
|
||||
class="mt-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="mt-16 p-16 bg-clr-grey-200"
|
||||
style="border-radius: 16px"
|
||||
>
|
||||
<UiInput
|
||||
id="amount"
|
||||
rules="required"
|
||||
:label="`Минимальная сумма ${minAmount} ${route.params.assetCode}`"
|
||||
:mask="{
|
||||
mask: Number,
|
||||
min: minAmount,
|
||||
max: maxAmount,
|
||||
scale: exponent,
|
||||
}"
|
||||
>
|
||||
<template #suffix>
|
||||
<UiButton
|
||||
type="link"
|
||||
size="small"
|
||||
@click="setValues({ amount: maxAmount }, false)"
|
||||
>
|
||||
{{ $t('maximum') }}
|
||||
</UiButton>
|
||||
</template>
|
||||
|
||||
<template #caption>
|
||||
<div class="create-withdraw__limit">
|
||||
<span>Доступный лимит на вывод - 1000 USDT</span>
|
||||
|
||||
<UiButton
|
||||
class="create-withdraw__upgrade"
|
||||
type="link"
|
||||
size="small"
|
||||
href="/verification"
|
||||
>
|
||||
Повысить лимит
|
||||
</UiButton>
|
||||
</div>
|
||||
</template>
|
||||
</UiInput>
|
||||
</div>
|
||||
|
||||
<div class="withdraw-form__bottom">
|
||||
<div class="withdraw-amount withdraw-amount--fee">
|
||||
<div class="withdraw-amount__title">
|
||||
{{ $t('fee') }}
|
||||
</div>
|
||||
|
||||
<div class="withdraw-amount__value">
|
||||
{{ fee }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="withdraw-amount">
|
||||
<div class="withdraw-amount__title">
|
||||
К отправке
|
||||
</div>
|
||||
|
||||
<div class="withdraw-amount__value">
|
||||
{{ total }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UiButton
|
||||
size="large"
|
||||
class="create-withdraw__continue"
|
||||
native-type="submit"
|
||||
:disabled="balance <= 0"
|
||||
>
|
||||
{{ $t('continue') }}
|
||||
</UiButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="withdraw-summary"
|
||||
>
|
||||
<FormHeader
|
||||
class="withdraw-summary__header"
|
||||
title="Confirm the withdrawal"
|
||||
:back-link="`/projects/${$route.params.projectId}`"
|
||||
:back-text="$t('back_to', [project.name])"
|
||||
/>
|
||||
|
||||
<dl class="withdraw-summary__details withdraw-details">
|
||||
<dt>Withdrawal wallet</dt>
|
||||
<dd>
|
||||
<TextShortener :text="values.paymentAddress" />
|
||||
</dd>
|
||||
|
||||
<dt>Network</dt>
|
||||
<dd class="text-clr-green-500">
|
||||
<CurrencyName
|
||||
:code="route.params.assetCode"
|
||||
size="small"
|
||||
/>
|
||||
</dd>
|
||||
|
||||
<dt>{{ $t('fee') }}</dt>
|
||||
<dd>{{ fee }}</dd>
|
||||
|
||||
<dt>К отправке</dt>
|
||||
<dd class="withdraw-details__amount">
|
||||
{{ total }}
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<UiAlert class="withdraw-summary__alert">
|
||||
Пожалуйста, подтвердите, что операцию инициировали именно вы.
|
||||
</UiAlert>
|
||||
|
||||
<UiCodeInput
|
||||
id="pincode"
|
||||
class="withdraw-summary__pincode"
|
||||
title="2FA-код"
|
||||
/>
|
||||
|
||||
<div class="withdraw-summary__actions">
|
||||
<UiButton
|
||||
color="secondary"
|
||||
size="large"
|
||||
@click="showSummary = false"
|
||||
>
|
||||
{{ $t('back') }}
|
||||
</UiButton>
|
||||
|
||||
<UiButton
|
||||
size="large"
|
||||
native-type="submit"
|
||||
:loading="isSubmitting"
|
||||
>
|
||||
{{ $t('withdraw') }}
|
||||
</UiButton>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { computedAsync } from '@vueuse/core'
|
||||
import Decimal from 'decimal.js'
|
||||
|
||||
definePageMeta({
|
||||
middleware: ['auth'],
|
||||
centerContent: true,
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const { data: project } = await useAsyncData(
|
||||
'project',
|
||||
() => {
|
||||
return $api(`/online_stores/${route.params.projectId}`, {
|
||||
method: 'GET',
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
if (!project.value) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: 'Page Not Found',
|
||||
})
|
||||
}
|
||||
|
||||
const notify = useNotify()
|
||||
const { t } = useI18n()
|
||||
|
||||
const { data: tariff } = await useAsyncData('tariff', () => {
|
||||
return $api(`/tariffs/current?currency=${route.params.assetCode}`)
|
||||
})
|
||||
|
||||
const { data: account } = await useAsyncData('account', () =>
|
||||
$api(`/accounts/${project.value.accountIds[0]}`, {
|
||||
method: 'GET',
|
||||
}))
|
||||
|
||||
const showSummary = ref(false)
|
||||
|
||||
const { isSubmitting, values, setValues, handleSubmit } = useForm({ keepValuesOnUnmount: true })
|
||||
|
||||
const commission = computedAsync(async () => {
|
||||
if (values.amount) {
|
||||
try {
|
||||
const result = await $api(`/withdrawals/commission`, { method: 'GET', params: { amount: values.amount, currency: route.params.assetCode } })
|
||||
|
||||
return result?.commission ?? 0
|
||||
}
|
||||
catch {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0
|
||||
}
|
||||
}, 0, { lazy: true })
|
||||
const fee = computed(() => $money.fullFormat(commission.value, route.params.assetCode))
|
||||
const balance = computed(() => $money.format(account.value.balance, route.params.assetCode))
|
||||
const maxAmount = computed(() => Math.min(1000, account.value.balance))
|
||||
const minAmount = computed(() => tariff.value?.data.minAmount)
|
||||
const exponent = computed(() => $money.getExponent(route.params.assetCode))
|
||||
const total = computed(() => $money.fullFormat(Decimal.sub(values.amount || 0, commission.value), route.params.assetCode))
|
||||
|
||||
const onSubmit = handleSubmit(async (values) => {
|
||||
if (!showSummary.value) {
|
||||
showSummary.value = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (values.pincode !== '123123') {
|
||||
notify({
|
||||
id: 'withdraw_error',
|
||||
text: t('invalid_otp_code'),
|
||||
type: 'negative',
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// const idempotencyKey = `${route.params.projectId + values.paymentAddress + route.params.assetCode}TRON${values.amount}`
|
||||
|
||||
await $api('/withdrawals', {
|
||||
method: 'POST',
|
||||
body: {
|
||||
...values,
|
||||
idempotencyKey: uuidv4().substring(0, 20),
|
||||
amount: +values.amount,
|
||||
onlineStoreId: +route.params.projectId,
|
||||
currencyCode: route.params.assetCode,
|
||||
blockchainCode: 'TRON',
|
||||
saveWallet: false,
|
||||
pincode: undefined,
|
||||
network: undefined,
|
||||
},
|
||||
})
|
||||
|
||||
notify({
|
||||
id: 'withdraw_success',
|
||||
type: 'positive',
|
||||
text: 'The withdrawal request has been successfully processed',
|
||||
})
|
||||
|
||||
navigateTo(`/projects/${route.params.projectId}`)
|
||||
}
|
||||
catch {
|
||||
notify({
|
||||
id: 'withdraw_error',
|
||||
text: t('something_went_wrong'),
|
||||
type: 'negative',
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.create-withdraw {
|
||||
&__currency-name {
|
||||
@include txt-l-sb('currency-name', true);
|
||||
@include txt-r-m('currency-name-code', true);
|
||||
|
||||
--currency-name-gap: 2px 16px;
|
||||
}
|
||||
|
||||
&__balance {
|
||||
@include txt-l-sb;
|
||||
}
|
||||
|
||||
&__continue {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__limit {
|
||||
@include txt-r-m;
|
||||
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
color: $clr-grey-500;
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.withdraw-form,
|
||||
.withdraw-summary {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
|
||||
&__header {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.withdraw-form {
|
||||
&__bottom {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.withdraw-summary {
|
||||
&__details {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__alert {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__pincode {
|
||||
padding-block: 16px;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
margin-top: 32px;
|
||||
|
||||
> * {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.withdraw-amount {
|
||||
$self: &;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
height: 48px;
|
||||
flex: 0 0 146px;
|
||||
|
||||
&--fee {
|
||||
flex: 0 0 100px
|
||||
}
|
||||
|
||||
&__title {
|
||||
@include txt-r-b;
|
||||
|
||||
color: $clr-grey-500;
|
||||
}
|
||||
|
||||
&__value {
|
||||
@include txt-l-sb;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
#{$self}--fee & {
|
||||
@include txt-i-sb;
|
||||
|
||||
color: $clr-grey-600;
|
||||
}
|
||||
}
|
||||
|
||||
& + & {
|
||||
border-left: 1px solid $clr-grey-300;
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.withdraw-details {
|
||||
@include txt-i-m;
|
||||
@include txt-i-m('text-shortener', true);
|
||||
@include txt-i-m('currency-name-code', true);
|
||||
|
||||
border-radius: 12px;
|
||||
background-color: $clr-grey-200;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
row-gap: 16px;
|
||||
color: $clr-grey-500;
|
||||
padding: 16px;
|
||||
|
||||
dt, dd {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
color: $clr-grey-600;
|
||||
}
|
||||
|
||||
dd {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&__amount {
|
||||
@include txt-l-sb;
|
||||
|
||||
color: $clr-black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user