wallet flow; new faucet; placing chart orders works!
This commit is contained in:
@@ -36,7 +36,7 @@ async function componentFindRoute() {
|
||||
os.routes = []
|
||||
if (!tokenA || !tokenB)
|
||||
return
|
||||
console.log('finding route', s.chainId.value, tokenA, tokenB)
|
||||
console.log('finding route', s.chainId, tokenA, tokenB)
|
||||
os.routesPending = true
|
||||
try {
|
||||
console.log('getting query helper')
|
||||
@@ -44,7 +44,7 @@ async function componentFindRoute() {
|
||||
if (!helper) {
|
||||
console.log('no helper')
|
||||
} else {
|
||||
const result = await findRoute(helper, s.chainId.value, tokenA, tokenB)
|
||||
const result = await findRoute(helper, s.chainId, tokenA, tokenB)
|
||||
console.log('found route', result)
|
||||
os.routes = result
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import {ethers} from "ethers";
|
||||
|
||||
// synchronous version may return null but will trigger a lookup
|
||||
export function token(addr) {
|
||||
// todo deprecated. use metadataMap[chainId][addr]
|
||||
console.warn('token() is deprecated')
|
||||
console.log('token', addr)
|
||||
if( !addr ) {
|
||||
// console.log('ignoring call to token', addr)
|
||||
@@ -23,6 +25,8 @@ export function token(addr) {
|
||||
|
||||
// async version doesnt return until it has a token value
|
||||
export async function getToken(addr) {
|
||||
// todo deprecated. use metadataMap[chainId][addr]
|
||||
console.warn('getToken() is deprecated')
|
||||
const s = useStore()
|
||||
if (!(addr in s.tokens))
|
||||
await addExtraToken(addr)
|
||||
|
||||
@@ -6,20 +6,26 @@ import {vaultAbi} from "@/blockchain/abi.js";
|
||||
import {SingletonCoroutine} from "@/misc.js";
|
||||
import {defineStore} from "pinia";
|
||||
import {ref} from "vue";
|
||||
import {metadata, metadataMap} from "@/version.js";
|
||||
|
||||
|
||||
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
|
||||
// {
|
||||
// chainId: 31337, // must never be null, even if no wallet plugin exists. chosen by app, not wallet.
|
||||
// placementTime: Date.now(),
|
||||
// submitted: false // true after the order has started to be sent to the wallet
|
||||
// tx: null // transaction ID
|
||||
// vault: '0x...', // or null if account not logged in yet
|
||||
// order: {tokenIn:..., tokenOut:..., ...} // blockchain binary order object
|
||||
// }
|
||||
const pendingOrders = ref([])
|
||||
|
||||
return {
|
||||
pendingOrders,
|
||||
chainId, pendingOrders,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -27,27 +33,31 @@ export const useWalletStore = defineStore('wallet', ()=>{
|
||||
export function onChainChanged(chainId) {
|
||||
chainId = Number(chainId)
|
||||
const store = useStore()
|
||||
if( chainId !== store.chainId.value ) {
|
||||
// todo check pending orders and confirm cancellation
|
||||
const ws = useWalletStore()
|
||||
if( chainId !== ws.chainId ) {
|
||||
console.log('chain changed', chainId)
|
||||
store.chainId.value = chainId
|
||||
store.account = null
|
||||
const provider = new ethers.BrowserProvider(window.ethereum, chainId);
|
||||
store.provider = provider
|
||||
provider.listAccounts().then((accounts)=>changeAccounts(chainId, accounts.map((a)=>a.address)))
|
||||
ws.chainId = chainId
|
||||
if (chainId.toString() in metadataMap) {
|
||||
console.log('app chain changed', chainId)
|
||||
store.chainId = chainId
|
||||
store.account = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function updateAccounts(chainId, provider) {
|
||||
provider.listAccounts().then((accounts) => changeAccounts(chainId, accounts.map((a) => a.address)))
|
||||
}
|
||||
|
||||
|
||||
function changeAccounts(chainId, accounts) {
|
||||
// console.log('changeAccounts', chainId, accounts)
|
||||
// this is a notification from the wallet that the user selected a different blockchain. that chain may or may not
|
||||
// be supported. we store this value in walletStore.chainId, which may or may not be the same as
|
||||
// the application's useStore().chainId
|
||||
console.log('changeAccounts', chainId, accounts)
|
||||
const store = useStore()
|
||||
if( accounts.length === 0 ) {
|
||||
console.log('account logged out')
|
||||
store.account = null
|
||||
store.vaults = []
|
||||
store.vaultBalances = {}
|
||||
}
|
||||
else {
|
||||
if (chainId === store.chainId && accounts.length) {
|
||||
const addr = accounts[0]
|
||||
console.log('account logged in', addr)
|
||||
store.account = addr
|
||||
@@ -55,12 +65,19 @@ function changeAccounts(chainId, accounts) {
|
||||
flushTransactions()
|
||||
socket.emit('address', chainId, addr)
|
||||
}
|
||||
else {
|
||||
console.log('account logged out')
|
||||
store.account = null
|
||||
store.vaults = []
|
||||
store.vaultBalances = {}
|
||||
}
|
||||
}
|
||||
|
||||
function onAccountsChanged(accounts) {
|
||||
const store = useStore()
|
||||
const ws = useWalletStore()
|
||||
if (accounts.length === 0 || accounts[0] !== store.account)
|
||||
changeAccounts(store.chainId.value, accounts);
|
||||
changeAccounts(ws.chainId, accounts);
|
||||
}
|
||||
|
||||
export function detectChain() {
|
||||
@@ -105,8 +122,49 @@ const errorHandlingProxy = {
|
||||
}
|
||||
|
||||
|
||||
export async function connectProvider(chainId) {
|
||||
console.log('connecting provider to chainId', chainId)
|
||||
try {
|
||||
return new ethers.BrowserProvider(window.ethereum, chainId)
|
||||
}
|
||||
catch (e) {
|
||||
console.log('provider error', e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
export async function connectWallet(chainId) {
|
||||
await new ethers.BrowserProvider(window.ethereum, chainId).getSigner();
|
||||
console.log('connectWallet', chainId)
|
||||
const ws = useWalletStore()
|
||||
if (ws.chainId !== chainId && !await switchChain(chainId))
|
||||
return null
|
||||
const p = await connectProvider(chainId)
|
||||
if (p!==null) {
|
||||
try {
|
||||
return await p.getSigner();
|
||||
}
|
||||
catch (e) {
|
||||
if (e.reason!=='rejected')
|
||||
console.error(e, e.reason)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function switchChain(chainId) {
|
||||
if (useWalletStore().chainId === chainId)
|
||||
return true
|
||||
try {
|
||||
await window.ethereum.request({
|
||||
"method": "wallet_switchEthereumChain",
|
||||
"params": [{"chainId": '0x' + chainId.toString(16)}]
|
||||
})
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +181,7 @@ const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50, false)
|
||||
async function _discoverVaults(owner) {
|
||||
const result = []
|
||||
const s = useStore()
|
||||
if( !owner || !s.chainId.value || !s.account) {
|
||||
if( !owner || !s.chainId || !s.account) {
|
||||
s.vaults = []
|
||||
return
|
||||
}
|
||||
@@ -159,7 +217,7 @@ async function _discoverVaults(owner) {
|
||||
if( result.length )
|
||||
flushOrders(result[0])
|
||||
else
|
||||
ensureVault2(s.chainId.value, owner, 0)
|
||||
ensureVault2(s.chainId, owner, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,8 +234,8 @@ async function ensureVault1() {
|
||||
const s = useStore()
|
||||
const owner = s.account;
|
||||
if (owner===null)
|
||||
await connectWallet(s.chainId.value)
|
||||
ensureVault2(s.chainId.value, owner, 0)
|
||||
await connectWallet(s.chainId)
|
||||
ensureVault2(s.chainId, owner, 0)
|
||||
}
|
||||
|
||||
export function ensureVault2(chainId, owner, num) {
|
||||
@@ -209,9 +267,10 @@ export async function pendOrder(order) {
|
||||
console.log('order', JSON.stringify(order))
|
||||
const s = useStore()
|
||||
useWalletStore().pendingOrders.push({
|
||||
chainId: s.chainId.value,
|
||||
chainId: s.chainId,
|
||||
placementTime: new Date(),
|
||||
vault: s.vaults.length ? s.vaults[0] : null,
|
||||
submitted: false,
|
||||
order
|
||||
})
|
||||
ensureVault()
|
||||
@@ -243,13 +302,18 @@ export async function cancelAll(vault) {
|
||||
|
||||
export function flushOrders(vault) {
|
||||
const ws = useWalletStore();
|
||||
let needsFlush = false
|
||||
for( const order of ws.pendingOrders ) {
|
||||
if (order.vault === null)
|
||||
order.vault = vault
|
||||
pendOrderAsTransaction(order)
|
||||
if (!order.submitted) {
|
||||
pendOrderAsTransaction(order)
|
||||
order.submitted = true
|
||||
needsFlush = true
|
||||
}
|
||||
}
|
||||
ws.pendingOrders = []
|
||||
flushTransactions()
|
||||
if (needsFlush)
|
||||
flushTransactions()
|
||||
}
|
||||
|
||||
|
||||
@@ -260,8 +324,18 @@ function pendOrderAsTransaction(order) {
|
||||
console.error('vault contract was null while sending order transaction', order.vault)
|
||||
return null
|
||||
}
|
||||
if (!await switchChain(order.chainId)) {
|
||||
console.log('user refused chain switch')
|
||||
return null
|
||||
}
|
||||
console.log('placing order', order)
|
||||
return await contract.placeOrder(order.order) // todo update status
|
||||
const tx = await contract.placeOrder(order.order) // todo update status
|
||||
order.tx = tx
|
||||
tx.wait().then((txReceipt)=>{
|
||||
const ws = useWalletStore();
|
||||
ws.pendingOrders = ws.pendingOrders.filter((o)=>o!==order)
|
||||
})
|
||||
return tx
|
||||
})
|
||||
}
|
||||
|
||||
@@ -273,26 +347,15 @@ export function pendTransaction(sender) {
|
||||
}
|
||||
|
||||
|
||||
const flushTransactionsRoutine = new SingletonCoroutine(asyncFlushTransactions,1)
|
||||
|
||||
let flushing = 0 // semaphore
|
||||
|
||||
export function flushTransactions() {
|
||||
flushing++
|
||||
if( flushing === 1 )
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
asyncFlushTransactions()
|
||||
flushTransactionsRoutine.invoke()
|
||||
}
|
||||
|
||||
export async function asyncFlushTransactions() {
|
||||
let counter
|
||||
do {
|
||||
counter = flushing
|
||||
await asyncFlushTransactions2()
|
||||
} while( flushing > counter)
|
||||
flushing = 0
|
||||
}
|
||||
|
||||
export async function asyncFlushTransactions2() {
|
||||
// todo rework into flushTransactions()
|
||||
async function asyncFlushTransactions() {
|
||||
const s = useStore()
|
||||
if( s.provider === null ) {
|
||||
console.log('warning: asyncFlushOrders() cancelled due to null provider')
|
||||
@@ -319,22 +382,21 @@ export async function asyncFlushTransactions2() {
|
||||
|
||||
function doSendTransaction(sender, signer) {
|
||||
const s = useStore();
|
||||
s.removeTransactionSender(sender)
|
||||
sender(signer).then((tx)=>{
|
||||
console.log('sent transaction', tx)
|
||||
s.removeTransactionSender(sender)
|
||||
tx.wait().then((tr)=>console.log('tx receipt',tr))
|
||||
if (tx!==null) {
|
||||
console.log('sent transaction', tx)
|
||||
tx.wait().then((tr)=>console.log('tx receipt',tr))
|
||||
}
|
||||
}).catch((e)=>{
|
||||
if( e.info?.error?.code === 4001 ) {
|
||||
console.log(`user rejected transaction`)
|
||||
s.removeTransactionSender(sender)
|
||||
}
|
||||
else {
|
||||
if( e.reason && e.info )
|
||||
console.error('error sending transaction', e.reason, e.info)
|
||||
else
|
||||
console.error('error sending transaction', e)
|
||||
s.removeTransactionSender(sender)
|
||||
// todo retry?
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user