import {ethers} from "ethers"; import {getProvider, getSigner} from "./blockchain.js"; import {vaultBalances, vaults} from './cache.js'; import {chainInfo} from "./chain.js"; import {sendVaultOrders} from "./order.js"; import {newContract} from "./contract.js"; export function vaultAddress(chainId, owner, num=0) { try { const salt = ethers.solidityPackedKeccak256(['address','uint8'],[owner,num]) const result = ethers.getCreate2Address(chainInfo[chainId].factory, salt, chainInfo[chainId].vaultInitCodeHash) // console.log('vaultAddress', chainId, owner, num, chainInfo[chainId].factory, salt, VAULT_INIT_CODE_HASH, result) return result } catch (e) { console.error('Could not generate vault address',chainId,owner,num,e) return null } } async function emitBalances(socket, chainId, vault) { const balances = await vaultBalances.get(chainId, vault); socket.emit('vb', chainId, vault, balances !== null ? balances : '{}') return balances; } async function sendVaultInfo(socket, chainId, owner) { const found = [] for (let num = 0; ; num++) { const vault = vaultAddress(chainId, owner, num) if (vault !== null && await vaults.contains(chainId, vault)) { found.push(vault) const balances = await emitBalances(socket, chainId, vault); console.log('found vault', vault, balances) } else break } console.log('sending vaults', found) socket.emit('vaults', chainId, owner, found) for (const vault of found) sendVaultOrders(socket, chainId, vault) } export async function loginAddress(socket, chainId, address) { if( socket.user_room !== undefined) socket.leave(socket.user_room) if( address ) { socket.user_room = `${chainId}|${address}` socket.join(socket.user_room) console.log('joined user room', socket.user_room) await sendVaultInfo(socket, chainId, address); } } const ensuring = {} export async function ensureVault(socket, chainId, owner, num) { const key = [chainId, owner, num] if( key in ensuring ) { console.log('squelching ensureVault since one is in-progress') return } ensuring[key] = true console.log('ensureVault', chainId, owner, num) if( chainId in chainInfo ) { const address = vaultAddress(chainId, owner, num) if (!await vaults.contains(chainId,address)) { try { const vault = await createVault(chainId, owner, num) if (vault !== null) { console.log('created vault', vault) socket.emit('vaults', chainId, owner, [vault]) await emitBalances(socket, chainId, vault) } else console.error('got null vault for chainId', chainId) } catch { } } else console.log('ensureVault', owner, 'exists:', address) } await sendVaultInfo(socket, chainId, owner) delete ensuring[key] } async function createVault(chainId, owner, num) { const signer = getSigner(chainId); const factory = chainInfo[chainId].factory; console.log('createVault', chainId, owner, num, factory, chainInfo[chainId].vaultInitCodeHash ) const deployer = await newContract(factory, 'IVaultFactory', signer) const vaultAddr = vaultAddress(chainId, owner, num) console.log(' ==>', vaultAddr ) try { const tx = await deployer['deployVault(address,uint8)'](owner, num) // must specify which deployVault() to call console.log(`deploying vault for ${owner} #${num} with tx ${tx.hash}`) const result = await tx.wait() if (result.status !== 1) { // noinspection ExceptionCaughtLocallyJS throw Error(`Vault deployment reverted. tx ${tx.hash}`) } } catch (e) { const vault = await newContract(vaultAddr, 'IVault', getProvider(chainId)) try { const ver = await vault.version() console.log(`vault already deployed at ${vaultAddr} with version ${ver}`) } catch (e2) { console.error('could not deploy vault:', e) return null } } return vaultAddr }