diff --git a/abi.js b/abi.js index e2d5424..b91a9ad 100644 --- a/abi.js +++ b/abi.js @@ -20,7 +20,7 @@ export const erc20Abi = [ const factoryAbi = [ - 'function deployVault(address owner) returns (address vault)', + 'function deployVault(address owner, uint8 num) returns (address vault)', 'event VaultCreated( address deployer, address owner )', ] diff --git a/cache.js b/cache.js index 16e85f1..0d597a3 100644 --- a/cache.js +++ b/cache.js @@ -13,7 +13,10 @@ export class CacheSet { } async contains(chain, key) { - return await redis.sIsMember(`${chain}|${this.series}`, key) + const series = `${chain}|${this.series}`; + const result = await redis.sIsMember(series, key) + console.log('contains', series, key, result) + return result } } @@ -40,12 +43,13 @@ export class CacheObject { } } -const cache_blocks = { +const blockCaches = { '1338': new CacheObject('1338|latest_block'), + '42161': new CacheObject('42161|latest_block'), } async function latestBlock(chain) { - return await cache_blocks[chain].get() + return await blockCaches[chain].get() } export const vaults = new CacheSet('v') diff --git a/main.js b/main.js index 5961ed8..c1d8ea4 100644 --- a/main.js +++ b/main.js @@ -3,7 +3,7 @@ import 'dotenv/config' import {lookupToken} from "./token.js"; import {httpServer, io} from "./io.js"; import {ensureVault, loginAddress} from "./vault.js"; -import {chainInfo} from "./misc.js"; +import {chainInfo, VAULT_INIT_CODE_HASH} from "./misc.js"; // setup socket.io @@ -14,10 +14,9 @@ io.on("connection", (socket) => { lookupToken(chainId, address).then((result)=>callback(result)).catch(()=>callback(null)) }) socket.on('address', (chainId, address) => loginAddress(socket, chainId, address) ) - socket.on('ensureVault', ensureVault ) - socket.emit('chainInfo', chainInfo) + socket.on('ensureVault', (chainId,owner,num) => ensureVault(socket, chainId, owner, num) ) socket.join('public') - io.to('room').emit('event', {foo:'bar'}) + socket.emit('welcome', {chainInfo, vaultInitCodeHash:VAULT_INIT_CODE_HASH}) }); io.on("disconnection", (socket)=>{ diff --git a/misc.js b/misc.js index 2a111f3..10dc582 100644 --- a/misc.js +++ b/misc.js @@ -26,6 +26,7 @@ for (const chain of _chains) { deployment = JSON.parse(fs.readFileSync(path, 'utf8')) //null synchronous is ok we only do this once on init } catch { + console.log(`warning: could not read deployment files for ${chain.id}`) continue } for (const tx of deployment.transactions) { diff --git a/vault.js b/vault.js index 77f8fe8..7281006 100644 --- a/vault.js +++ b/vault.js @@ -1,50 +1,83 @@ -import {ethers, keccak256} from "ethers"; +import {ethers} from "ethers"; import {getAbi} from "./abi.js"; -import {getSigner} from "./blockchain.js"; +import {getProvider, getSigner} from "./blockchain.js"; import {vaults} from './cache.js'; +import {chainInfo, VAULT_INIT_CODE_HASH} from "./misc.js"; // Vault // address owner // balances { tokenAddress: amount } // recentOrders [] -const deployerAbi = await getAbi('Factory'); +const vaultAbi = await getAbi('Vault') +const factoryAbi = await getAbi('Factory') -export function vaultAddress(chainId, ownerAddress, num=0) { - const encoded = ethers.AbiCoder.defaultAbiCoder().encode(['address','uint8'], [ownerAddress,num]) - const salt = ethers.keccak256(encoded) - return ethers.getCreate2Address(getDeployerAddress(chainId), salt, VAULT_INIT_CODE_HASH) +export function vaultAddress(chainId, owner, num=0) { + const salt = ethers.solidityPackedKeccak256(['address','uint8'],[owner,num]) + const result = ethers.getCreate2Address(chainInfo[chainId].factory, salt, VAULT_INIT_CODE_HASH) + console.log('vaultAddress', chainId, owner, num, chainInfo[chainId].factory, salt, VAULT_INIT_CODE_HASH, result) + return result } export async function loginAddress(socket, chainId, address) { - // todo send known tokens - if (await vaults.contains(chainId,address)) { - // todo send welcome with basic info and extra tokens - socket.send('welcome',{}) + console.log('loginAddress', chainId, address) + if( socket.user_room !== undefined) + socket.leave(socket.user_room) + socket.user_room = `${chainId}|${address}` + socket.join(socket.user_room) + const found = [] + for( let num = 0; ; num++ ) { + const vault = vaultAddress(chainId, address, num) + if(await vaults.contains(chainId, vault)) + found.push(vault) + else + break } + socket.emit('vaults', found) } -export async function ensureVault(chainId, owner, num) { +export async function ensureVault(socket, chainId, owner, num) { + console.log('ensureVault', owner, num) const address = vaultAddress(chainId, owner, num) - if (!await vaults.contains(chainId,address)) - await createVault(chainId, owner, num) + if (!await vaults.contains(chainId,address)) { + try { + await createVault(chainId, owner, num) + await loginAddress(socket, chainId, owner) + } catch { + } + } + else + console.log('ensureVault', owner, 'exists:', address) } async function createVault(chainId, owner, num) { // todo create vault request for backend to pick up - const deployer = new ethers.Contract(factoryAddresses[chainId], deployerAbi, getSigner(chainId)) - await deployer.deployVault(owner, num) + console.log('creating vault', owner, num) + const signer = getSigner(chainId); + const deployer = new ethers.Contract(chainInfo[chainId].factory, factoryAbi, signer) + console.log('got deployer') + try { + const tx = await deployer.deployVault(owner, num) + console.log(`deploying vault for ${owner} #${num} with tx ${tx.hash}`) + } + catch (e) { + const addr = vaultAddress(chainId, owner, num) + const vault = new ethers.Contract(addr, vaultAbi, getProvider(chainId)) + try { + const ver = await vault.version() + console.log(`vault already deployed at ${addr} with version ${ver}`) + } + catch (e2) { + console.error('could not deploy vault:',e) + } + } } -export async function watchVaultCreated(provider, db, event) { - console.log(`vault created`, event) -} - export async function watchErc20Transfer(provider, db, event) { console.log('Transfer', event) const [from, to, amount] = event.args