transaction placement dialog

This commit is contained in:
tim
2024-11-11 20:55:28 -04:00
parent 43891434c5
commit a9bf23ddbb
18 changed files with 439 additions and 122 deletions

View File

@@ -1,6 +1,5 @@
import {uint32max, uint64max} from "@/misc.js";
import {decodeIEE754, encodeIEE754} from "@/common.js";
import order from "@/components/Order.vue";
import {encodeIEE754} from "@/common.js";
export const MAX_FRACTION = 65535;
export const NO_CONDITIONAL_ORDER = uint64max;

View File

@@ -0,0 +1,279 @@
import {nav, timestamp, uuid} from "@/misc.js";
import {newContract, vaultContract} from "@/blockchain/contract.js";
import {ensureVault, provider, switchChain, useWalletStore} from "@/blockchain/wallet.js";
import {toRaw} from "vue";
import {useChartOrderStore} from "@/orderbuild.js";
export const TransactionState = {
Created: 0, // user requested a transaction
Proposed: 1, // tx is sent to the wallet
Signed: 2, // tx is awaiting blockchain mining
Rejected: 3, // user refused to sign the tx
Error: 3, // unknown error sending the tx to the wallet
Mined: 4, // transaction has been confirmed on-chain
}
export const TransactionType = {
PlaceOrder: 1,
CancelOrder: 2,
CancelAll: 3,
Wrap: 4,
Unwrap: 5,
WithdrawNative: 6,
Withdraw: 7,
}
export class Transaction {
constructor(chainId, type) {
this.id = uuid()
this.type = type
this.state = TransactionState.Created
this.tx = null
this.chainId = chainId
this.owner = null
this.vault = null
this.error = null
}
submit() {
useWalletStore().transaction = this
ensureVault()
}
propose(owner, vault) {
if (this.vault !== null && this.vault !== vault) {
this.failed('proposed vault did not match withdrawl vault', vault, this.vault)
return
}
this.owner = owner
this.vault = vault
this.send().catch(this.catchSend.bind(this))
this.state = TransactionState.Proposed
}
async createTx(vaultContract) {
throw Error('unimplemented')
}
signed(tx) {
this.tx = tx
this.state = TransactionState.Signed
}
rejected() {
this.tx = null
this.chainId = null
this.owner = null
this.vault = null
this.end(TransactionState.Rejected)
console.log('transaction rejected', this.id)
}
failed(e) {
this.error = e
this.end(TransactionState.Error)
console.log('transaction failed', this.id, e)
}
mined(receipt) {
this.receipt = receipt
this.end(TransactionState.Mined)
console.log('mined transaction', this.id, receipt)
}
isOpen() {
return this.state >= TransactionState.Rejected
}
isClosed() {
return this.state < TransactionState.Rejected
}
end(state) {
this.state = state
useWalletStore().transaction = null
}
async send() {
console.log('sendTransaction', this)
try {
await switchChain(this.chainId)
} catch (e) {
if (e.code === 4001) {
this.rejected()
return null
} else {
this.failed(e)
return null
}
}
let signer
try {
signer = await provider.getSigner();
} catch (e) {
// {
// "code": -32002,
// "message": "Already processing eth_requestAccounts. Please wait."
// }
this.rejected()
return null
}
let contract
try {
contract = await vaultContract(this.vault, signer)
} catch (e) {
this.failed('vault contract was null while sending order transaction')
return null
}
const tx = toRaw(await this.createTx(contract))
this.signed(tx)
console.log(`sent transaction`, tx)
tx.wait().then(this.mined.bind(this)).catch(this.failed.bind(this))
return this.tx
}
catchSend(e) {
this.error = e
if (e.info?.error?.code === 4001) {
console.log(`wallet refused transaction`, this.id)
this.rejected()
} else {
this.failed(e)
}
}
}
export class PlaceOrderTransaction extends Transaction {
constructor(chainId, order) {
super(chainId, TransactionType.PlaceOrder)
this.order = order
this.placementTime = Date.now()/1000
this.fee = null // dexorder place and gas fee total
}
async createTx(vaultContract) {
this.fee = await placementFee(this.vault, this.order)
console.log('placing order', this.id, this.fee, this.order)
return await vaultContract.placeDexorder(this.order, {value: this.fee.reduce((a, b) => a + b)})
}
end(state) {
super.end(state)
if (state === TransactionState.Mined) {
useChartOrderStore().resetOrders()
nav('Status')
}
}
}
// todo move to orderlib
async function placementFee(vault, order, window = 300) {
// If the fees are about to change within `window` seconds of now, we send the higher native amount of the two fees.
// If the fees sent are too much, the vault will refund the sender.
const v = await vaultContract(vault, provider)
const feeManagerAddr = await v.feeManager()
const feeManager = await newContract(feeManagerAddr, 'IFeeManager', provider)
const [sched, changeTimestamp] = await Promise.all([feeManager.fees(), feeManager.proposedFeeActivationTime()])
console.log('sched', order, sched)
// single order placement selector
const placementFeeSelector = 'placementFee((address,address,(uint8,uint24),uint256,uint256,bool,bool,bool,uint64,(uint16,bool,bool,bool,bool,bool,bool,bool,bool,uint16,uint24,uint32,uint32,(uint32,uint32),(uint32,uint32))[]),(uint8,uint8,uint8,uint8,uint8))'
let [orderFee, gasFee] = await v[placementFeeSelector](order, [...sched])
console.log('placementFee', orderFee, gasFee)
if (Number(changeTimestamp) - timestamp() < window) {
const nextSched = await feeManager.proposedFees()
const [nextOrderFee, nextGasFee] = await v[placementFeeSelector](order, [...nextSched])
if (nextOrderFee + nextGasFee > orderFee + gasFee)
[orderFee, gasFee] = [nextOrderFee, nextGasFee]
}
return [orderFee, gasFee]
}
export class CancelOrderTransaction extends Transaction {
constructor(chainId, index) {
super(chainId, TransactionType.CancelOrder)
this.index = index
}
async createTx(vaultContract) {
return await vaultContract.cancelDexorder(this.index)
}
}
export class CancelAllTransaction extends Transaction {
constructor(chainId, vault) {
super(chainId, TransactionType.CancelAll)
this.vault = vault
}
async createTx(vaultContract) {
return await vaultContract.cancelAllDexorders()
}
}
export class WithdrawTransaction extends Transaction {
constructor(chainId, vault, token, amount) {
super(chainId, TransactionType.Withdraw)
this.token = token
this.amount = amount
this.vault = vault
}
async createTx(vaultContract) {
return await vaultContract['withdraw(address,uint256)'](this.token.a, this.amount)
}
}
export class WithdrawNativeTransaction extends Transaction {
constructor(chainId, vault, amount) {
super(chainId, TransactionType.WithdrawNative)
this.amount = amount
this.vault = vault
}
async createTx(vaultContract) {
return await vaultContract['withdraw(uint256)'](this.amount)
}
}
export class WrapTransaction extends Transaction {
constructor(chainId, vault, amount) {
super(chainId, TransactionType.Wrap)
this.vault = vault
this.amount = amount
}
async createTx(vaultContract) {
return await vaultContract.wrap(this.amount)
}
}
export class UnwrapTransaction extends Transaction {
constructor(chainId, vault, amount) {
super(chainId, TransactionType.Unwrap)
this.amount = amount
}
async createTx(vaultContract) {
return await vaultContract.unwrap(this.amount)
}
}

View File

@@ -1,21 +1,23 @@
import {BrowserProvider, ethers} from "ethers";
import {useStore} from "@/store/store";
import {socket} from "@/socket.js";
import {SingletonCoroutine, timestamp, uuid} from "@/misc.js";
import {SingletonCoroutine, uuid} from "@/misc.js";
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
import {defineStore} from "pinia";
import {ref} from "vue";
import {metadataMap, version} from "@/version.js";
import {CancelAllTransaction, TransactionState} from "@/blockchain/transaction.js";
export let provider = null
// DEPRECATED
export const useWalletStore = defineStore('wallet', ()=>{
// this is what the wallet is logged into. it could be different than the application's store.chainId.
const chainId = ref(0)
// Pending Order Format
// OLD Pending Order Format
// {
// chainId: 31337, // must never be null, even if no wallet plugin exists. chosen by app, not wallet.
// placementTime: Date.now(),
@@ -26,8 +28,11 @@ export const useWalletStore = defineStore('wallet', ()=>{
// }
const pendingOrders = ref([])
// NEW Format is a single Transaction class
const transaction = ref(null)
return {
chainId, pendingOrders,
chainId, pendingOrders, transaction,
}
})
@@ -165,7 +170,7 @@ function discoverVaults(owner) {
doDiscoverVaults.invoke(owner)
}
const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50, false)
const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50)
async function _discoverVaults(owner) {
const result = []
const versions = []
@@ -204,11 +209,12 @@ async function _discoverVaults(owner) {
if( s.account === owner ) { // double-check the account since it could have changed during our await
s.vaults = result
s.vaultVersions = versions
if( useWalletStore().pendingOrders.length ) {
if( useWalletStore().transaction ) {
const num = 0 // todo multiple vaults
if (result.length)
flushOrders(result[0])
flushOrders(s.chainId, owner, num, result[0])
else
ensureVault2(s.chainId, owner, 0)
ensureVault2(s.chainId, owner, num)
}
}
}
@@ -248,7 +254,7 @@ async function doEnsureVault(chainId, owner, num) {
if (s.vaults.length <= num)
await _discoverVaults(owner)
if( s.vaults[num] )
flushOrders(s.vaults[num])
flushOrders(chainId, owner, num, s.vaults[num])
else {
console.log(`requesting vault ${owner} ${num}`)
socket.emit('ensureVault', chainId, owner, num)
@@ -258,53 +264,6 @@ async function doEnsureVault(chainId, owner, num) {
const ensureVaultRoutine = new SingletonCoroutine(doEnsureVault, 100)
export const PendingOrderState = {
Submitted: -100, // user clicked Place Order but the tx isn't sent to the wallet yet
Signing: 0, // tx is sent to the wallet
Rejected: -101, // user refused to sign the tx
Sent: -102, // tx is awaiting blockchain mining
}
// single order placement selector
const placementFeeSelector = 'placementFee((address,address,(uint8,uint24),uint256,uint256,bool,bool,bool,uint64,(uint16,bool,bool,bool,bool,bool,bool,bool,bool,uint16,uint24,uint32,uint32,(uint32,uint32),(uint32,uint32))[]),(uint8,uint8,uint8,uint8,uint8))'
export async function placementFee(vault, order, window=300) {
// If the fees are about to change within `window` seconds of now, we send the higher native amount of the two fees.
// If the fees sent are too much, the vault will refund the sender.
const v = await vaultContract(vault, provider)
const feeManagerAddr = await v.feeManager()
const feeManager = await newContract(feeManagerAddr, 'IFeeManager', provider)
const [sched, changeTimestamp] = await Promise.all([feeManager.fees(), feeManager.proposedFeeActivationTime()])
console.log('sched', order, sched)
let [orderFee, gasFee] = await v[placementFeeSelector](order, [...sched])
console.log('placementFee', orderFee, gasFee)
if (Number(changeTimestamp) - timestamp() < window) {
const nextSched = await feeManager.proposedFees()
const [nextOrderFee, nextGasFee] = await v[placementFeeSelector](order, [...nextSched])
if (nextOrderFee + nextGasFee > orderFee + gasFee)
[orderFee, gasFee] = [nextOrderFee, nextGasFee]
}
return [orderFee, gasFee]
}
export async function pendOrder(order, fee=null) {
const s = useStore()
const pend = {
id: uuid(),
chainId: s.chainId,
placementTime: Date.now()/1000,
fee: fee, // dexorder place and gas fee total
vault: s.vaults.length ? s.vaults[0] : null,
state: PendingOrderState.Submitted,
order
};
useWalletStore().pendingOrders.splice(0,0, pend)
console.log('pended order', pend.id, JSON.stringify(order))
ensureVault()
}
export async function cancelOrder(vault, orderIndex) {
console.log('cancel order', vault, orderIndex)
pendTransaction(async (signer)=> {
@@ -318,18 +277,13 @@ export async function cancelOrder(vault, orderIndex) {
}
export async function cancelAll(vault) {
pendTransaction(async (signer)=> {
const contract = await vaultContract(vault, signer)
if( contract === null ) {
console.error('vault contract was null while canceling order', vault)
return null
}
return await contract.cancelAllDexorders()
})
new CancelAllTransaction(useStore().chainId, vault).submit()
}
export function flushOrders(vault) {
export function flushOrders(chainId, owner, num, vault) {
const ws = useWalletStore();
if (ws.transaction!==null && ws.transaction.state < TransactionState.Proposed)
ws.transaction.propose(owner, vault)
let needsFlush = false
for( const pend of ws.pendingOrders ) {
if (pend.vault === null)
@@ -337,7 +291,7 @@ export function flushOrders(vault) {
if (pend.state === PendingOrderState.Submitted) {
console.log('flushing order', pend.id)
pendOrderAsTransaction(pend)
pend.state = PendingOrderState.Signing
setPendState(pend, PendingOrderState.Signing)
needsFlush = true
}
}
@@ -363,7 +317,7 @@ function pendOrderAsTransaction(pend) {
catch (e) {
if(e.code===4001) {
console.log('user refused chain switch')
pend.state = PendingOrderState.Rejected
setPendState(pend, PendingOrderState.Rejected)
return null
}
else {
@@ -378,7 +332,7 @@ function pendOrderAsTransaction(pend) {
console.log('placing order', pend.id, pend.fee, pend.order)
const tx = await contract.placeDexorder(pend.order, {value:pend.fee})
pend.tx = tx
pend.state = PendingOrderState.Sent
setPendState(pend, PendingOrderState.Sent)
console.log(`order ${pend.id} sent transaction`, tx)
tx.wait().then((txReceipt)=>{
console.log('mined order', pend.id, txReceipt)
@@ -391,7 +345,7 @@ function pendOrderAsTransaction(pend) {
(e) => {
if( e.info?.error?.code === 4001 ) {
console.log(`wallet refused order`, pend.id)
pend.state = PendingOrderState.Rejected
setPendState(pend, PendingOrderState.Rejected)
return true // returning true means we handled the error. any other return value will dump to console.
}
})

View File

@@ -9,9 +9,9 @@
<script setup>
import PairPrice from "@/components/PairPrice.vue";
import {computed} from "vue";
import {computed, defineAsyncComponent} from "vue";
import {useStore} from "@/store/store.js";
const PairPrice = defineAsyncComponent(()=>import("@/components/PairPrice.vue"))
const props = defineProps(['base', 'quote', 'm', 'b', 'isBreakout', 'showBtn', 'buy'])
const s = useStore()

View File

@@ -26,9 +26,8 @@
<script setup>
import {useStore} from "@/store/store";
import {computed, ref} from "vue";
import {vaultContract} from "@/blockchain/contract.js"
import {pendTransaction} from "@/blockchain/wallet.js";
import {FixedNumber} from "ethers";
import {WrapTransaction} from "@/blockchain/transaction.js";
const s = useStore()
const props = defineProps(['modelValue', 'vault', 'maxAmount'])
@@ -45,10 +44,7 @@ function wrapNative() {
if( amount === 0n )
return
console.log('pending wrap', valueStr, amount)
pendTransaction(async (signer)=>{
const vault = await vaultContract(vaultAddr, signer)
return await vault.wrap(amount)
})
new WrapTransaction(s.chainId, vaultAddr, amount).submit()
floatAmount.value = 0
emit('update:modelValue', false)
}

View File

@@ -26,7 +26,6 @@ import Amount from "@/components/Amount.vue"
import {nav, SingletonCoroutine, vAutoSelect} from "@/misc.js";
import {newOrder} from "@/blockchain/orderlib.js";
import {FixedNumber} from "ethers";
import {pendOrder} from "@/blockchain/wallet.js";
import PairChoice from "@/components/PairChoice.vue";
import NeedsSigner from "@/components/NeedsSigner.vue";
import {useChartOrderStore} from "@/orderbuild.js";

View File

@@ -18,7 +18,6 @@ import {flipInversionPreference, inversionPreference} from "@/misc.js";
const props = defineProps(['value', 'base', 'quote', 'showBtn'])
const s = useStore()
const prefs = usePrefStore()
async function token(obj) {
if (!obj) return null

View File

@@ -71,10 +71,12 @@
</suspense>
</template>
<template v-slot:item.state="{ item }">
<!--
<v-chip v-if="item.state===PendingOrderState.Submitted || item.state===PendingOrderState.Signing"
prepend-icon="mdi-signature">Wallet Signing</v-chip>
<v-chip v-if="item.state===PendingOrderState.Rejected" prepend-icon="mdi-cancel">Rejected</v-chip>
<v-chip v-if="item.state===PendingOrderState.Sent" prepend-icon="mdi-send">Sent</v-chip>
-->
<v-chip v-if="item.state===OrderState.Open" class="d-none d-lg-inline-flex" prepend-icon="mdi-dots-horizontal"
color="green">Open
</v-chip>
@@ -176,7 +178,7 @@ import LinePrice from "@/components/LinePrice.vue";
import {useStore} from "@/store/store";
import {computed, defineAsyncComponent, onUnmounted, ref, watch} from "vue";
import Btn from "@/components/Btn.vue"
import {cancelOrder, PendingOrderState, useWalletStore} from "@/blockchain/wallet.js";
import {cancelOrder, useWalletStore} from "@/blockchain/wallet.js";
import {DISTANT_FUTURE, isOpen, OrderState} from "@/blockchain/orderlib.js";
import Pulse from "@/components/Pulse.vue";
import {OrderShapes} from "@/charts/ordershapes.js";

View File

@@ -15,7 +15,7 @@
<v-list v-if="token">
<v-list-subheader :title="token.s"/>
<v-list-item title="Withdraw" key="withdraw" value="withdraw" prepend-icon="mdi-arrow-down-bold"
@click="()=>onWithdraw(token.a)"/>
@click="()=>onWithdraw(token)"/>
</v-list>
</v-menu>
</td>

View File

@@ -34,10 +34,8 @@
<v-card-item v-if="!empty">
<v-table>
<tbody>
<suspense>
<native-row v-if="nativeBalance" :chain-id="s.chainId" :addr="s.vault" :amount="nativeBalance"
:on-withdraw="onWithdrawNative" :on-wrap="()=>wrapShow=true"/>
</suspense>
<native-row v-if="nativeBalance" :chain-id="s.chainId" :addr="s.vault" :amount="nativeBalance"
:on-withdraw="onWithdrawNative" :on-wrap="()=>wrapShow=true"/>
<suspense v-for="(amount,addr) of balances">
<token-row v-if="BigInt(amount)!==0n" :chain-id="s.chainId" :addr="addr" :amount="amount" :onWithdraw="onWithdraw"/>
</suspense>
@@ -65,7 +63,6 @@ import {vaultAddress} from "@/blockchain/contract.js";
import {ensureVault, provider} from "@/blockchain/wallet.js";
import CopyButton from "@/components/CopyButton.vue";
import Withdraw from "@/components/Withdraw.vue";
import {getToken} from "@/blockchain/token.js";
import NativeRow from "@/components/NativeRow.vue";
import NativeWrap from "@/components/NativeWrap.vue";
import WithdrawNative from "@/components/WithdrawNative.vue";
@@ -91,8 +88,7 @@ const hasVault = computed(()=>s.vault!==null)
const withdrawToken = ref(null)
const withdrawShow = ref(false)
async function onWithdraw(addr) {
const token = await getToken(s.chainId, addr)
async function onWithdraw(token) {
console.log('withdraw', addr, token)
withdrawToken.value = token
withdrawShow.value = true

View File

@@ -30,6 +30,7 @@ import {tokenFloat} from "@/misc.js";
import {vaultContract} from "@/blockchain/contract.js"
import {pendTransaction} from "@/blockchain/wallet.js";
import {FixedNumber} from "ethers";
import {WithdrawTransaction} from "@/blockchain/transaction.js";
const s = useStore()
const props = defineProps(['modelValue', 'vault', 'token'])
@@ -50,10 +51,7 @@ function withdraw() {
if( amount === 0n )
return
console.log('pending withdrawal', valueStr, amount, props.token.s)
pendTransaction(async (signer)=>{
const vault = await vaultContract(vaultAddr, signer)
return await vault['withdraw(address,uint256)'](props.token.a, amount)
})
new WithdrawTransaction(s.chainId, vaultAddr, props.token, amount).submit()
floatAmount.value = 0
emit('update:modelValue', false)
}

View File

@@ -26,9 +26,8 @@
<script setup>
import {useStore} from "@/store/store";
import {computed, ref} from "vue";
import {vaultContract} from "@/blockchain/contract.js"
import {pendTransaction} from "@/blockchain/wallet.js";
import {FixedNumber} from "ethers";
import {WithdrawNativeTransaction} from "@/blockchain/transaction.js";
const s = useStore()
const props = defineProps(['modelValue', 'vault', 'balance'])
@@ -44,11 +43,7 @@ function withdraw() {
console.log('pending native withdrawal', valueStr, amount)
if( amount === 0n )
return
pendTransaction(async (signer)=>{
const vault = await vaultContract(vaultAddr, signer)
console.log('invoking withdraw', vaultAddr, amount)
return await vault['withdraw(uint256)'](amount)
})
new WithdrawNativeTransaction(s.chainId, vaultAddr, amount).submit()
floatAmount.value = 0
emit('update:modelValue', false)
}

View File

@@ -29,20 +29,21 @@
<script setup>
import {orderFuncs, useChartOrderStore} from "@/orderbuild.js";
import {addSymbolChangedCallback, removeSymbolChangedCallback} from "@/charts/chart.js";
import {computed, onBeforeUnmount, ref} from "vue";
import {computed, onBeforeUnmount, ref, toRaw, watchEffect} from "vue";
import {useOrderStore, useStore} from "@/store/store.js";
import {routeFinder} from "@/blockchain/route.js";
import ChartOrder from "@/components/chart/ChartOrder.vue";
import {useTheme} from "vuetify";
import {pendOrder} from "@/blockchain/wallet.js";
import {useWalletStore} from "@/blockchain/wallet.js";
import ToolbarPane from "@/components/chart/ToolbarPane.vue";
import NeedsChart from "@/components/NeedsChart.vue";
import {nav} from "@/misc.js";
import {PlaceOrderTransaction} from "@/blockchain/transaction.js";
const s = useStore()
const co = useChartOrderStore()
const os = useOrderStore()
const ws = useWalletStore()
function changeSymbol(symbol) {
console.log('changeSymbol', symbol)
@@ -79,6 +80,32 @@ function cancelOrder() {
showResetDialog.value = true
}
watchEffect(()=>{
const removable = []
for (const order of ws.pendingOrders) {
console.log('pend state', order.state)
switch (order.state) {
case PendingOrderState.Sent:
break
case PendingOrderState.Rejected:
removable.push(order)
break
case PendingOrderState.Signing:
break
case PendingOrderState.Submitted:
removable.push(order)
break
default:
console.error('unknown pend state', order.state)
}
}
if (removable.length>0) {
if (ws.pendingOrders.length!==removable.length)
console.error('Not all orders were rejected') // todo multiple orders / order group
ws.pendingOrders = []
}
})
async function placeOrder() {
const chartOrders = co.orders;
@@ -90,13 +117,11 @@ async function placeOrder() {
built.push(order)
}
console.log('place orders', built)
if (built.length !== 1) {
console.error('Multiple orders not supported')
if (ws.transaction!==null) {
console.error('Transaction already in progress')
}
else {
await pendOrder(built[0])
co.resetOrders()
nav('Status')
new PlaceOrderTransaction(s.chainId, toRaw(built[0])).submit()
}
}

View File

@@ -9,27 +9,18 @@
<toolbar-button tooltip="Assets" icon="mdi-currency-btc" route="Assets"/>
<!-- mdi-format-list-checks mdi-format-list-bulleted-square -->
<toolbar-button tooltip="Status" icon="mdi-format-list-checks" route="Status"/>
<v-btn variant="text" icon="mdi-help-circle-outline" text="Info" @click="showCorp"></v-btn>
<v-btn variant="text" icon="mdi-information-outline" text="Info" @click="showCorp"></v-btn>
</div>
</div>
</template>
<script setup>
import {useStore} from "@/store/store.js";
import {useChartOrderStore} from "@/orderbuild.js";
import {useTheme} from "vuetify";
import ToolbarButton from "@/components/chart/ToolbarButton.vue";
import beta from "@/components/Beta.vue";
import Logo from "@/components/Logo.vue";
import {nav} from "@/misc.js";
const props = defineProps(['title', 'icon'])
const s = useStore()
const co = useChartOrderStore()
const theme = useTheme().current
function showCorp() {
window.open('https://dexorder.trade/', 'dexorder')
}

View File

@@ -1,12 +1,95 @@
<template>
<v-app>
<main-view/>
<v-dialog v-model="showTransactionDialog" max-width="300">
<v-card :title="title">
<v-card-text v-if="description!==null">{{description}}</v-card-text>
<v-card-text>Confirm this {{noun}} in your wallet.</v-card-text>
</v-card>
</v-dialog>
</v-app>
</template>
<script setup>
import MainView from './MainView.vue'
import {useStore} from "@/store/store.js";
import {computed} from "vue";
import {useWalletStore} from "@/blockchain/wallet.js";
import {TransactionType} from "@/blockchain/transaction.js";
import {FixedNumber} from "ethers";
const s = useStore()
const ws = useWalletStore()
const showTransactionDialog = computed(()=>ws.transaction!==null)
const title = computed(()=>{
switch (ws.transaction?.type) {
case TransactionType.PlaceOrder:
return "Placing Order"
case TransactionType.CancelOrder:
return "Canceling Order"
case TransactionType.CancelAll:
return "Cancel All Orders"
case TransactionType.Wrap:
return "Wrap"
case TransactionType.Unwrap:
return "Unwrap"
case TransactionType.WithdrawNative:
case TransactionType.Withdraw:
return "Withdraw"
default:
return null
}
})
const description = computed(()=>{
const tx = ws.transaction
switch (tx?.type) {
case TransactionType.PlaceOrder:
return describeOrder(tx.order)
case TransactionType.CancelOrder:
return null // todo fetch the order status and describe it
case TransactionType.CancelAll:
return null
case TransactionType.Wrap:
return `Wrap ${FixedNumber.fromValue(tx.amount,18)} ETH` // todo native token symbol and decimals
case TransactionType.Unwrap:
return `Unwrap ${FixedNumber.fromValue(tx.amount,18)} WETH` // todo wrapped token symbol and decimals
case TransactionType.WithdrawNative:
return `Withdraw ${FixedNumber.fromValue(tx.amount,18)} ETH` // todo native token symbol and decimals
case TransactionType.Withdraw:
return `Withdraw ${FixedNumber.fromValue(tx.amount,tx.token.d)} ${tx.token.s}`
default:
return null
}
})
const noun = computed(()=>{
const tx = ws.transaction
switch (tx?.type) {
case TransactionType.PlaceOrder:
return 'order'
case TransactionType.CancelOrder:
return 'cancelation'
case TransactionType.CancelAll:
return 'cancelation'
case TransactionType.Wrap:
return 'wrapping'
case TransactionType.Unwrap:
return 'unwrapping'
case TransactionType.WithdrawNative:
return 'withdrawal'
case TransactionType.Withdraw:
return 'withdrawal'
default:
return null
}
})
function describeOrder(order) {
return null // todo
}
</script>

View File

@@ -144,7 +144,7 @@ export function inversionPreference(chainId, base, quote) {
const inputInverted = base.a > quote.a
const token0 = !inputInverted ? base.a : quote.a
const token1 = inputInverted ? base.a : quote.a
const key = [chainId, token0, token1];
const key = [chainId, token0, token1]; // todo chainId shouldn't matter
const prefs = usePrefStore()
if (!(key in prefs.inverted)) {
// todo prefer stablecoins as the quote asset
@@ -157,6 +157,7 @@ export function inversionPreference(chainId, base, quote) {
break // definitely inverted
}
}
console.log('inverted?', base, quote, preferInverted)
prefs.inverted[key] = preferInverted
}
// console.log('inversion preference', base, quote, prefs.inverted[key], inputInverted)

View File

@@ -40,8 +40,8 @@ export async function notifyFillEvent(chainId, status, trancheIndex, fill) {
const quoteAddr = status.order.inverted ? low : high
const buy = status.order.tokenIn === quoteAddr
const [base, quote] = await Promise.all([getToken(chainId, baseAddr), getToken(chainId, quoteAddr)]);
const baseAmount = (buy ? fill.filledOut : fill.filledIn) * 10**-base.d
const quoteAmount = (buy ? fill.filledIn : fill.filledOut) * 10**-quote.d
const baseAmount = Number(buy ? fill.filledOut : fill.filledIn) * 10**-base.d
const quoteAmount = Number(buy ? fill.filledIn : fill.filledOut) * 10**-quote.d
const average = quoteAmount / baseAmount
const title = `${buy?"Bought":"Sold"} ${baseAmount.toPrecision(5)} ${base.s}`;
const msg = title +

View File

@@ -53,7 +53,7 @@ socket.on('vaults', (chainId, owner, vaults)=>{
s.vaults = vaults
if( vaults.length ) {
const vault = vaults[0]
flushOrders(vault)
flushOrders(chainId, owner, 0, vault)
}
}
})