Files
server/vault.js
2024-07-16 22:49:39 -04:00

121 lines
4.3 KiB
JavaScript

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)
console.log('vault addr', address)
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(' ==> vault addr', 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
}