withdrawls
This commit is contained in:
34
src/components/Blockchain.vue
Normal file
34
src/components/Blockchain.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div :class="['chain-block','chain-'+chainId]"><v-avatar class='chain-avatar' v-if="media.img" :image="media.img" rounded="0" size="1em"/> {{media.name}}</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed} from "vue";
|
||||
|
||||
const unsupportedMedia = {}
|
||||
const chainMedia = {
|
||||
1: {name: 'Ethereum', img: null},
|
||||
42161: { name: 'Arbitrum One', img: '/arbitrum-logo.svg'},
|
||||
31331: { name: 'Mockchain', img: null},
|
||||
}
|
||||
|
||||
const s = useStore()
|
||||
const props = defineProps(['chainId'])
|
||||
const media = computed(()=>chainMedia[props.chainId] || unsupportedMedia)
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss"> // NOT 'scoped'
|
||||
@use "src/styles/vars" as *;
|
||||
//.chain-avatar {
|
||||
// max-height: 1em;
|
||||
// max-width: 1em;
|
||||
//}
|
||||
.chain-block {
|
||||
display: inline;
|
||||
}
|
||||
.chain-42161 {
|
||||
color: #12aaff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,24 +0,0 @@
|
||||
<template>
|
||||
<v-btn prepend-icon="mdi-lightbulb-on" text="Connect Wallet" @click="connectWallet" :disabled="disabled"/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {ref} from "vue";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
|
||||
const s = useStore()
|
||||
const disabled = ref(false)
|
||||
|
||||
async function connectWallet() {
|
||||
disabled.value = true
|
||||
await provider.getSigner()
|
||||
disabled.value = false
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
|
||||
</style>
|
||||
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<v-btn v-if="permitted" rounded variant="text" size="small" density="compact" @click="copy()"
|
||||
:class="error?'error':copied?'success':''"
|
||||
:icon="error?'mdi-close-box-outline':copied?'mdi-check-circle-outline':'mdi-content-copy'"/>
|
||||
<v-tooltip :model-value="!error&&copied" :open-on-hover="false">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn v-bind="props" v-if="permitted" rounded variant="text" size="small" density="compact" @click="copy()"
|
||||
:class="error?'error':copied?'success':''"
|
||||
:icon="error?'mdi-close-box-outline':copied?'mdi-check-circle-outline':'mdi-content-copy'"/>
|
||||
</template>
|
||||
<span>Copied!</span>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
52
src/components/NeedsProvider.vue
Normal file
52
src/components/NeedsProvider.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<slot v-if="ok"/>
|
||||
<phone-card v-if="!walletOk">
|
||||
<v-card-title>Install Wallet</v-card-title>
|
||||
<v-card-text>
|
||||
A cryptocurrency wallet such as <a href="https://metamask.io/download/">MetaMask</a> is required to use Dexorder.
|
||||
Please install a crypto wallet into your browser to experience the power of Dexorder.
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn prepend-icon="mdi-reload" text="Reload After Installing Wallet"/>
|
||||
</v-card-actions>
|
||||
</phone-card>
|
||||
<phone-card v-if="walletOk && !providerOk">
|
||||
<v-card-text>
|
||||
Please log in to your crypto wallet.
|
||||
</v-card-text>
|
||||
<v-card-actions v-if="walletOk && !providerOk">
|
||||
<v-btn prepend-icon="mdi-power" text="Connect Wallet" @click="connectWallet"/>
|
||||
</v-card-actions>
|
||||
</phone-card>
|
||||
<phone-card v-if="walletOk && providerOk && !chainOk">
|
||||
<v-card-title><v-icon icon="mdi-reload-alert" color="warning"/> Change Blockchain</v-card-title>
|
||||
<v-card-text>
|
||||
Dexorder works only with <blockchain chain-id="42161"/>. Please switch to the
|
||||
<blockchain chain-id="42161"/> blockchain in your wallet.
|
||||
</v-card-text>
|
||||
</phone-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import PhoneCard from "@/components/PhoneCard.vue";
|
||||
import {connectWallet} from "@/blockchain/wallet.js";
|
||||
import {computed} from "vue";
|
||||
import Blockchain from "@/components/Blockchain.vue";
|
||||
|
||||
const s = useStore()
|
||||
const walletOk = typeof window.ethereum !== 'undefined'
|
||||
const providerOk = computed(()=>s.provider!==null)
|
||||
const chainOk = computed(()=>providerOk.value && s.helper!==null)
|
||||
const ok = computed(()=>{
|
||||
return walletOk && providerOk.value && chainOk.value
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
.arbitrum {
|
||||
color: $arbitrum-color;
|
||||
}
|
||||
</style>
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<!-- <v-card v-if="!s.account" prepend-icon="mdi-connection" title="Connect Wallet"-->
|
||||
<!-- text="Please connect your wallet to an Arbitrum account.">-->
|
||||
<!-- <v-card-actions><v-btn text="Connect Wallet" color="green" variant="elevated" @click="connectWallet" prepend-icon="mdi-power"/></v-card-actions>-->
|
||||
<!-- </v-card>-->
|
||||
<slot v-if="s.helper"/>
|
||||
<v-card v-if="!s.helper" prepend-icon='mdi-reload-alert' title="Change Blockchain"
|
||||
text="Dexorder works only with Arbitrum. Please choose the Arbitrum blockchain in your wallet."/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
|
||||
const s = useStore()
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
|
||||
<v-btn prepend-icon="mdi-plus" text="New Order"/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -1,8 +1,10 @@
|
||||
<template>
|
||||
<v-card class="d-none d-md-block" :elevation="4">
|
||||
<!-- tablets and desktops get a card outline -->
|
||||
<v-card class="d-none d-sm-block phone-card" :elevation="4">
|
||||
<slot/>
|
||||
</v-card>
|
||||
<v-container class="d-md-none">
|
||||
<!-- phones use the entire screen -->
|
||||
<v-container class="d-sm-none">
|
||||
<slot/>
|
||||
</v-container>
|
||||
</template>
|
||||
@@ -16,4 +18,7 @@ const s = useStore()
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
.phone-card {
|
||||
max-width: $card-maxw;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<NeedsQueryHelper>
|
||||
<PhoneCard>
|
||||
<needs-provider>
|
||||
<phone-card>
|
||||
<v-card-title class="big">DCA / TWAP</v-card-title>
|
||||
<v-card-subtitle>Multiple tranches over a time range</v-card-subtitle>
|
||||
<v-card-text>
|
||||
@@ -20,7 +20,7 @@
|
||||
<v-chip v-for="r in routes" variant="text">
|
||||
{{ s.chain.name }}
|
||||
<v-img src="https://upload.wikimedia.org/wikipedia/commons/e/e7/Uniswap_Logo.svg" width="1.5em"/>
|
||||
<span class="uniswap-pink ml-0 mr-1">v3</span>
|
||||
<span class="uniswap-color ml-0 mr-1">v3</span>
|
||||
{{pairSymbol}} {{r.fee/10000}}%
|
||||
</v-chip>
|
||||
|
||||
@@ -78,8 +78,8 @@
|
||||
<v-btn variant="outlined" color="red">Cancel</v-btn>
|
||||
<v-btn variant="flat" color="green" :disabled="!validOrder" @click="placeOrder">Place Order</v-btn>
|
||||
</v-card-actions>
|
||||
</PhoneCard>
|
||||
</NeedsQueryHelper>
|
||||
</phone-card>
|
||||
</needs-provider>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -90,15 +90,15 @@ import PhoneCard from "@/components/PhoneCard.vue";
|
||||
import {queryHelperContract} from "@/blockchain/contract.js";
|
||||
// noinspection ES6UnusedImports
|
||||
import {SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||
import NeedsQueryHelper from "@/components/NeedsQueryHelper.vue";
|
||||
import {Exchange, newOrder, newTimeConstraint, TimeMode} from "@/blockchain/orderlib.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {pendOrder} from "@/blockchain/wallet.js";
|
||||
import NeedsProvider from "@/components/NeedsProvider.vue";
|
||||
|
||||
const s = useStore()
|
||||
const buy = ref(false)
|
||||
let _tokenA = ref(s.tokens !== undefined && s.tokens.length >= 1 ? s.tokens[0] : null)
|
||||
let _tokenB = ref(s.tokens !== undefined && s.tokens.length >= 2 ? s.tokens[1] : null)
|
||||
let _tokenA = ref(Object.values(s.tokens).length >= 1 ? Object.values(s.tokens)[0] : null)
|
||||
let _tokenB = ref(Object.values(s.tokens).length >= 2 ? Object.values(s.tokens)[1] : null)
|
||||
const tokenA = computed({
|
||||
get() {
|
||||
return _tokenA.value
|
||||
@@ -149,19 +149,22 @@ const limitIsMinimum = computed(() => !(buy.value ^ inverted.value))
|
||||
const validOrder = computed(()=>amount.value > 0 && routes.value.length > 0 )
|
||||
|
||||
async function findRoute() {
|
||||
console.log('finding route', _tokenA.value, _tokenB.value)
|
||||
routes.value = []
|
||||
if( !_tokenA.value || !_tokenB.value )
|
||||
return
|
||||
const helper = await queryHelperContract()
|
||||
if( !helper )
|
||||
if( !helper ) {
|
||||
console.log('no helper')
|
||||
return
|
||||
}
|
||||
routesPending.value = true
|
||||
let rawRoutes
|
||||
try {
|
||||
rawRoutes = await helper.getRoutes(tokenA.value.address, tokenB.value.address)
|
||||
}
|
||||
catch (e) {
|
||||
// console.log('routes exception', e)
|
||||
console.log('routes exception', e)
|
||||
routesPending.value = false
|
||||
return
|
||||
}
|
||||
@@ -242,7 +245,7 @@ function validateMin(v) {
|
||||
return true
|
||||
}
|
||||
|
||||
async function placeOrder() {
|
||||
function placeOrder() {
|
||||
const ta = tokenA.value;
|
||||
const tb = tokenB.value;
|
||||
const tokenIn = buy.value ? tb.address : ta.address
|
||||
@@ -278,7 +281,7 @@ async function placeOrder() {
|
||||
ts.push([amtPerTranche, cs])
|
||||
}
|
||||
const order = newOrder(tokenIn, tokenOut, route.exchange, route.fee, amt, amountIsInput, ts)
|
||||
await pendOrder(order)
|
||||
pendOrder(order)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<v-combobox :items="Object.values(s.tokens)" :auto-select-first="true"
|
||||
<v-combobox :items="tokens" :auto-select-first="true"
|
||||
item-title="symbol"
|
||||
:filter-keys="['raw.name','raw.symbol','raw.address']"
|
||||
:model-value="modelValue"
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<script setup>
|
||||
import {useStore as useStore2} from "@/store/store";
|
||||
import {ref} from "vue";
|
||||
import {computed, ref} from "vue";
|
||||
import {ethers} from "ethers";
|
||||
// noinspection ES6UnusedImports
|
||||
import {vAutoSelect} from "@/misc.js";
|
||||
@@ -32,6 +32,8 @@ const props = defineProps(['modelValue', 'label'])
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const loading = ref(false)
|
||||
const errors = ref([])
|
||||
const tokens = computed(()=>Object.values(s.tokens))
|
||||
|
||||
|
||||
function good() {
|
||||
errors.value = []
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
<template>
|
||||
<tr>
|
||||
<td><v-img v-if="imageSrc" :src="imageSrc"/></td>
|
||||
<td>{{token.symbol}}</td>
|
||||
<td class="d-none d-sm-table-cell">{{token.name||''}}</td>
|
||||
<td>{{fixed}}</td>
|
||||
<td><!-- todo actions --></td>
|
||||
<td>
|
||||
<v-avatar v-if="imageSrc" :image="imageSrc"/>
|
||||
</td>
|
||||
<td class="d-none d-sm-table-cell">{{ token.name || '' }}</td>
|
||||
<td class="text-right">{{ fixed }}</td>
|
||||
<td class="text-left">{{ token.symbol }}</td>
|
||||
<!-- todo price and value columns -->
|
||||
<td>
|
||||
<v-menu>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn variant="plain" v-bind="props" icon="mdi-menu"/> <!-- mdi-dots-vertical -->
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-subheader :title="token.symbol"/>
|
||||
<v-list-item title="Withdraw" key="withdraw" value="withdraw" prepend-icon="mdi-arrow-down-bold"
|
||||
@click="()=>onWithdraw(token.address)"/>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
@@ -12,13 +26,17 @@
|
||||
import {useStore} from "@/store/store";
|
||||
import {getToken} from "@/blockchain/token.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {computed} from "vue";
|
||||
import {computed, ref} from "vue";
|
||||
|
||||
const s = useStore()
|
||||
const props = defineProps(['addr','amount'])
|
||||
const props = defineProps(['addr', 'amount', 'onWithdraw'])
|
||||
const token = await getToken(props.addr)
|
||||
console.log('token', props.addr, token)
|
||||
const fixed = computed(()=>FixedNumber.fromValue(props.amount, token.decimals, {width:256, decimals: token.decimals}))
|
||||
const imageSrc = computed(()=>null )
|
||||
const fixed = computed(() => FixedNumber.fromValue(props.amount, token.decimals, {
|
||||
width: 256,
|
||||
decimals: token.decimals
|
||||
}))
|
||||
const imageSrc = computed(() => null)
|
||||
const withdrawing = ref(false)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,58 +1,70 @@
|
||||
<template>
|
||||
<!-- todo we can use something like this for ethereum where the vault creation is too expensive to subsidize
|
||||
<PhoneCard v-if="s.vault===null || s.vault.length === 0">
|
||||
<v-card-title><v-icon color="warning" icon="mdi-alert"/> Setup Vault</v-card-title>
|
||||
<v-card-subtitle>Create Your Own Personal Dexorder Vault</v-card-subtitle>
|
||||
<v-card-text>
|
||||
Dexorder never has access to your tokens. Instead, you create a personal
|
||||
vault which acts like your Dexorder account.
|
||||
Create your own personal asset vault to get started with Dexorder. This vault
|
||||
acts like your Dexorder account. For security, only <i>you</i> can deposit
|
||||
or withdraw tokens from your vault, and no token approvals are ever given to
|
||||
Dexorder. Instead, Dexorder sends trade requests to your vault at the right
|
||||
times, then your vault checks the validity of those trade requests before
|
||||
trading directly from your vault to the dex liquidity pool. Dexorder never
|
||||
has any access to the funds in your vault.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
Creating your personal vault is a one-time setup operation. Your vault address
|
||||
is unique to you and never changes. You may deposit or withdraw funds in your
|
||||
vault at any time, and you may save your vault address in your wallet for
|
||||
easy access.
|
||||
</v-card-text>
|
||||
</PhoneCard>
|
||||
<needs-provider>
|
||||
<!-- todo we can use something like this for ethereum where the vault creation is too expensive to subsidize
|
||||
<PhoneCard v-if="s.vault===null || s.vault.length === 0">
|
||||
<v-card-title><v-icon color="warning" icon="mdi-alert"/> Setup Vault</v-card-title>
|
||||
<v-card-subtitle>Create Your Own Personal Dexorder Vault</v-card-subtitle>
|
||||
<v-card-text>
|
||||
Dexorder never has access to your tokens. Instead, you create a personal
|
||||
vault which acts like your Dexorder account.
|
||||
Create your own personal asset vault to get started with Dexorder. This vault
|
||||
acts like your Dexorder account. For security, only <i>you</i> can deposit
|
||||
or withdraw tokens from your vault, and no token approvals are ever given to
|
||||
Dexorder. Instead, Dexorder sends trade requests to your vault at the right
|
||||
times, then your vault checks the validity of those trade requests before
|
||||
trading directly from your vault to the dex liquidity pool. Dexorder never
|
||||
has any access to the funds in your vault.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
Creating your personal vault is a one-time setup operation. Your vault address
|
||||
is unique to you and never changes. You may deposit or withdraw funds in your
|
||||
vault at any time, and you may save your vault address in your wallet for
|
||||
easy access.
|
||||
</v-card-text>
|
||||
</PhoneCard>
|
||||
-->
|
||||
<v-card v-if="s.vaults.length<num">
|
||||
<v-card-title>No Vault Yet</v-card-title>
|
||||
<v-card-text v-if="num!==0"><!--todo-->Multiple vaults are not yet supported</v-card-text>
|
||||
<v-card-text v-if="num===0">Create an order first, then your vault account will appear here to accept a deposit of trading funds.</v-card-text>
|
||||
</v-card>
|
||||
<v-card v-if="s.vaults.length>num">
|
||||
<v-card-title>Vault {{s.vaults.length>1?'#'+(num+1):''}}</v-card-title> <!-- todo vault nicknames -->
|
||||
<v-card-subtitle v-if="exists">{{addr}} <copy-button :text="addr"/></v-card-subtitle>
|
||||
<v-card-text v-if="empty">
|
||||
<p>There are no funds currently in your vault.</p>
|
||||
<p>Send tokens to the address above to fund your vault.</p>
|
||||
</v-card-text>
|
||||
<v-card-item v-if="!empty">
|
||||
<v-table>
|
||||
<tbody>
|
||||
<suspense v-for="(amount,addr) of balances">
|
||||
<token-row :addr="addr" :amount="amount" :onWithdraw="onWithdraw"/>
|
||||
</suspense>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</v-card-item>
|
||||
</v-card>
|
||||
<withdraw :vault="addr" :token="withdrawToken" v-model="withdrawShow"/>
|
||||
<!--
|
||||
<div>
|
||||
addr {{ addr }}<br/>
|
||||
empty {{ empty }}<br/>
|
||||
exists {{ exists }}<br/>
|
||||
</div>
|
||||
-->
|
||||
<v-card v-if="s.vaults.length<num">
|
||||
<v-card-title>No Vault Yet</v-card-title>
|
||||
<v-card-text v-if="num!==0"><!--todo-->Multiple vaults are not yet supported</v-card-text>
|
||||
<v-card-text v-if="num===0">Create an order first, then your vault account will appear here to accept a deposit of trading funds.</v-card-text>
|
||||
</v-card>
|
||||
<v-card v-if="s.vaults.length>num">
|
||||
<v-card-title>Vault {{s.vaults.length>1?'#'+(num+1):''}}</v-card-title> <!-- todo vault nicknames -->
|
||||
<v-card-subtitle v-if="exists">{{addr}} <copy-button :text="addr"/></v-card-subtitle>
|
||||
<v-card-text v-if="empty">
|
||||
<p>There are no funds currently in your vault.</p>
|
||||
<p>Send tokens to the address above to fund your vault.</p>
|
||||
</v-card-text>
|
||||
<v-card-item>
|
||||
<v-table v-if="!empty">
|
||||
<tbody>
|
||||
<suspense v-for="(amount,addr) of balances">
|
||||
<token-row :addr="addr" :amount="amount"/>
|
||||
</suspense>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</v-card-item>
|
||||
</v-card>
|
||||
</needs-provider>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store.js";
|
||||
import PhoneCard from "@/components/PhoneCard.vue";
|
||||
import {computed, defineAsyncComponent} from "vue";
|
||||
import {computed, defineAsyncComponent, ref} from "vue";
|
||||
import {vaultAddress} from "@/blockchain/contract.js";
|
||||
import CopyButton from "@/components/CopyButton.vue";
|
||||
|
||||
import NeedsProvider from "@/components/NeedsProvider.vue";
|
||||
import Withdraw from "@/components/Withdraw.vue";
|
||||
console.log('vault setup')
|
||||
const TokenRow = defineAsyncComponent(()=>import('./TokenRow.vue'))
|
||||
const s = useStore()
|
||||
|
||||
@@ -63,9 +75,17 @@ const balances = computed(()=>{
|
||||
console.log('balances', addr.value, s.vaultBalances, bs)
|
||||
return bs || {}
|
||||
})
|
||||
const tokenAddrs = computed(()=>Object.keys(balances))
|
||||
const empty = computed(()=>Object.keys(balances.value).length===0)
|
||||
const exists = computed(()=>s.vaults.length>0)
|
||||
|
||||
const withdrawToken = ref(null)
|
||||
const withdrawShow = ref(false)
|
||||
function onWithdraw(addr) {
|
||||
const token = s.tokens[addr]
|
||||
console.log('withdraw', addr, token)
|
||||
withdrawToken.value = token
|
||||
withdrawShow.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
64
src/components/Withdraw.vue
Normal file
64
src/components/Withdraw.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<v-dialog :model-value="modelValue" @update:modelValue="$emit('update:modelValue', $event)">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<v-icon icon="mdi-down-arrow"/> Withdraw {{ token.symbol }}
|
||||
</v-card-title>
|
||||
<v-card-item>
|
||||
<v-text-field class="text-end" type="number" variant="outlined" :min="0" :max="balanceFloat"
|
||||
v-model="floatAmount" :step="balanceFloat/10">
|
||||
<template v-slot:prepend-inner>
|
||||
<v-btn variant="text" text="max" @click="floatAmount=balanceFloat"/>
|
||||
</template>
|
||||
<template v-slot:append-inner>
|
||||
<span>{{ token.symbol }}</span>
|
||||
</template>
|
||||
</v-text-field>
|
||||
<v-card-actions>
|
||||
<v-btn text="Cancel" @click="$emit('update:modelValue', false)"/>
|
||||
<v-btn text="Withdraw" color="red" @click="withdraw"/>
|
||||
</v-card-actions>
|
||||
</v-card-item>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed, ref} from "vue";
|
||||
import {tokenFloat} from "@/misc.js";
|
||||
import {contractOrNull} from "@/blockchain/contract.js"
|
||||
import {vaultAbi} from "@/blockchain/abi.js";
|
||||
import {pendTransaction} from "@/blockchain/wallet.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
|
||||
const s = useStore()
|
||||
const props = defineProps(['modelValue', 'vault', 'token'])
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const balance = computed(() => {
|
||||
console.log('balance', props.vault, props.token, s.vaultBalances)
|
||||
return s.vaultBalances[props.vault][props.token.address] || 0
|
||||
})
|
||||
const balanceFloat = computed(() => tokenFloat(props.token, balance.value))
|
||||
const floatAmount = ref(0)
|
||||
|
||||
function withdraw() {
|
||||
const vaultAddr = props.vault
|
||||
const valueStr = floatAmount.value.toString();
|
||||
const amount = FixedNumber.fromString(valueStr,{decimals:props.token.decimals, width:256, signed: false}).value;
|
||||
console.log('pending withdrawl', valueStr, amount, props.token.symbol)
|
||||
if( amount === 0n )
|
||||
return
|
||||
pendTransaction(async (signer)=>{
|
||||
const vault = contractOrNull(vaultAddr, vaultAbi, signer)
|
||||
return await vault['withdraw(address,uint256)'](props.token.address, amount)
|
||||
})
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user