vault upgrades; fees; refactoring

This commit is contained in:
Tim
2024-06-17 02:39:12 -04:00
parent fd8f20c4d4
commit 104b798d4f
15 changed files with 260 additions and 86 deletions

View File

@@ -16,9 +16,6 @@
<div id="app"></div> <div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.4/socket.io.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.4/socket.io.js"></script>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
<!-- HubSpot -->
<script type="text/javascript" id="hs-script-loader" async defer src="//js-na1.hs-scripts.com/46028804.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,6 +1,8 @@
<template> <template>
<router-view/> <router-view/>
<HubSpot/>
</template> </template>
<script setup> <script setup>
import HubSpot from "@/components/HubSpot.vue";
</script> </script>

View File

@@ -1,5 +1,14 @@
export const factoryAbi = [ export const factoryAbi = [
'function deployVault() returns (address payable vault)',
'function deployVault(uint8 num) returns (address payable vault)',
'function deployVault(address owner) returns (address payable vault)',
'function deployVault(address owner, uint8 num) returns (address payable vault)',
'function logic() view returns (address)',
'function upgrader() view returns (address)',
'function proposedLogicActivationTimestamp() view returns (uint32)',
'function proposedLogic() view returns (address)',
'function upgradeLogic(address newLogic)',
] ]
export const queryHelperAbi = [ export const queryHelperAbi = [
@@ -55,11 +64,11 @@ const Tranche = `(
bool minIsBarrier, bool minIsBarrier,
bool maxIsBarrier, bool maxIsBarrier,
bool marketOrder, bool marketOrder,
bool _reserved5, bool minIsRatio,
bool _reserved6, bool maxIsRatio,
bool _reserved7, bool _reserved7,
uint8 _reserved8, uint16 rateLimitFraction,
uint32 _reserved16, uint24 rateLimitPeriod,
uint32 startTime, uint32 startTime,
uint32 endTime, uint32 endTime,
uint32 minIntercept, uint32 minIntercept,
@@ -67,6 +76,7 @@ const Tranche = `(
uint32 maxIntercept, uint32 maxIntercept,
uint32 maxSlope uint32 maxSlope
)` )`
const SwapOrder = `( const SwapOrder = `(
address tokenIn, address tokenIn,
address tokenOut, address tokenOut,
@@ -75,19 +85,23 @@ const SwapOrder = `(
uint256 minFillAmount, uint256 minFillAmount,
bool amountIsInput, bool amountIsInput,
bool outputDirectlyToOwner, bool outputDirectlyToOwner,
uint64 chainOrder, uint64 conditionalOrder,
${Tranche}[] tranches ${Tranche}[] tranches
)` )`
export const vaultAbi = [ export const vaultAbi = [
'function version() view returns (uint8)', 'function version() pure returns (uint8)',
'function logic() view returns (address)',
'function upgrade(address)',
'function feeManager() view returns (address)',
'function withdraw(uint256 amount)', 'function withdraw(uint256 amount)',
'function withdrawTo(address payable recipient, uint256 amount)', 'function withdrawTo(address payable recipient, uint256 amount)',
'function withdraw(address token, uint256 amount)', 'function withdraw(address token, uint256 amount)',
'function withdrawTo(address token, address recipient, uint256 amount)', 'function withdrawTo(address token, address recipient, uint256 amount)',
'function numSwapOrders() view returns (uint64 num)', 'function numSwapOrders() view returns (uint64 num)',
`function placeDexorder(${SwapOrder})`, `function placementFee(${SwapOrder} order) view returns (uint256 orderFee, uint256 gasFee)`,
`function placeDexorders(${SwapOrder}[], uint8 ocoMode)`, `function placeDexorder(${SwapOrder}) payable`,
`function placeDexorders(${SwapOrder}[], uint8 ocoMode) payable`,
'function cancelDexorder(uint64 orderIndex)', 'function cancelDexorder(uint64 orderIndex)',
'function cancelAllDexorders()', 'function cancelAllDexorders()',
// `function swapOrderStatus(uint64 orderIndex) view returns (${SwapOrderStatus} memory status)`, // `function swapOrderStatus(uint64 orderIndex) view returns (${SwapOrderStatus} memory status)`,

View File

@@ -2,7 +2,7 @@ import {uint32max, uint64max} from "@/misc.js";
import {decodeIEE754, encodeIEE754} from "@/common.js"; import {decodeIEE754, encodeIEE754} from "@/common.js";
export const MAX_FRACTION = 65535; export const MAX_FRACTION = 65535;
export const NO_CHAIN = uint64max; export const NO_CONDITIONAL_ORDER = uint64max;
export const NO_OCO = uint64max; export const NO_OCO = uint64max;
export const DISTANT_PAST = 0 export const DISTANT_PAST = 0
export const DISTANT_FUTURE = uint32max export const DISTANT_FUTURE = uint32max
@@ -15,7 +15,7 @@ export const DISTANT_FUTURE = uint32max
// uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed // uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed
// bool amountIsInput; // bool amountIsInput;
// bool outputDirectlyToOwner; // bool outputDirectlyToOwner;
// uint64 chainOrder; // use NO_CHAIN for no chaining. chainOrder index must be < than this order's index for safety (written first) and chainOrder state must be Template // uint64 conditionalOrder; // use NO_CONDITIONAL_ORDER for no chaining. conditionalOrder index must be < than this order's index for safety (written first) and conditionalOrder state must be Template
// Tranche[] tranches; // Tranche[] tranches;
// } // }
// struct Route { // struct Route {
@@ -23,7 +23,7 @@ export const DISTANT_FUTURE = uint32max
// uint24 fee; // uint24 fee;
// } // }
export function newOrder(tokenIn, tokenOut, exchange, fee, amount, amountIsInput, tranches, export function newOrder(tokenIn, tokenOut, exchange, fee, amount, amountIsInput, tranches,
minFillAmount=null, outputDirectlyToOwner = false, chainOrder = NO_CHAIN) { minFillAmount=null, outputDirectlyToOwner = false, conditionalOrder = NO_CONDITIONAL_ORDER) {
amountIsInput = !!amountIsInput // force convert to bool amountIsInput = !!amountIsInput // force convert to bool
outputDirectlyToOwner = !!outputDirectlyToOwner // force convert to bool outputDirectlyToOwner = !!outputDirectlyToOwner // force convert to bool
amount = BigInt(amount) amount = BigInt(amount)
@@ -34,7 +34,7 @@ export function newOrder(tokenIn, tokenOut, exchange, fee, amount, amountIsInput
return { return {
tokenIn, tokenOut, route:{exchange, fee}, tokenIn, tokenOut, route:{exchange, fee},
amount, minFillAmount, amountIsInput, amount, minFillAmount, amountIsInput,
outputDirectlyToOwner, chainOrder, tranches outputDirectlyToOwner, conditionalOrder, tranches
} }
} }
@@ -46,11 +46,11 @@ export function newOrder(tokenIn, tokenOut, exchange, fee, amount, amountIsInput
// bool minIsBarrier; // bool minIsBarrier;
// bool maxIsBarrier; // bool maxIsBarrier;
// bool marketOrder; // if true, both min and max lines are ignored, and minIntercept is treated as a maximum slippage value (use positive numbers) // bool marketOrder; // if true, both min and max lines are ignored, and minIntercept is treated as a maximum slippage value (use positive numbers)
// bool _reserved5; // bool minIsRatio;
// bool _reserved6; // bool maxIsRatio;
// bool _reserved7; // bool _reserved7;
// uint8 _reserved8; // uint16 rateLimitFraction;
// uint32 _reserved16; // uint24 rateLimitPeriod;
// //
// uint32 startTime; // use DISTANT_PAST to disable // uint32 startTime; // use DISTANT_PAST to disable
// uint32 endTime; // use DISTANT_FUTURE to disable // uint32 endTime; // use DISTANT_FUTURE to disable
@@ -69,12 +69,16 @@ export function newTranche({
endTimeIsRelative = false, endTimeIsRelative = false,
endTime = DISTANT_FUTURE, endTime = DISTANT_FUTURE,
minIsBarrier = false, minIsBarrier = false,
minIsRatio = false,
minIntercept = 0, minIntercept = 0,
slippage = 0, // may also set minIntercept instead slippage = 0, // may also set minIntercept instead
minSlope = 0, minSlope = 0,
maxIsBarrier = false, maxIsBarrier = false,
maxIsRatio = false,
maxIntercept = 0, maxIntercept = 0,
maxSlope = 0, maxSlope = 0,
rateLimitFraction = 0,
rateLimitPeriod = 0,
} = {}) { } = {}) {
if( minIntercept === 0 && minSlope === 0 && maxIntercept === 0 && maxSlope === 0 ) if( minIntercept === 0 && minSlope === 0 && maxIntercept === 0 && maxSlope === 0 )
marketOrder = true marketOrder = true
@@ -90,7 +94,7 @@ export function newTranche({
fraction: Math.min(MAX_FRACTION, Math.round(fraction)), marketOrder, fraction: Math.min(MAX_FRACTION, Math.round(fraction)), marketOrder,
startTimeIsRelative, startTime, endTimeIsRelative, endTime, startTimeIsRelative, startTime, endTimeIsRelative, endTime,
minIsBarrier, minIntercept, minSlope, maxIsBarrier, maxIntercept, maxSlope, minIsBarrier, minIntercept, minSlope, maxIsBarrier, maxIntercept, maxSlope,
_reserved5: false, _reserved6: false, _reserved7: false, _reserved8: 0, _reserved16: 0, minIsRatio, maxIsRatio, _reserved7: false, rateLimitFraction, rateLimitPeriod,
} }
} }
@@ -110,10 +114,6 @@ export const OrderState = {
Error: 99, Error: 99,
} }
export function orderIsOpen(order) {
return isOpen(order.state)
}
export function isOpen(state) { export function isOpen(state) {
return state >= 1 && state < 3 return state >= 1 && state < 3
} }
@@ -121,7 +121,7 @@ export function isOpen(state) {
export function parseOrderStatus(chainId, status) { export function parseOrderStatus(chainId, status) {
let [ let [
order, order,
fillFeeBP, fillFeeHalfBps,
state, state,
start, start,
ocoGroup, ocoGroup,
@@ -129,14 +129,17 @@ export function parseOrderStatus(chainId, status) {
filledOut, filledOut,
trancheFilledIn, trancheFilledIn,
trancheFilledOut, trancheFilledOut,
trancheActivationTime,
] = status ] = status
order = parseOrder(order) order = parseOrder(order)
filledIn = BigInt(filledIn) filledIn = BigInt(filledIn)
filledOut = BigInt(filledOut) filledOut = BigInt(filledOut)
trancheFilledIn = trancheFilledIn.map((f)=>BigInt(f)) trancheFilledIn = trancheFilledIn.map((f)=>BigInt(f))
trancheFilledOut = trancheFilledOut.map((f)=>BigInt(f)) trancheFilledOut = trancheFilledOut.map((f)=>BigInt(f))
trancheActivationTime = trancheActivationTime.map((v)=>Number(v))
return { return {
chainId, order, fillFeeBP, state, start, ocoGroup, filledIn, filledOut, trancheFilledIn, trancheFilledOut, chainId, order, fillFeeHalfBps, state, start, ocoGroup,
filledIn, filledOut, trancheFilledIn, trancheFilledOut, trancheActivationTime
} }
} }
@@ -150,7 +153,7 @@ export function parseOrder(order) {
minFillAmount, minFillAmount,
amountIsInput, amountIsInput,
outputDirectlyToOwner, outputDirectlyToOwner,
chainOrder, conditionalOrder,
tranches, tranches,
] = order ] = order
route = parseRoute(route) route = parseRoute(route)
@@ -158,7 +161,7 @@ export function parseOrder(order) {
minFillAmount = BigInt(minFillAmount) minFillAmount = BigInt(minFillAmount)
tranches = tranches.map(parseTranche) tranches = tranches.map(parseTranche)
return { return {
tokenIn, tokenOut, route, amount, minFillAmount, amountIsInput, outputDirectlyToOwner, chainOrder, tranches tokenIn, tokenOut, route, amount, minFillAmount, amountIsInput, outputDirectlyToOwner, conditionalOrder, tranches
} }
} }
@@ -175,11 +178,11 @@ export function parseTranche(tranche) {
minIsBarrier, minIsBarrier,
maxIsBarrier, maxIsBarrier,
marketOrder, marketOrder,
_reserved5, minIsRatio,
_reserved6, maxIsRatio,
_reserved7, _reserved7,
_reserved8, rateLimitFraction,
_reserved16, rateLimitPeriod,
startTime, startTime,
endTime, endTime,
minIntercept, minIntercept,
@@ -193,6 +196,7 @@ export function parseTranche(tranche) {
maxSlope = decodeIEE754(maxSlope) maxSlope = decodeIEE754(maxSlope)
return { return {
fraction, startTimeIsRelative, endTimeIsRelative, minIsBarrier, maxIsBarrier, marketOrder, fraction, startTimeIsRelative, endTimeIsRelative, minIsBarrier, maxIsBarrier, marketOrder,
minIsRatio, maxIsRatio, rateLimitFraction, rateLimitPeriod,
startTime, endTime, minIntercept, minSlope, maxIntercept, maxSlope, startTime, endTime, minIntercept, minSlope, maxIntercept, maxSlope,
} }
} }

View File

@@ -3,10 +3,10 @@ import {useStore} from "@/store/store";
import {socket} from "@/socket.js"; import {socket} from "@/socket.js";
import {contractOrNull, vaultAddress} from "@/blockchain/contract.js"; import {contractOrNull, vaultAddress} from "@/blockchain/contract.js";
import {SingletonCoroutine, uuid} from "@/misc.js"; import {SingletonCoroutine, uuid} from "@/misc.js";
import {vaultAbi} from "@/blockchain/abi.js"; import {factoryAbi, vaultAbi} from "@/blockchain/abi.js";
import {defineStore} from "pinia"; import {defineStore} from "pinia";
import {ref} from "vue"; import {ref} from "vue";
import {metadataMap} from "@/version.js"; import {metadataMap, version} from "@/version.js";
export let provider = null export let provider = null
@@ -198,6 +198,7 @@ function discoverVaults(owner) {
const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50, false) const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50, false)
async function _discoverVaults(owner) { async function _discoverVaults(owner) {
const result = [] const result = []
const versions = []
const s = useStore() const s = useStore()
if( !owner || !s.chainId || !s.account) { if( !owner || !s.chainId || !s.account) {
s.vaults = [] s.vaults = []
@@ -205,38 +206,34 @@ async function _discoverVaults(owner) {
} }
// todo multi-vault scan // todo multi-vault scan
// console.log('_discoverVaults',owner) // console.log('_discoverVaults',owner)
for (let num=0; num < 1; num++) {
const num = 0 const num = 0
const addr = vaultAddress(s.factory, s.vaultInitCodeHash, owner, num) const addr = vaultAddress(s.factory, s.vaultInitCodeHash, owner, num)
// console.log(`vault ${num} at`, addr) // console.log(`vault ${num} at`, addr)
if( addr === null ) { if (addr === null) // no more vaults
s.vaults = [] break
return
}
console.log('provider', provider) console.log('provider', provider)
if (!provider) { if (!provider) {
console.log('No provider') console.log('No provider')
return // do not change whatever was already found return // do not change whatever was already found
} }
const vault = new ethers.Contract(addr, vaultAbi, provider) const vault = new ethers.Contract(addr, vaultAbi, provider)
let version = -1
try { try {
version = await vault.version(); const version = Number(await vault.version())
if( Number(version) === 1 ) { console.log(`found vault #${num} v${version} at ${addr}`)
console.log(`found vault ${num} at ${addr}`)
result.push(addr) result.push(addr)
} versions.push(version)
else } catch (e) {
console.error(`bad vault version ${version}`)
}
catch (e) {
if (e.value === '0x' && e.code === 'BAD_DATA' || e.revert === null && e.code === 'CALL_EXCEPTION') if (e.value === '0x' && e.code === 'BAD_DATA' || e.revert === null && e.code === 'CALL_EXCEPTION')
console.log(`no vault ${num} at ${addr}`) console.log(`no vault ${num} at ${addr}`)
else else
console.error(`discoverVaults failed`, e) console.error(`discoverVaults failed`, e)
return // do not change what was already found todo is this correct? return // do not change what was already found todo is this correct?
} }
}
if( s.account === owner ) { // double-check the account since it could have changed during our await if( s.account === owner ) { // double-check the account since it could have changed during our await
s.vaults = result s.vaults = result
s.vaultVersions = versions
if( useWalletStore().pendingOrders.length ) { if( useWalletStore().pendingOrders.length ) {
if (result.length) if (result.length)
flushOrders(result[0]) flushOrders(result[0])
@@ -287,7 +284,6 @@ async function doEnsureVault(chainId, owner, num) {
socket.emit('ensureVault', chainId, owner, num) socket.emit('ensureVault', chainId, owner, num)
} }
} }
// await sleep(5000) // prevent this process from running more than once every 5 seconds
const ensureVaultRoutine = new SingletonCoroutine(doEnsureVault, 100) const ensureVaultRoutine = new SingletonCoroutine(doEnsureVault, 100)
@@ -300,18 +296,27 @@ export const PendingOrderState = {
} }
export async function pendOrder(order) { export async function placementFee(vault, order) {
const v = new ethers.Contract(vault, vaultAbi, provider)
const [orderFee, gasFee] = await v.placementFee(order)
console.log('computed fees', orderFee, gasFee)
return [orderFee, gasFee]
}
export async function pendOrder(order, fee=null) {
const s = useStore() const s = useStore()
const pend = { const pend = {
id: uuid(), id: uuid(),
chainId: s.chainId, chainId: s.chainId,
placementTime: Date.now()/1000, placementTime: Date.now()/1000,
fee: fee,
vault: s.vaults.length ? s.vaults[0] : null, vault: s.vaults.length ? s.vaults[0] : null,
state: PendingOrderState.Submitted, state: PendingOrderState.Submitted,
order order
}; };
useWalletStore().pendingOrders.splice(0,0, pend) useWalletStore().pendingOrders.splice(0,0, pend)
console.log('pending order', pend.id, JSON.stringify(order)) console.log('pended order', pend.id, JSON.stringify(order))
ensureVault() ensureVault()
} }
@@ -378,8 +383,12 @@ function pendOrderAsTransaction(pend) {
return null return null
} }
} }
if (pend.fee === null) {
const [orderFee, gasFee] = await placementFee(pend.vault, pend.order)
pend.fee = orderFee + gasFee
}
console.log('placing order', pend.id, pend.order) console.log('placing order', pend.id, pend.order)
const tx = await contract.placeDexorder(pend.order) const tx = await contract.placeDexorder(pend.order, {value:pend.fee})
pend.tx = tx pend.tx = tx
pend.state = PendingOrderState.Sent pend.state = PendingOrderState.Sent
console.log(`order ${pend.id} sent transaction`, tx) console.log(`order ${pend.id} sent transaction`, tx)
@@ -400,7 +409,7 @@ function pendOrderAsTransaction(pend) {
}) })
} }
0
export function pendTransaction(sender, errHandler) { export function pendTransaction(sender, errHandler) {
const s = useStore() const s = useStore()
s.transactionSenders.push([sender,errHandler]) s.transactionSenders.push([sender,errHandler])
@@ -462,3 +471,60 @@ function doSendTransaction(sender, signer, errHandler) {
} }
}) })
} }
export async function detectUpgrade() {
if (!provider) {
console.log('no provider!')
return 0
}
const s = useStore()
if (!s.vault) {
console.log('no vault logged in')
return 0
}
const info = version.chainInfo[s.chainId]
if (!info) {
console.log(`couldn't get chainInfo for ${s.chainId}`)
return 0
}
try {
console.log('factory', info.factory)
const factory = new ethers.Contract(info.factory, factoryAbi, provider)
const vault = new ethers.Contract(s.vault, vaultAbi, provider)
const vaultLogic = await vault.logic()
const latestLogic = await factory.logic()
// const [vaultLogic, latestLogic] = await Promise.all( vault.logic(), factory.logic() )
console.log('vaultLogic / latestLogic', vaultLogic, latestLogic)
if ( vaultLogic !== latestLogic ) {
s.upgrade = latestLogic
const logic = new ethers.Contract(latestLogic, vaultAbi, provider)
const version = await logic.version()
console.log(`found vault version ${version}`)
return version
}
}
catch (e) {
console.error('ignorable error while querying for an upgrade', e)
}
return 0
}
function upgradeSender(vault, logic) {
return async function (signer) {
const v = new ethers.Contract(vault, vaultAbi, signer)
v.upgrade(logic)
}
}
function upgradeError(e) {
console.error('error while upgrading vault', e)
}
export async function upgradeVault(vault, logic) {
pendTransaction(upgradeSender(vault, logic), upgradeError)
}

View File

@@ -359,7 +359,7 @@ function doHandleDrawingEvent(id, event) {
if (id in shapeCallbacks) { if (id in shapeCallbacks) {
invokeCallbacks(shapeCallbacks[id], 'onHide', id, shape) invokeCallbacks(shapeCallbacks[id], 'onHide', id, shape)
} }
} else if (event === 'show') { } else if (event === 'showDialog') {
if (id in shapeCallbacks) { if (id in shapeCallbacks) {
invokeCallbacks(shapeCallbacks[id], 'onShow', id, shape) invokeCallbacks(shapeCallbacks[id], 'onShow', id, shape)
} }

View File

@@ -0,0 +1,17 @@
<template>
</template>
<script setup>
const importUrl = 'https://js-na1.hs-scripts.com/46028804.js'
const viteWsUrl = import.meta.env.VITE_WS_URL;
if (viteWsUrl.indexOf('localhost') === -1) {
console.log('loading HubSpot')
let script = document.createElement('script')
script.setAttribute('src', importUrl)
document.head.appendChild(script)
}
</script>

View File

@@ -43,7 +43,7 @@ function placeOrder() {
const route = os.route const route = os.route
const amt = FixedNumber.fromString(os.totalAmount.toString(), {decimals: os.amountToken.decimals}).value const amt = FixedNumber.fromString(os.totalAmount.toString(), {decimals: os.amountToken.decimals}).value
const ts = props.tranches() const ts = props.tranches()
const order = newOrder(tokenIn, tokenOut, route.exchange, route.fee, amt, os.amountIsInput, ts) // todo: minAmount, outputToOwner, chainOrder const order = newOrder(tokenIn, tokenOut, route.exchange, route.fee, amt, os.amountIsInput, ts) // todo: minAmount, outputToOwner, conditionalOrder
pendOrder(order) pendOrder(order)
route('Status') route('Status')
} }

View File

@@ -115,6 +115,7 @@
</suspense> </suspense>
</td> </td>
<td class="d-flex align-center text-left"> <td class="d-flex align-center text-left">
<!-- todo describe rate limits -->
<div class="text-right"> <div class="text-right">
<div class="mx-3">{{ describeTrancheTime(item, true, t) }}</div> <div class="mx-3">{{ describeTrancheTime(item, true, t) }}</div>
<div class="mx-3">{{ describeTrancheTime(item, false, t) }}</div> <div class="mx-3">{{ describeTrancheTime(item, false, t) }}</div>
@@ -160,7 +161,6 @@ const s = useStore()
const ws = useWalletStore() const ws = useWalletStore()
const props = defineProps(['vault']) const props = defineProps(['vault'])
const vaultAddr = computed(()=>props.vault?props.vault:s.vault) const vaultAddr = computed(()=>props.vault?props.vault:s.vault)
const inverted = ref({})
const datatableHeaders = [ const datatableHeaders = [
@@ -191,11 +191,11 @@ const orders = computed(()=>{
// false, min is barrier // false, min is barrier
// false, max is barrier // false, max is barrier
// false, market order // false, market order
// false, reserved // 0, minIsRatio
// false, reserved // 0, maxIsRatio
// false, reserved // false, _reserved7
// 0, reserved // 0, rateLimitFraction
// 0, reserved // 0, rateLimitPeriod
// 0, start time // 0, start time
// 20, end time // 20, end time
// 730643660, min intercept // 730643660, min intercept

View File

@@ -0,0 +1,72 @@
<template>
<div v-if="upgradeVersion>0">
<v-alert type="info" closable rounded="0">
Vault Upgrade Available!
<v-btn @click="showDialog=true" size="small">
Upgrade Now
</v-btn>
</v-alert>
<v-dialog v-model="showDialog">
<v-card title="Upgrade Vault" width="25em" class="mx-auto">
<v-card-text>An upgrade to version {{upgradeVersion}} is available for your approval.</v-card-text>
<v-card-text><v-icon icon="mdi-information" color="yellow"/> Any currently open orders will continue to execute normally.</v-card-text>
<v-card-actions class="d-flex justify-center">
<v-btn color='primary' @click="doUpgrade">Upgrade Vault</v-btn>
<v-btn @click="showDialog=false">Cancel</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-alert v-if="upgradeResult==='SUCCESS'" type="info" closable rounded="0">
Vault Upgraded Successfully!
</v-alert>
<v-alert v-if="upgradeResult && upgradeResult!=='SUCCESS'" type="warning" closable rounded="0">
Vault upgrade failed! ({{upgradeResult}})
</v-alert>
</div>
</template>
<script setup>
import {ref} from "vue";
import {upgradeVault, detectUpgrade} from "@/blockchain/wallet.js";
import {useStore} from "@/store/store.js";
const s = useStore()
const upgradeVersion = ref(0)
const showDialog = ref(false)
const upgradeResult = ref(null)
detectUpgrade().then((version)=>{
if (version===0) {
console.log('Vault is the latest version')
}
else {
upgradeVersion.value = version
console.log(`Vault upgrade available to version ${version}`)
}
})
async function doUpgrade() {
showDialog.value = false
if (!s.upgrade) {
console.error('no upgrade available')
return
}
const vault = s.vault
if (!vault) {
console.error('no vault logged in')
return
}
upgradeVault(vault, s.upgrade).then(()=>{
upgradeVersion.value = 0
console.log('vault upgraded')
upgradeResult.value = 'SUCCESS'
}).catch((reason)=>{
upgradeResult.value = reason
})
}
</script>
<style scoped lang="scss">
</style>

View File

@@ -108,7 +108,7 @@ function buildOrder() {
// uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed // uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed
// bool amountIsInput; // bool amountIsInput;
// bool outputDirectlyToOwner; // bool outputDirectlyToOwner;
// uint64 chainOrder; // use NO_CHAIN for no chaining. chainOrder index must be < than this order's index for safety (written first) and chainOrder state must be Template // uint64 conditionalOrder; // use NO_CONDITIONAL_ORDER for no chaining. conditionalOrder index must be < than this order's index for safety (written first) and conditionalOrder state must be Template
// Tranche[] tranches; // Tranche[] tranches;
// } // }
const symbol = co.selectedSymbol const symbol = co.selectedSymbol

View File

@@ -303,9 +303,7 @@ const _extendLeft = ref(false)
const extendLeft = computed({ const extendLeft = computed({
get() {return _extendLeft.value}, get() {return _extendLeft.value},
set(v) { set(v) {
console.log('set extendLeft', v)
if (v !== _extendLeft.value) { if (v !== _extendLeft.value) {
console.log('DO set extendLeft')
_extendLeft.value = v; _extendLeft.value = v;
const b = {...props.builder} const b = {...props.builder}
b.extendLeft = v b.extendLeft = v

View File

@@ -3,6 +3,7 @@
<toolbar :title="title" :icon="icon"> <toolbar :title="title" :icon="icon">
<slot name="toolbar"/> <slot name="toolbar"/>
</toolbar> </toolbar>
<upgrade-alert/>
<div class="overflow-y-auto"> <div class="overflow-y-auto">
<slot/> <slot/>
</div> </div>
@@ -12,6 +13,7 @@
<script setup> <script setup>
import Toolbar from "@/components/chart/Toolbar.vue"; import Toolbar from "@/components/chart/Toolbar.vue";
import UpgradeAlert from "@/components/UpgradeAlert.vue";
const props = defineProps(['title', 'icon']) const props = defineProps(['title', 'icon'])

View File

@@ -1,7 +1,5 @@
<template> <template>
<v-main> <v-main>
<v-alert text="TESTNET FAKE COINS&nbsp;&nbsp;&nbsp;&nbsp;• UNI • ARB • WETH • WBTC • LINK • USDC •"
color="red" :closable="false" rounded="0" height="0"/>
<Alerts/> <Alerts/>
<chart-view/> <chart-view/>
</v-main> </v-main>

View File

@@ -2,7 +2,7 @@
import {defineStore} from 'pinia' import {defineStore} from 'pinia'
import {knownTokens} from "@/knownTokens.js"; import {knownTokens} from "@/knownTokens.js";
import {computed, ref} from "vue"; import {computed, ref} from "vue";
import {version} from "@/version.js"; import {version as versionMeta} from "@/version.js";
// USING THE STORE: // USING THE STORE:
// //
@@ -42,8 +42,8 @@ export const useStore = defineStore('app', ()=> {
const nav = ref(false) // controls opening navigation drawer const nav = ref(false) // controls opening navigation drawer
const _chainId = ref(Number(Object.keys(version.chainInfo)[0])) const _chainId = ref(Number(Object.keys(versionMeta.chainInfo)[0]))
const _chainInfo = ref(version.chainInfo) const _chainInfo = ref(versionMeta.chainInfo)
function getTokenList() { function getTokenList() {
const chains = _chainId.value in _chainInfo.value && _chainInfo.value[_chainId.value].tokens !== undefined ? const chains = _chainId.value in _chainInfo.value && _chainInfo.value[_chainId.value].tokens !== undefined ?
@@ -88,6 +88,7 @@ export const useStore = defineStore('app', ()=> {
const vaultInitCodeHash = computed(() => !chain.value ? null : chain.value.vaultInitCodeHash) const vaultInitCodeHash = computed(() => !chain.value ? null : chain.value.vaultInitCodeHash)
const account = ref(null) const account = ref(null)
const vaults = ref([]) const vaults = ref([])
const vaultVersions = ref([])
const transactionSenders = ref([]) // a list of function(signer) that send transactions const transactionSenders = ref([]) // a list of function(signer) that send transactions
const errors = ref([]) const errors = ref([])
const extraTokens = ref({}) const extraTokens = ref({})
@@ -96,6 +97,8 @@ export const useStore = defineStore('app', ()=> {
const orders = ref({}) // indexed by vault value is another dictionary with orderIndex as key and order status values const orders = ref({}) // indexed by vault value is another dictionary with orderIndex as key and order status values
const vault = computed(() => vaults.value.length === 0 ? null : vaults.value[0] ) const vault = computed(() => vaults.value.length === 0 ? null : vaults.value[0] )
const upgrade = ref(null)
const version = computed( () => vaultVersions.value.length === 0 ? 0 : vaultVersions.value[0] )
const balances = computed( () => vault.value === null ? {} : vaultBalances.value[vault.value] || {} ) const balances = computed( () => vault.value === null ? {} : vaultBalances.value[vault.value] || {} )
const vaultOrders = computed(()=> vault.value === null || (!vault.value in orders.value) ? {} : orders.value[vault.value] ? orders.value[vault.value] : [] ) const vaultOrders = computed(()=> vault.value === null || (!vault.value in orders.value) ? {} : orders.value[vault.value] ? orders.value[vault.value] : [] )
const tokens = computed(getTokens) const tokens = computed(getTokens)
@@ -126,8 +129,9 @@ export const useStore = defineStore('app', ()=> {
} }
return { return {
nav, chainId, chainInfo, chain, provider, providerRef, vaultInitCodeHash, account, vaults, transactionSenders, nav, chainId, chainInfo, chain, provider, providerRef, vaultInitCodeHash, account, vaults, vaultVersions,
errors, extraTokens, poolPrices, vaultBalances, orders, vault, vaultOrders, tokens, factory, helper, transactionSenders, errors, extraTokens, poolPrices, vaultBalances, orders, vault, version, upgrade, vaultOrders,
tokens, factory, helper,
mockenv, mockCoins, mockenv, mockCoins,
removeTransactionSender, error, closeError, addToken, clock, timeZone, balances, removeTransactionSender, error, closeError, addToken, clock, timeZone, balances,
} }