mobile fixes
This commit is contained in:
@@ -6,12 +6,9 @@
|
||||
|
||||
<script setup>
|
||||
import SupportChat from "@/components/SupportChat.vue";
|
||||
import {detectChain} from "@/blockchain/wallet.js";
|
||||
import WelcomeDialog from "@/components/WelcomeDialog.vue";
|
||||
import {usePrefStore} from "@/store/store.js";
|
||||
|
||||
detectChain()
|
||||
|
||||
const prefs = usePrefStore()
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {provider as walletProvider} from "@/blockchain/provider.js";
|
||||
import {ethers} from "ethers";
|
||||
import {AbiURLCache} from "../common.js";
|
||||
import {provider as walletProvider} from "@/blockchain/wallet.js";
|
||||
|
||||
export const abiCache = new AbiURLCache('/contract/out/')
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {uint32max, uint64max} from "@/misc.js";
|
||||
import {encodeIEE754} from "@/common.js";
|
||||
import {DEFAULT_SLIPPAGE, MIN_SLIPPAGE} from "@/orderbuild.js";
|
||||
|
||||
|
||||
export const MAX_FRACTION = 65535;
|
||||
export const NO_CONDITIONAL_ORDER = uint64max;
|
||||
@@ -8,6 +8,10 @@ export const NO_OCO = uint64max;
|
||||
export const DISTANT_PAST = 0
|
||||
export const DISTANT_FUTURE = uint32max
|
||||
|
||||
export const MIN_EXECUTION_TIME = 60 // give at least one full minute for each tranche to trigger
|
||||
export const DEFAULT_SLIPPAGE = 0.0030;
|
||||
export const MIN_SLIPPAGE = 0.0001;
|
||||
|
||||
// struct SwapOrder {
|
||||
// address tokenIn;
|
||||
// address tokenOut;
|
||||
@@ -253,4 +257,3 @@ export function parseFeeSchedule(sched) {
|
||||
fillFee: fillFeeHalfBps/1_000_000 // fillFee is a multiplier on the filled volume. 0.0001 = 0.1% of the output token taken as a fee
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {socket} from "@/socket.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {Exchange} from "@/blockchain/orderlib.js";
|
||||
import {uniswapV3PoolAddress} from "@/blockchain/uniswap.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {newContract} from "@/blockchain/contract.js";
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
const subscriptionCounts = {} // key is route and value is a subscription counter
|
||||
export const WIDE_PRICE_FORMAT = {decimals:38, width:512, signed:false}; // 38 decimals is 127 bits
|
||||
|
||||
1
src/blockchain/provider.js
Normal file
1
src/blockchain/provider.js
Normal file
@@ -0,0 +1 @@
|
||||
export let provider = null
|
||||
@@ -2,7 +2,8 @@ import {Exchange} from "@/blockchain/orderlib.js";
|
||||
import {useOrderStore, useStore} from "@/store/store.js";
|
||||
import {queryHelperContract} from "@/blockchain/contract.js";
|
||||
import {SingletonCoroutine} from "@/misc.js";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
|
||||
|
||||
export async function findRoute(helper, chainId, tokenA, tokenB) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {socket} from "@/socket.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {metadataMap} from "@/version.js";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {newContract} from "@/blockchain/contract.js";
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
|
||||
// synchronous version may return null but will trigger a lookup
|
||||
|
||||
@@ -1,28 +1,13 @@
|
||||
import {nav, sleep, uuid} from "@/misc.js";
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
||||
import {sleep, uuid} from "@/misc.js";
|
||||
import {vaultContract} from "@/blockchain/contract.js";
|
||||
import {ensureVault, provider, switchChain, useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {switchChain, useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {toRaw} from "vue";
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
import {placementFee} from "@/fees.js";
|
||||
import {router} from "@/router/router.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) {
|
||||
@@ -195,7 +180,8 @@ export class PlaceOrderTransaction extends Transaction {
|
||||
super.end(state)
|
||||
if (state === TransactionState.Mined) {
|
||||
useChartOrderStore().resetOrders()
|
||||
nav('Status')
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name: 'Status'})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -280,4 +266,3 @@ export class UnwrapTransaction extends Transaction {
|
||||
return await vaultContract.unwrap(this.amount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
17
src/blockchain/transactionDecl.js
Normal file
17
src/blockchain/transactionDecl.js
Normal file
@@ -0,0 +1,17 @@
|
||||
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,
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
import {BrowserProvider, ethers} from "ethers";
|
||||
import {useStore} from "@/store/store";
|
||||
import {socket} from "@/socket.js";
|
||||
import {errorSuggestsMissingVault, SingletonCoroutine} from "@/misc.js";
|
||||
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
|
||||
import {defineStore} from "pinia";
|
||||
import {computed, ref} from "vue";
|
||||
import {metadataMap, version} from "@/version.js";
|
||||
import {CancelAllTransaction, TransactionState, TransactionType} from "@/blockchain/transaction.js";
|
||||
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
||||
import {track} from "@/track.js";
|
||||
|
||||
|
||||
export let provider = null
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
|
||||
export const useWalletStore = defineStore('wallet', ()=>{
|
||||
@@ -121,17 +119,17 @@ export function detectChain() {
|
||||
try {
|
||||
window.ethereum.on('chainChanged', onChainChanged);
|
||||
window.ethereum.on('accountsChanged', onAccountsChanged);
|
||||
new ethers.BrowserProvider(window.ethereum).getNetwork().then((network)=>{
|
||||
const chainId = network.chainId
|
||||
onChainChanged(chainId)
|
||||
})
|
||||
}
|
||||
catch (e) {
|
||||
console.log('Could not connect change hooks to wallet', e)
|
||||
return
|
||||
}
|
||||
new ethers.BrowserProvider(window.ethereum).getNetwork().then((network)=>{
|
||||
const chainId = network.chainId
|
||||
onChainChanged(chainId)
|
||||
})
|
||||
}
|
||||
|
||||
detectChain()
|
||||
|
||||
const errorHandlingProxy = {
|
||||
get(target, prop, proxy) {
|
||||
@@ -308,11 +306,6 @@ export async function cancelOrder(vault, orderIndex) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function cancelAll(vault) {
|
||||
new CancelAllTransaction(useStore().chainId, vault).submit()
|
||||
}
|
||||
|
||||
|
||||
async function progressTransactions() {
|
||||
const s = useStore()
|
||||
const ws = useWalletStore();
|
||||
@@ -324,7 +317,7 @@ async function progressTransactions() {
|
||||
signer = await provider.getSigner()
|
||||
}
|
||||
catch (e) {
|
||||
console.log('signer error', e.code, e.info.error.code)
|
||||
console.log('signer error', e.code, e.info?.error?.code)
|
||||
if (e?.info?.error?.code === 4001) {
|
||||
console.log('signer rejected')
|
||||
signer = null
|
||||
@@ -643,4 +636,4 @@ export async function addNetworkAndConnectWallet(chainId) {
|
||||
if (e.code !== 4001)
|
||||
console.log('connectWallet() failed', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
import {convertTvResolution, loadOHLC} from './ohlc.js';
|
||||
import {metadata} from "@/version.js";
|
||||
import FlexSearch from "flexsearch";
|
||||
@@ -5,12 +6,11 @@ import {useChartOrderStore} from "@/orderbuild.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {subOHLC, unsubOHLC} from "@/blockchain/ohlcs.js";
|
||||
import {ohlcStart} from "@/charts/chart-misc.js";
|
||||
|
||||
import {timestamp, USD_FIAT} from "@/common.js";
|
||||
import {timestamp} from "@/common.js";
|
||||
import {erc20Contract} from "@/blockchain/contract.js";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {track} from "@/track.js";
|
||||
|
||||
|
||||
const DEBUG_LOGGING = false
|
||||
const log = DEBUG_LOGGING ? console.log : ()=>{}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {socket} from "@/socket.js";
|
||||
import {useRoute} from "vue-router";
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
const s = useStore()
|
||||
|
||||
|
||||
65
src/components/DebugConsole.vue
Normal file
65
src/components/DebugConsole.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="debug-console">
|
||||
<div v-for="(entry, idx) in logs" :key="idx" :class="['log-entry', entry.type]">
|
||||
[{{ entry.type }}] {{ entry.message }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
|
||||
const logs = ref([]);
|
||||
|
||||
function stringify(args) {
|
||||
return args.map(arg => {
|
||||
if (typeof arg === 'object') {
|
||||
try { return JSON.stringify(arg); } catch { return String(arg); }
|
||||
}
|
||||
return String(arg);
|
||||
}).join(' ');
|
||||
}
|
||||
|
||||
let original = {};
|
||||
|
||||
onMounted(() => {
|
||||
['log', 'warn', 'error', 'info'].forEach(type => {
|
||||
// Save the original method
|
||||
original[type] = console[type];
|
||||
console[type] = function(...args) {
|
||||
logs.value.push({
|
||||
type,
|
||||
message: stringify(args)
|
||||
});
|
||||
// Optionally limit log length:
|
||||
if (logs.value.length > 200) logs.value.shift();
|
||||
original[type].apply(console, args);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// Restore the original methods
|
||||
Object.keys(original).forEach(type => {
|
||||
if (original[type]) console[type] = original[type];
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.debug-console {
|
||||
background: #1a1a1a;
|
||||
color: #0f0;
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
padding: 10px;
|
||||
max-height: 260px;
|
||||
overflow-y: auto;
|
||||
border-radius: 5px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.log-entry { margin-bottom: 2px; }
|
||||
.log-entry.warn { color: #ff0; }
|
||||
.log-entry.error { color: #f55; }
|
||||
.log-entry.info { color: #0cf; }
|
||||
</style>
|
||||
@@ -36,8 +36,8 @@
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed, ref} from "vue";
|
||||
import Btn from "@/components/Btn.vue";
|
||||
import {socket} from "@/socket.js";
|
||||
import {metadata} from "@/version.js";
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
const DISABLED_DURATION = 60_000;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import router from "@/router/index.js";
|
||||
import {router} from "@/router/router.js";
|
||||
const s = useStore()
|
||||
|
||||
function nav(path) {
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
</div>
|
||||
</v-card-item>
|
||||
<v-card-actions class="d-flex justify-space-evenly mb-4">
|
||||
<v-btn variant="outlined" color="red" @click="nav('Assets')">Cancel</v-btn>
|
||||
<v-btn variant="outlined" color="red" @click="// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name: 'Assets'})">Cancel</v-btn>
|
||||
<v-btn variant="flat" color="green" :disabled="!valid()" @click="placeOrder">Place Dexorder</v-btn>
|
||||
</v-card-actions>
|
||||
</phone-card>
|
||||
@@ -23,12 +24,13 @@ import {useOrderStore, useStore} from "@/store/store";
|
||||
import PhoneCard from "@/components/PhoneCard.vue";
|
||||
import Amount from "@/components/Amount.vue"
|
||||
// noinspection ES6UnusedImports
|
||||
import {nav, SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||
import {SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||
import {newOrder} from "@/blockchain/orderlib.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import PairChoice from "@/components/PairChoice.vue";
|
||||
import NeedsSigner from "@/components/NeedsSigner.vue";
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
import {router} from "@/router/router.js";
|
||||
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
import {usePrefStore} from "@/store/store.js";
|
||||
import {computed, ref, watch} from "vue";
|
||||
|
||||
import {socket} from "@/socket.js";
|
||||
import TosCard from "@/components/TosCard.vue";
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
// UPDATE THIS WHEN CHANGING THE TOS
|
||||
const CURRENT_VERSION='2024-11-18' // this must be a parseable date
|
||||
|
||||
@@ -60,12 +60,13 @@
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {computed, defineAsyncComponent, onUnmounted, ref, watchEffect} from "vue";
|
||||
import {vaultAddress} from "@/blockchain/contract.js";
|
||||
import {ensureVault, provider} from "@/blockchain/wallet.js";
|
||||
import {ensureVault} from "@/blockchain/wallet.js";
|
||||
import CopyButton from "@/components/CopyButton.vue";
|
||||
import Withdraw from "@/components/Withdraw.vue";
|
||||
import NativeRow from "@/components/NativeRow.vue";
|
||||
import NativeWrap from "@/components/NativeWrap.vue";
|
||||
import WithdrawNative from "@/components/WithdrawNative.vue";
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
|
||||
const TokenRow = defineAsyncComponent(()=>import('./TokenRow.vue'))
|
||||
const s = useStore()
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<toolbar-pane title="Status" icon="mdi-format-list-bulleted-square">
|
||||
<template #toolbar>
|
||||
<v-btn variant="text" v-if="s.vault" prepend-icon="mdi-delete-alert" color="red"
|
||||
@click="cancelAll(s.vault)" :disabled="!anyOrdersOpen"
|
||||
@click="(async function (vault){
|
||||
new CancelAllTransaction(useStore().chainId, vault).submit()
|
||||
})(s.vault)" :disabled="!anyOrdersOpen"
|
||||
text="Cancel All"/>
|
||||
</template>
|
||||
<needs-signer>
|
||||
@@ -16,10 +18,10 @@
|
||||
import ToolbarPane from "@/components/chart/ToolbarPane.vue";
|
||||
import Orders from "@/components/Status.vue";
|
||||
import NeedsSigner from "@/components/NeedsSigner.vue";
|
||||
import {cancelAll} from "@/blockchain/wallet.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {computed} from "vue";
|
||||
import {isOpen} from "@/blockchain/orderlib.js";
|
||||
import {CancelAllTransaction} from "@/blockchain/transaction.js";
|
||||
|
||||
const s = useStore()
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {builderDefaults, DEFAULT_SLIPPAGE, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {allocationText, ShapeType} from "@/charts/shape.js";
|
||||
import {sideColor, SingletonCoroutine, toPrecision, vAutoSelect} from "@/misc.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
@@ -57,7 +57,7 @@ import BuilderPanel from "@/components/chart/BuilderPanel.vue";
|
||||
import {ohlcStart} from "@/charts/chart-misc.js";
|
||||
import Color from "color";
|
||||
import OrderAmount from "@/components/chart/OrderAmount.vue";
|
||||
import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import {DEFAULT_SLIPPAGE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import {getFeeSchedule} from "@/fees.js";
|
||||
import {NATIVE_TOKEN} from "@/common.js";
|
||||
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {builderDefaults, DEFAULT_SLIPPAGE, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {allocationText, VLine} from "@/charts/shape.js";
|
||||
import {sideColor} from "@/misc.js";
|
||||
import {useOrderStore, usePrefStore, useStore} from "@/store/store.js";
|
||||
import {DISTANT_FUTURE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import {DEFAULT_SLIPPAGE, DISTANT_FUTURE, MAX_FRACTION, MIN_EXECUTION_TIME, newTranche} from "@/blockchain/orderlib.js";
|
||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||
import {computed, ref, watchEffect} from "vue";
|
||||
import {chart, dragging} from "@/charts/chart.js";
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {builderDefaults, builderFuncs, DEFAULT_SLIPPAGE, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {builderDefaults, builderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {computed, onMounted, onUnmounted} from "vue";
|
||||
import {newTranche} from "@/blockchain/orderlib.js";
|
||||
import {DEFAULT_SLIPPAGE, newTranche} from "@/blockchain/orderlib.js";
|
||||
|
||||
const co = useChartOrderStore()
|
||||
const props = defineProps(['order', 'builder'])
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
<script setup>
|
||||
import {loadShareUrl} from "@/share.js";
|
||||
import router from "@/router/index.js";
|
||||
import {socket} from "@/socket.js";
|
||||
import {router} from "@/router/router.js";
|
||||
import {useRoute} from "vue-router";
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
const route = useRoute()
|
||||
const code = route.params.code
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="d-flex mb-1 align-center w-100">
|
||||
<logo class="d-flex align-end clickable logo-large ml-1" @click="nav('Order')" :show-tag="true" max-height="32"/>
|
||||
<logo class="d-flex align-end clickable logo-large ml-1" @click="// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name: 'Order'})" :show-tag="true" max-height="32"/>
|
||||
<slot/>
|
||||
<div class="ml-auto d-flex align-center">
|
||||
<span class="title mr-4">{{title}}</span>
|
||||
@@ -17,7 +18,7 @@
|
||||
<script setup>
|
||||
import ToolbarButton from "@/components/chart/ToolbarButton.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import {router} from "@/router/router.js";
|
||||
|
||||
const props = defineProps(['title', 'icon'])
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
<script setup>
|
||||
import {computed} from "vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import {nav} from "/src/misc.js"
|
||||
|
||||
const props = defineProps(['icon', 'route', 'tooltip', 'href', 'target'])
|
||||
const router = useRoute();
|
||||
@@ -29,7 +28,8 @@ function click() {
|
||||
|
||||
}
|
||||
else
|
||||
nav(props.route)
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
router1.push({name: props.route})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
</v-card-text>
|
||||
<div class="w-100 d-flex justify-center my-6 actions">
|
||||
<app-btn/>
|
||||
<v-btn prepend-icon="mdi-information-outline" variant="flat" text="How It Works" @click="nav('HowItWorks')"/>
|
||||
<v-btn prepend-icon="mdi-information-outline" variant="flat" text="How It Works" @click="// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name: 'HowItWorks'})"/>
|
||||
</div>
|
||||
</v-card>
|
||||
</template>
|
||||
@@ -36,10 +37,8 @@ import beta from "@/components/Beta.vue";
|
||||
import Soon from "@/components/Soon.vue";
|
||||
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import AppBtn from "@/corp/AppBtn.vue";
|
||||
import Social from "@/components/Social.vue";
|
||||
|
||||
import {router} from "@/router/router.js";
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -49,7 +49,8 @@
|
||||
</v-card-text>
|
||||
<v-card-actions class="justify-center my-6 actions">
|
||||
<app-btn/>
|
||||
<v-btn prepend-icon="mdi-home-outline" variant="flat" text="Home" @click="nav('Home')"/>
|
||||
<v-btn prepend-icon="mdi-home-outline" variant="flat" text="Home" @click="// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name: 'Home'})"/>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</template>
|
||||
@@ -57,8 +58,8 @@
|
||||
<script setup>
|
||||
|
||||
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import AppBtn from "@/corp/AppBtn.vue";
|
||||
import {router} from "@/router/router.js";
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
<!-- <v-app-bar-nav-icon @click="s.nav=!s.nav" icon="mdi-plus"/>-->
|
||||
|
||||
<v-app-bar-title>
|
||||
<logo @click="nav('Home')" class="clickable"/>
|
||||
<logo @click="// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name: 'Home'})" class="clickable"/>
|
||||
<social class="d-inline" size="small"/>
|
||||
</v-app-bar-title>
|
||||
|
||||
<v-btn @click="nav('HowItWorks')" prepend-icon="mdi-information-outline" text="How It Works"/>
|
||||
<v-btn @click="// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name: 'HowItWorks'})" prepend-icon="mdi-information-outline" text="How It Works"/>
|
||||
<v-btn prepend-icon="mdi-arrow-up-bold" variant="tonal" color="primary" @click="openApp" text="Launch App"/>
|
||||
|
||||
</v-app-bar>
|
||||
@@ -16,8 +18,8 @@
|
||||
<script setup>
|
||||
import {useTheme} from "vuetify";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import Social from "@/components/Social.vue";
|
||||
import {router} from "@/router/router.js";
|
||||
|
||||
const theme = useTheme().current
|
||||
|
||||
|
||||
47
src/debug_console.js
Normal file
47
src/debug_console.js
Normal file
@@ -0,0 +1,47 @@
|
||||
(function() {
|
||||
let debugDiv = document.createElement('div');
|
||||
debugDiv.id = 'debug-log';
|
||||
debugDiv.setAttribute(
|
||||
'style',
|
||||
`
|
||||
background:#222 !important;
|
||||
color:#0f0 !important;
|
||||
padding:8px !important;
|
||||
font-family:monospace !important;
|
||||
font-size:14px !important;
|
||||
position:fixed !important;
|
||||
left:0 !important; right:0 !important;
|
||||
bottom:0 !important;
|
||||
max-height:35vh !important;
|
||||
width:100vw !important;
|
||||
overflow-y:auto !important;
|
||||
z-index:9999 !important;
|
||||
pointer-events:auto !important;
|
||||
box-shadow:0 0 8px #000 !important;
|
||||
touch-action: auto !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
white-space: pre-wrap !important;
|
||||
word-break: break-word !important;
|
||||
`
|
||||
);
|
||||
document.body.appendChild(debugDiv);
|
||||
|
||||
function printLog(type, args) {
|
||||
let msg = Array.from(args).map(a => {
|
||||
try { return typeof a === 'object' ? JSON.stringify(a, null, 2) : String(a); }
|
||||
catch { return String(a); }
|
||||
}).join(' ');
|
||||
let line = document.createElement('div');
|
||||
line.textContent = `[${type}] ${msg}`;
|
||||
debugDiv.appendChild(line);
|
||||
debugDiv.scrollTop = debugDiv.scrollHeight;
|
||||
}
|
||||
|
||||
['trace', 'log', 'info', 'warn', 'error'].forEach(type => {
|
||||
let orig = console[type];
|
||||
console[type] = function(...args) {
|
||||
printLog(type, args);
|
||||
orig.apply(console, args);
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -1,7 +1,7 @@
|
||||
import {newContract, vaultContract} from "@/blockchain/contract.js";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {timestamp} from "@/common.js";
|
||||
import TTLCache from "@isaacs/ttlcache";
|
||||
import {provider} from "@/blockchain/provider.js";
|
||||
|
||||
|
||||
async function getFeeManagerContract(vaultContract) {
|
||||
|
||||
@@ -19,9 +19,9 @@ import MainView from './MainView.vue'
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {computed} from "vue";
|
||||
import {useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {TransactionState, TransactionType} from "@/blockchain/transaction.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import PoolSelectionDialog from "@/components/PoolSelectionDialog.vue";
|
||||
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
||||
|
||||
const s = useStore()
|
||||
const ws = useWalletStore()
|
||||
|
||||
@@ -13,7 +13,7 @@ import { createApp } from 'vue'
|
||||
// Plugins
|
||||
import { registerPlugins } from '@/plugins'
|
||||
import '@/styles/style.scss'
|
||||
import "./socket.js"
|
||||
import "./socketInit.js"
|
||||
import "./version.js"
|
||||
|
||||
BigInt.prototype.toJSON = function() { return this.toString() }
|
||||
|
||||
12
src/misc.js
12
src/misc.js
@@ -3,13 +3,8 @@ import {usePrefStore, useStore} from "@/store/store.js";
|
||||
import {token} from "@/blockchain/token.js";
|
||||
import Color from "color";
|
||||
import {DateTime} from "luxon";
|
||||
import router from "@/router/index.js";
|
||||
import {dateString} from "@/common.js";
|
||||
|
||||
export function nav(name) {
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
router.push({name})
|
||||
}
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
const QUOTE_SYMBOLS = [
|
||||
// in order of preference
|
||||
@@ -153,10 +148,7 @@ export function inversionPreference(chainId, base, quote) {
|
||||
|
||||
export const sleep = ms => new Promise(r => setTimeout(r, ms))
|
||||
|
||||
export function uuid() {
|
||||
// noinspection JSUnresolvedReference
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
export function uuid() {return uuidv4()}
|
||||
|
||||
export function lightenColor(color, lightness = 85, alpha = null) {
|
||||
let c = new Color(color).hsl()
|
||||
|
||||
@@ -2,15 +2,14 @@ import {getToken} from "@/blockchain/token.js";
|
||||
|
||||
let native = false // whether native browser notifications are allowed
|
||||
|
||||
Notification.requestPermission()
|
||||
.then(permission => {
|
||||
console.log(`notification permission: ${permission}`);
|
||||
native = permission === 'granted'
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(`notification permission error: ${error}`);
|
||||
native = false;
|
||||
});
|
||||
if ('Notification' in window) {
|
||||
Notification.requestPermission()
|
||||
.then(permission => {
|
||||
console.log(`notification permission: ${permission}`);
|
||||
native = permission === 'granted'
|
||||
})
|
||||
.catch(error => {console.error(`notification permission error: ${error}`);});
|
||||
}
|
||||
|
||||
|
||||
export function notify(title, message=null) {
|
||||
@@ -44,4 +43,4 @@ export async function notifyFillEvent(chainId, status, trancheIndex, fill) {
|
||||
` for ${quoteAmount.toPrecision(5)} ${quote.s} average ${average.toPrecision(5)} ${base.s}/${quote.s}}`;
|
||||
// todo buy/sell arrow icon
|
||||
notify(title)
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,6 @@ import {computed, ref} from "vue";
|
||||
import Color from "color";
|
||||
|
||||
|
||||
export const MIN_EXECUTION_TIME = 60 // give at least one full minute for each tranche to trigger
|
||||
export const DEFAULT_SLIPPAGE = 0.0030;
|
||||
export const MIN_SLIPPAGE = 0.0001;
|
||||
|
||||
|
||||
// Builders are data objects which store a configuration state
|
||||
// the component name must match a corresponding Vue component in the BuilderFactory.vue component, which is responsible
|
||||
// for instantiating the UI component for a given builder dictionary, based on its builder.component field.
|
||||
@@ -23,6 +18,7 @@ export function newBuilder( component, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
console.log('new default order')
|
||||
// Orders hold an amount and builders
|
||||
// noinspection JSUnusedLocalSymbols
|
||||
const Order = {
|
||||
@@ -30,6 +26,7 @@ const Order = {
|
||||
amount: 0,
|
||||
builders: [],
|
||||
}
|
||||
console.log('new default order completed')
|
||||
|
||||
|
||||
// the key is order.id and the value is a function() that returns an order
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
import { loadFonts } from './webfontloader'
|
||||
import vuetify from './vuetify'
|
||||
import {pinia} from '../store/pinia.js'
|
||||
import router from '../router'
|
||||
import {setRouter} from '../router/router.js'
|
||||
import {newRouter} from '../router/newRouter.js'
|
||||
import vsp from "vue-scroll-picker";
|
||||
|
||||
import "vue-scroll-picker/lib/style.css";
|
||||
|
||||
const router = newRouter();
|
||||
setRouter(router)
|
||||
|
||||
export function registerPlugins (app) {
|
||||
loadFonts().catch((e)=>console.error('Could not load fonts!',e))
|
||||
app
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
// Composables
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('@/layouts/chart/ChartLayout.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'App',
|
||||
path: '/',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
||||
},
|
||||
{
|
||||
name: 'Shared',
|
||||
path: '/shared/:code',
|
||||
component: ()=> import('@/components/chart/Shared.vue')
|
||||
},
|
||||
{
|
||||
name: 'Order',
|
||||
path: '/order',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
||||
},
|
||||
{
|
||||
name: 'Assets',
|
||||
path: '/assets',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartVault.vue'),
|
||||
},
|
||||
{
|
||||
name: 'Status',
|
||||
path: '/status',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartStatus.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(process.env.BASE_URL),
|
||||
routes,
|
||||
})
|
||||
|
||||
export default router
|
||||
10
src/router/newRouter.js
Normal file
10
src/router/newRouter.js
Normal file
@@ -0,0 +1,10 @@
|
||||
// Composables
|
||||
import {createRouter, createWebHistory} from 'vue-router'
|
||||
import {routes} from "@/router/routes.js";
|
||||
|
||||
export function newRouter() {
|
||||
return createRouter({
|
||||
history: createWebHistory(process.env.BASE_URL),
|
||||
routes,
|
||||
})
|
||||
}
|
||||
3
src/router/router.js
Normal file
3
src/router/router.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export let router = null
|
||||
|
||||
export function setRouter (r) { router = r }
|
||||
45
src/router/routes.js
Normal file
45
src/router/routes.js
Normal file
@@ -0,0 +1,45 @@
|
||||
export const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('@/layouts/chart/ChartLayout.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'App',
|
||||
path: '/',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
||||
},
|
||||
{
|
||||
name: 'Shared',
|
||||
path: '/shared/:code',
|
||||
component: () => import('@/components/chart/Shared.vue')
|
||||
},
|
||||
{
|
||||
name: 'Order',
|
||||
path: '/order',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
||||
},
|
||||
{
|
||||
name: 'Assets',
|
||||
path: '/assets',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartVault.vue'),
|
||||
},
|
||||
{
|
||||
name: 'Status',
|
||||
path: '/status',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('@/components/chart/ChartStatus.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
@@ -4,6 +4,7 @@ import {changeIntervalSecs, onChartReady, setSymbol, widget} from "@/charts/char
|
||||
import {usePrefStore, useStore} from "@/store/store.js";
|
||||
import {lookupSymbol} from "@/charts/datafeed.js";
|
||||
import {track} from "@/track.js";
|
||||
|
||||
import {socket} from "@/socket.js";
|
||||
|
||||
export async function getShareUrl() {
|
||||
|
||||
152
src/socket.js
152
src/socket.js
@@ -1,10 +1,4 @@
|
||||
import {io} from "socket.io-client";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {ensureVault, flushOrders} from "@/blockchain/wallet.js";
|
||||
import {parseElaboratedOrderStatus} from "@/blockchain/orderlib.js";
|
||||
import { DataFeed } from "./charts/datafeed";
|
||||
import {notifyFillEvent} from "@/notify.js";
|
||||
import {refreshOHLCSubs} from "@/blockchain/ohlcs.js";
|
||||
|
||||
const socketOptions = {
|
||||
transports: ["websocket"],
|
||||
@@ -12,149 +6,3 @@ const socketOptions = {
|
||||
pingTimeout: 60000 // Timeout if no PONG in 60 seconds
|
||||
}
|
||||
export const socket = io(import.meta.env.VITE_WS_URL || undefined, socketOptions)
|
||||
|
||||
socket.on('connect', () => {
|
||||
console.log(new Date(), 'ws connected')
|
||||
const s = useStore();
|
||||
s.connected = true
|
||||
if (s.chainId && s.account)
|
||||
socket.emit('address', s.chainId, s.account)
|
||||
refreshOHLCSubs()
|
||||
})
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log(new Date(), 'ws disconnected')
|
||||
useStore().connected = false
|
||||
})
|
||||
|
||||
socket.on('approvedRegion', (approved) => {
|
||||
console.log('approved region', approved)
|
||||
useStore().regionApproved = approved
|
||||
})
|
||||
|
||||
socket.on('approvedWallet', (approved) => {
|
||||
console.log('approved wallet', approved)
|
||||
useStore().walletApproved = approved
|
||||
})
|
||||
|
||||
socket.on('p', async (chainId, pool, price) => {
|
||||
console.log('pool price from message', chainId, pool, price)
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
s.poolPrices[[chainId,pool]] = price
|
||||
})
|
||||
|
||||
socket.on('ohlc', async (chainId, poolPeriod, ohlcs) => {
|
||||
// console.log('pool bars', poolPeriod, ohlcs)
|
||||
if (ohlcs && ohlcs.length) {
|
||||
const split = poolPeriod.indexOf('|')
|
||||
const pool = poolPeriod.slice(0,split)
|
||||
useStore().poolPrices[[chainId, pool]] = parseFloat(ohlcs[ohlcs.length - 1][4]) // closing price
|
||||
}
|
||||
DataFeed.poolCallback(chainId, poolPeriod, ohlcs)
|
||||
})
|
||||
|
||||
socket.on('vb', async (chainId, vault, balances) => {
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
console.log('vb', vault, balances)
|
||||
s.vaultBalances[vault] = JSON.parse(balances)
|
||||
console.log('vault balances', vault, s.vaultBalances[vault])
|
||||
})
|
||||
|
||||
socket.on('vaults', (chainId, owner, vaults)=>{
|
||||
const s = useStore()
|
||||
console.log('vaults', chainId, owner, vaults)
|
||||
if( s.chainId !== chainId || s.account !== owner )
|
||||
return
|
||||
if( vaults.length > s.vaults.length ) {
|
||||
s.vaults = vaults
|
||||
if( vaults.length ) {
|
||||
const vault = vaults[0]
|
||||
flushOrders(chainId, owner, 0, vault)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('mark.usd', (chainId, token, value)=>{
|
||||
const s = useStore()
|
||||
s.markPrices[`${chainId}|${token}`] = Number(value)
|
||||
// console.log('mark.usd', token, value)
|
||||
})
|
||||
|
||||
function handleOrderStatus(chainId, vault, orderIndex, status) {
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
// message 'o' is a single order status
|
||||
const parsed = parseElaboratedOrderStatus(chainId, status);
|
||||
// console.log('o', chainId, vault, orderIndex, status, parsed)
|
||||
if( !(vault in s.orders) )
|
||||
s.orders[vault] = {}
|
||||
s.orders[vault][orderIndex] = parsed
|
||||
}
|
||||
|
||||
socket.on('os', (chainId, vault, orders) => {
|
||||
// message 'os' has multiple order statuses
|
||||
console.log('os', orders)
|
||||
for( const [orderIndex, status] of orders )
|
||||
handleOrderStatus(chainId, vault, orderIndex, status)
|
||||
})
|
||||
|
||||
socket.on( 'o', handleOrderStatus)
|
||||
|
||||
socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
console.log('of', chainId, vault, orderIndex, filled)
|
||||
if( !(vault in s.orders) ) {
|
||||
console.log('warning: got fill on an order in an unknown vault')
|
||||
return
|
||||
}
|
||||
if( !(orderIndex in s.orders[vault]) ) {
|
||||
console.log(`warning: orderIndex ${orderIndex} missing from vault ${vault}`)
|
||||
return
|
||||
}
|
||||
|
||||
const status = s.orders[vault][orderIndex]
|
||||
console.log('apply fills', status, filled)
|
||||
|
||||
let orderIn = 0n
|
||||
let orderOut = 0n
|
||||
for (const i in filled) {
|
||||
const ts = status.trancheStatus[i]
|
||||
let filledIn = 0n
|
||||
let filledOut = 0n
|
||||
const [activationTime, fills] = filled[i];
|
||||
const numOld = ts.fills.length;
|
||||
for (let i=0; i<fills.length; i++) {
|
||||
const fill = fills[i]
|
||||
let [tx, time, fi, fo, fee] = fill
|
||||
fi = BigInt(fi)
|
||||
fo = BigInt(fo)
|
||||
fee = BigInt(fee)
|
||||
filledIn += fi
|
||||
filledOut += fo
|
||||
if (i>=numOld) {
|
||||
// new fill detected
|
||||
const f = {tx, time, filledIn: fi, filledOut: fo, fee, filled: status.order.amountIsInput ? fi : fo};
|
||||
console.log('new fill', f)
|
||||
notifyFillEvent(chainId, status, i, f).catch((e)=>console.log('fill notification error', e))
|
||||
ts.fills.push(f)
|
||||
}
|
||||
}
|
||||
ts.filledIn = filledIn
|
||||
ts.filledOut = filledOut
|
||||
ts.activationTime = activationTime
|
||||
orderIn += filledIn
|
||||
orderOut += filledOut
|
||||
}
|
||||
status.filledIn = orderIn
|
||||
status.filledOut = orderOut
|
||||
status.filled = status.order.amountIsInput ? orderIn : orderOut
|
||||
|
||||
console.log('apply fills completed', status)
|
||||
})
|
||||
|
||||
153
src/socketInit.js
Normal file
153
src/socketInit.js
Normal file
@@ -0,0 +1,153 @@
|
||||
import {socket} from "@/socket.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {flushOrders} from "@/blockchain/wallet.js";
|
||||
import {parseElaboratedOrderStatus} from "@/blockchain/orderlib.js";
|
||||
import {DataFeed} from "./charts/datafeed";
|
||||
import {notifyFillEvent} from "@/notify.js";
|
||||
import {refreshOHLCSubs} from "@/blockchain/ohlcs.js";
|
||||
|
||||
socket.on('connect', () => {
|
||||
console.log(new Date(), 'ws connected')
|
||||
const s = useStore();
|
||||
s.connected = true
|
||||
if (s.chainId && s.account)
|
||||
socket.emit('address', s.chainId, s.account)
|
||||
refreshOHLCSubs()
|
||||
})
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log(new Date(), 'ws disconnected')
|
||||
useStore().connected = false
|
||||
})
|
||||
|
||||
socket.on('approvedRegion', (approved) => {
|
||||
console.log('approved region', approved)
|
||||
useStore().regionApproved = approved
|
||||
})
|
||||
|
||||
socket.on('approvedWallet', (approved) => {
|
||||
console.log('approved wallet', approved)
|
||||
useStore().walletApproved = approved
|
||||
})
|
||||
|
||||
socket.on('p', async (chainId, pool, price) => {
|
||||
console.log('pool price from message', chainId, pool, price)
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
s.poolPrices[[chainId,pool]] = price
|
||||
})
|
||||
|
||||
socket.on('ohlc', async (chainId, poolPeriod, ohlcs) => {
|
||||
// console.log('pool bars', poolPeriod, ohlcs)
|
||||
if (ohlcs && ohlcs.length) {
|
||||
const split = poolPeriod.indexOf('|')
|
||||
const pool = poolPeriod.slice(0,split)
|
||||
useStore().poolPrices[[chainId, pool]] = parseFloat(ohlcs[ohlcs.length - 1][4]) // closing price
|
||||
}
|
||||
DataFeed.poolCallback(chainId, poolPeriod, ohlcs)
|
||||
})
|
||||
|
||||
socket.on('vb', async (chainId, vault, balances) => {
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
console.log('vb', vault, balances)
|
||||
s.vaultBalances[vault] = JSON.parse(balances)
|
||||
console.log('vault balances', vault, s.vaultBalances[vault])
|
||||
})
|
||||
|
||||
socket.on('vaults', (chainId, owner, vaults)=>{
|
||||
const s = useStore()
|
||||
console.log('vaults', chainId, owner, vaults)
|
||||
if( s.chainId !== chainId || s.account !== owner )
|
||||
return
|
||||
if( vaults.length > s.vaults.length ) {
|
||||
s.vaults = vaults
|
||||
if( vaults.length ) {
|
||||
const vault = vaults[0]
|
||||
flushOrders(chainId, owner, 0, vault)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('mark.usd', (chainId, token, value)=>{
|
||||
const s = useStore()
|
||||
s.markPrices[`${chainId}|${token}`] = Number(value)
|
||||
// console.log('mark.usd', token, value)
|
||||
})
|
||||
|
||||
function handleOrderStatus(chainId, vault, orderIndex, status) {
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
// message 'o' is a single order status
|
||||
const parsed = parseElaboratedOrderStatus(chainId, status);
|
||||
// console.log('o', chainId, vault, orderIndex, status, parsed)
|
||||
if( !(vault in s.orders) )
|
||||
s.orders[vault] = {}
|
||||
s.orders[vault][orderIndex] = parsed
|
||||
}
|
||||
|
||||
socket.on('os', (chainId, vault, orders) => {
|
||||
// message 'os' has multiple order statuses
|
||||
console.log('os', orders)
|
||||
for( const [orderIndex, status] of orders )
|
||||
handleOrderStatus(chainId, vault, orderIndex, status)
|
||||
})
|
||||
|
||||
socket.on( 'o', handleOrderStatus)
|
||||
|
||||
socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
||||
const s = useStore()
|
||||
if( s.chainId !== chainId )
|
||||
return
|
||||
console.log('of', chainId, vault, orderIndex, filled)
|
||||
if( !(vault in s.orders) ) {
|
||||
console.log('warning: got fill on an order in an unknown vault')
|
||||
return
|
||||
}
|
||||
if( !(orderIndex in s.orders[vault]) ) {
|
||||
console.log(`warning: orderIndex ${orderIndex} missing from vault ${vault}`)
|
||||
return
|
||||
}
|
||||
|
||||
const status = s.orders[vault][orderIndex]
|
||||
console.log('apply fills', status, filled)
|
||||
|
||||
let orderIn = 0n
|
||||
let orderOut = 0n
|
||||
for (const i in filled) {
|
||||
const ts = status.trancheStatus[i]
|
||||
let filledIn = 0n
|
||||
let filledOut = 0n
|
||||
const [activationTime, fills] = filled[i];
|
||||
const numOld = ts.fills.length;
|
||||
for (let i=0; i<fills.length; i++) {
|
||||
const fill = fills[i]
|
||||
let [tx, time, fi, fo, fee] = fill
|
||||
fi = BigInt(fi)
|
||||
fo = BigInt(fo)
|
||||
fee = BigInt(fee)
|
||||
filledIn += fi
|
||||
filledOut += fo
|
||||
if (i>=numOld) {
|
||||
// new fill detected
|
||||
const f = {tx, time, filledIn: fi, filledOut: fo, fee, filled: status.order.amountIsInput ? fi : fo};
|
||||
console.log('new fill', f)
|
||||
notifyFillEvent(chainId, status, i, f).catch((e)=>console.log('fill notification error', e))
|
||||
ts.fills.push(f)
|
||||
}
|
||||
}
|
||||
ts.filledIn = filledIn
|
||||
ts.filledOut = filledOut
|
||||
ts.activationTime = activationTime
|
||||
orderIn += filledIn
|
||||
orderOut += filledOut
|
||||
}
|
||||
status.filledIn = orderIn
|
||||
status.filledOut = orderOut
|
||||
status.filled = status.order.amountIsInput ? orderIn : orderOut
|
||||
|
||||
console.log('apply fills completed', status)
|
||||
})
|
||||
@@ -224,4 +224,3 @@ export const usePrefStore = defineStore({
|
||||
return {inverted, acceptedTos, selectedTicker, selectedTimeframe, timezone, newbie, hints, }
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user