transaction progressor

This commit is contained in:
tim
2025-03-28 20:05:31 -04:00
parent 7626504480
commit a6bce1613b
10 changed files with 130 additions and 25 deletions

View File

@@ -37,10 +37,15 @@ export class Transaction {
}
submit() {
useWalletStore().transaction = this
ensureVault()
const ws = useWalletStore();
if ( ws.transaction !== null ) {
console.error('Transaction already in progress', ws.transaction)
return
}
ws.transaction = this
}
// "propose" means attach the transaction to a specific vault
propose(owner, vault) {
if (this.vault !== null && this.vault !== vault) {
this.failed('proposed vault did not match withdrawl vault', vault, this.vault)
@@ -131,13 +136,13 @@ export class Transaction {
try {
const tx = toRaw(await this.createTx(contract))
this.signed(tx)
tx.wait().then(this.mined.bind(this)).catch(this.failed.bind(this))
console.log(`sent transaction`, tx)
}
catch (e) {
this.failed(e)
return null
}
tx.wait().then(this.mined.bind(this)).catch(this.failed.bind(this))
return this.tx
}
@@ -165,19 +170,21 @@ export class PlaceOrderTransaction extends Transaction {
async createTx(vaultContract) {
const tries = 3;
const tries = 65;
let i;
for (i=0; i<tries; i++ ) {
let success = false
for (i=0; !success && i<tries; i++ ) {
try {
console.error('getting placement fee', vaultContract, this.order)
this.fee = await placementFee(vaultContract, this.order)
break
success = true
}
catch (e) {
console.warn('failed to get placement fee', e)
await sleep(1000)
}
}
if (i===tries)
if (!success)
throw Error('failed to get placement fee')
console.log('placing order', this.id, this.fee, this.order)
return await vaultContract.placeDexorder(this.order, {value: this.fee.reduce((a, b) => a + b)})

View File

@@ -1,18 +1,17 @@
import {BrowserProvider, ethers} from "ethers";
import {useStore} from "@/store/store";
import {socket} from "@/socket.js";
import {SingletonCoroutine} from "@/misc.js";
import {errorSuggestsMissingVault, SingletonCoroutine} from "@/misc.js";
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
import {defineStore} from "pinia";
import {ref} from "vue";
import {computed, ref} from "vue";
import {metadataMap, version} from "@/version.js";
import {CancelAllTransaction, TransactionState} from "@/blockchain/transaction.js";
import {CancelAllTransaction, TransactionState, TransactionType} 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)
@@ -29,7 +28,24 @@ export const useWalletStore = defineStore('wallet', ()=>{
const pendingOrders = ref([])
// NEW Format is a single Transaction class
const transaction = ref(null)
const _tx = ref(null)
const transaction = computed({
get() {return _tx.value},
set(v) {
_tx.value = v;
if (v===null) {
if (progressionInvoker!==null) {
clearTimeout(progressionInvoker)
progressionInvoker = null
}
}
else {
transactionProgressor.invoke();
if (progressionInvoker===null)
progressionInvoker = setInterval(()=>transactionProgressor.invoke(), 1000)
}
},
})
return {
chainId, pendingOrders, transaction,
@@ -183,6 +199,7 @@ function discoverVaults(owner) {
}
const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50)
async function _discoverVaults(owner) {
const result = []
const versions = []
@@ -199,7 +216,6 @@ async function _discoverVaults(owner) {
// console.log(`vault ${num} at`, addr)
if (addr === null) // no more vaults
break
console.log('provider', provider)
if (!provider) {
console.log('No provider')
return // do not change whatever was already found
@@ -211,7 +227,7 @@ async function _discoverVaults(owner) {
result.push(addr)
versions.push(version)
} catch (e) {
if (e.value === '0x' && e.code === 'BAD_DATA' || e.revert === null && e.code === 'CALL_EXCEPTION')
if (errorSuggestsMissingVault(e))
console.log(`no vault ${num} at ${addr}`)
else
console.error(`discoverVaults failed`, e)
@@ -293,10 +309,51 @@ export async function cancelAll(vault) {
new CancelAllTransaction(useStore().chainId, vault).submit()
}
async function progressTransactions() {
const s = useStore()
const ws = useWalletStore();
if( ws.transaction===null )
return
if( s.account === null ) {
let signer = null
try {
signer = await provider.getSigner()
}
catch (e) {
console.log('signer error', e.code, e.info.error.code)
if (e?.info?.error?.code === 4001) {
console.log('signer rejected')
signer = null
}
else
throw e
}
if (signer === null) {
console.log('setting tx state to rejected')
ws.transaction.state = TransactionState.Rejected
ws.transaction = null
return
}
}
if( s.vault === null ) {
ensureVault()
return
}
if( ws.transaction.type === TransactionType.PlaceOrder ) {
flushOrders(s.chainId, s.account, 0, s.vault)
}
}
const transactionProgressor = new SingletonCoroutine(progressTransactions, 10)
let progressionInvoker = null
export function flushOrders(chainId, owner, num, vault) {
const ws = useWalletStore();
console.log('flushOrders', ws.transaction)
if (ws.transaction!==null && ws.transaction.state < TransactionState.Proposed)
console.log('flushOrders', chainId, owner, num, vault)
if (ws.transaction!==null && ws.transaction.type === TransactionType.PlaceOrder && ws.transaction.state < TransactionState.Proposed)
ws.transaction.propose(owner, vault)
let needsFlush = false
for( const pend of ws.pendingOrders ) {