From 2b4a77454ccf9b8499c75d21ccbf54c34fa18aca Mon Sep 17 00:00:00 2001 From: Mike Frager Date: Tue, 22 Nov 2022 14:04:07 -0800 Subject: [PATCH] Trade logging --- Cargo.lock | 9 +- js/spl/create_users.js | 2 +- js/spl/market_wsol_usdc_1.json | 12 +-- js/spl/market_wsol_usdc_1.json.bak | 9 -- js/spl/orders1.js | 3 +- js/spl/show_trade_log.js | 148 +++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 22 deletions(-) delete mode 100644 js/spl/market_wsol_usdc_1.json.bak create mode 100644 js/spl/show_trade_log.js diff --git a/Cargo.lock b/Cargo.lock index fb1ea2a..ce7e2b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ dependencies = [ "bytemuck", "num_enum", "security-token", - "slab-alloc 1.0.0", + "slab-alloc 1.0.0 (git+https://github.com/atellix/slab-alloc?branch=aqua-dex)", "solana-program", ] @@ -811,7 +811,7 @@ dependencies = [ "byte-slice-cast", "bytemuck", "num_enum", - "slab-alloc 1.0.1", + "slab-alloc 1.0.0", "solana-program", "uuid", ] @@ -1194,7 +1194,6 @@ dependencies = [ [[package]] name = "slab-alloc" version = "1.0.0" -source = "git+https://github.com/atellix/slab-alloc?branch=aqua-dex#ca2bfd0883ce8d4c9fe3f342bbe392774c83e948" dependencies = [ "arrayref", "bytemuck", @@ -1207,8 +1206,8 @@ dependencies = [ [[package]] name = "slab-alloc" -version = "1.0.1" -source = "git+https://github.com/atellix/slab-alloc?branch=net-authority#54e09b99ac5bf8aff1ca593eff17b5b0b3da592d" +version = "1.0.0" +source = "git+https://github.com/atellix/slab-alloc?branch=aqua-dex#ca2bfd0883ce8d4c9fe3f342bbe392774c83e948" dependencies = [ "arrayref", "bytemuck", diff --git a/js/spl/create_users.js b/js/spl/create_users.js index 581fdde..4e4c12a 100644 --- a/js/spl/create_users.js +++ b/js/spl/create_users.js @@ -31,7 +31,7 @@ async function storeUser(uid, kp) { async function main() { var users = [] - for (var x = 0; x < 100; x++) { + for (var x = 0; x < 20; x++) { kp = anchor.web3.Keypair.generate() users.push({ 'pubkey': kp.publicKey.toString(), diff --git a/js/spl/market_wsol_usdc_1.json b/js/spl/market_wsol_usdc_1.json index c8c62d3..1f4cfce 100644 --- a/js/spl/market_wsol_usdc_1.json +++ b/js/spl/market_wsol_usdc_1.json @@ -1,10 +1,10 @@ { "tokenMint1": "So11111111111111111111111111111111111111112", "tokenMint2": "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr", - "market": "BJohpKc6fsNp3zMNFdXFg5wLzn8qo9JF2szioM2RPixZ", - "marketState": "BhjDgYQuZbq4oaW7Qvw8aqyZidhKNE5uDp9486wZTCdk", - "orders": "5L2tXwNgFPXvgM733q2oKnp6K3aJMaeP8AVJdYd3ZjUL", - "tradeLog": "Toqjg81bPznQEUdDoMnfixxy9UmE4hX2rDSGepBSY8P", - "settle1": "7bHiNpWtzKCDWCAPYCnyiBM8RtyUXRma6kFrxXv9sKjR", - "settle2": "J79Xw1CURSBJcXr2aMXPkLouXJWVZfUBNv72AdVzvv96" + "market": "HmGNL7Gnww1c7n7MgpHAA1CvERxxiFid9mtXrnGa47nz", + "marketState": "HGe36WbsrNUUaLhxtM8ovC74e6JEtTBi9oeAgmhmq13", + "orders": "HEwL543Kfs5UCeZmgArVtDrLUxJABNGR17VcMDmoM34h", + "tradeLog": "8rfAFi5ZdY5zM6R5VwpK1YRCXpgJ3AJxPfbivhZtMK8s", + "settle1": "GN8T4rU8waYpF3anyouWH6QVbRZh5PdpTU3ubxhDzL8a", + "settle2": "74TmswUNDgg5nx7Uv4JHvezmB4vXUnS9FfQQrof9VTTz" } \ No newline at end of file diff --git a/js/spl/market_wsol_usdc_1.json.bak b/js/spl/market_wsol_usdc_1.json.bak deleted file mode 100644 index a0f8d88..0000000 --- a/js/spl/market_wsol_usdc_1.json.bak +++ /dev/null @@ -1,9 +0,0 @@ -{ - "tokenMint1": "So11111111111111111111111111111111111111112", - "tokenMint2": "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr", - "market": "2F8dLJVEQ1kc6piZPZD1Crxw5MwpmqaBD7hHAN2WhaPX", - "marketState": "DbVdPACMvo94QCzKH6fnqShNW3YiWjq4NJTCK4nMKhDW", - "orders": "473P9nKcGE6saA2EFbyA6SnMksFdEc6J6iFUeSzgmVu3", - "settle1": "5XUwQXprew4jVmbenriTdvu9sjd55rGVG7JJiziEFp84", - "settle2": "Eae1TcpRV5e1KvgnJ6hzzYqkuXbcNcKwdJ1bfAh4soxc" -} \ No newline at end of file diff --git a/js/spl/orders1.js b/js/spl/orders1.js index e20e411..65ca0ae 100644 --- a/js/spl/orders1.js +++ b/js/spl/orders1.js @@ -234,7 +234,8 @@ async function main() { var userWallet = importSecretKey(user.secret) var userToken1 = await associatedTokenAddress(userWallet.publicKey, tokenMint1) var userToken2 = await associatedTokenAddress(userWallet.publicKey, tokenMint2) - console.log(await limitOrder('bid', userWallet, resultData1, 1 * (10**9), 15 * (10**6))) + //console.log(await limitOrder('bid', userWallet, resultData1, 1 * (10**9), 15 * (10**6))) + console.log(await limitOrder('ask', userWallet, resultData1, 1 * (10**9), 15 * (10**6))) var res = await aquadex.account.tradeResult.fetch(resultData1.publicKey) console.log(formatOrder(res)) diff --git a/js/spl/show_trade_log.js b/js/spl/show_trade_log.js new file mode 100644 index 0000000..76c98b5 --- /dev/null +++ b/js/spl/show_trade_log.js @@ -0,0 +1,148 @@ +const { Buffer } = require('buffer') +const { DateTime } = require("luxon") +const { v4: uuidv4, parse: uuidparse, stringify: uuidstringify } = require('uuid') +const { PublicKey, Keypair, SystemProgram, SYSVAR_RENT_PUBKEY } = require('@solana/web3.js') +const { TOKEN_PROGRAM_ID } = require('@solana/spl-token') +const { promisify } = require('util') +const exec = promisify(require('child_process').exec) +const fs = require('fs').promises +const base32 = require("base32.js") +const anchor = require('@project-serum/anchor') +const lo = require('buffer-layout') +const bigintConv = require('bigint-conversion') + +const provider = anchor.AnchorProvider.env() +//const provider = anchor.Provider.local() +anchor.setProvider(provider) + +const aquadex = anchor.workspace.AquaDex +const aquadexPK = aquadex.programId + +function showData(spec) { + var r = {} + for (var i in spec) { + if (typeof spec[i] === 'object' && spec[i].constructor.name === 'Object') { + r[i] = showData(spec[i]) + } else if (typeof spec[i].toString !== 'undefined') { + r[i] = spec[i].toString() + } + } + return r +} + +function encodeOrderId(orderIdBuf) { + const enc = new base32.Encoder({ type: "crockford", lc: true }) + var zflist = orderIdBuf.toJSON().data + var zflen = 16 - zflist.length + if (zflen > 0) { + zfprefix = Array(zflen).fill(0) + zflist = zfprefix.concat(zflist) + } + zflist.reverse() + return enc.write(new Uint8Array(zflist)).finalize() +} + +function decodeTradeLogVec(pageTableEntry, pages) { + const headerSize = pageTableEntry['header_size'] + const offsetSize = pageTableEntry['offset_size'] + const stLogEntry = lo.struct([ + lo.blob(16, 'event_type'), + lo.nu64('action_id'), + lo.nu64('trade_id'), + lo.blob(16, 'maker_order_id'), + lo.u8('maker_filled'), + lo.blob(32, 'maker'), + lo.blob(32, 'taker'), + lo.u8('taker_side'), + lo.nu64('amount'), + lo.nu64('price'), + lo.ns64('ts'), + ]) + const instPerPage = Math.floor((16384 - (headerSize + offsetSize)) / stLogEntry.span) + const stSlabVec = lo.struct([ + lo.blob(offsetSize), + lo.nu64('trade_count'), + lo.nu64('entry_max'), + lo.seq(stLogEntry, instPerPage, 'logs'), + ]) + var totalPages = Math.floor(pageTableEntry['alloc_items'] / instPerPage) + if ((pageTableEntry['alloc_items'] % instPerPage) !== 0) { + totalPages = totalPages + 1 + } + var vecPages = [] + for (var p = 0; p < totalPages; p++) { + var pidx = pageTableEntry['alloc_pages'][p] + vecPages.push(pages[pidx]) + } + var logSpec = { + 'logs': [], + } + for (var i = 0; i < vecPages.length; i++) { + var res = stSlabVec.decode(vecPages[i]) + if (i === 0) { + logSpec['trade_count'] = res['trade_count'] + logSpec['entry_max'] = res['entry_max'] + } + for (var logIdx = 0; logIdx < res['logs'].length; logIdx++) { + var item = res['logs'][logIdx] + if (item['trade_id'] === 0) { + continue + } + item['event_type'] = (new anchor.BN(item['event_type'])).toString() + item['maker_order_id'] = encodeOrderId(item['maker_order_id']) + item['maker'] = new PublicKey(item['maker']).toString() + item['taker'] = new PublicKey(item['taker']).toString() + logSpec['logs'].push(item) + if (logSpec['logs'].length === pageTableEntry['alloc_items']) { + i = vecPages.length + break + } + } + } + logSpec.logs.reverse() + return logSpec +} + +function decodeTradeLog(data) { + const stTypedPage = lo.struct([ + lo.nu64('header_size'), + lo.nu64('offset_size'), + lo.nu64('alloc_items'), + lo.seq(lo.u16('page_index'), 128, 'alloc_pages'), // TYPE_MAX_PAGES + ]); + const stSlabAlloc = lo.struct([ + lo.u16('top_unused_page'), + lo.seq(stTypedPage, 16, 'type_page'), // TYPE_MAX + lo.seq(lo.blob(16384), 4, 'pages'), // PAGE_SIZE + ]); + var res = stSlabAlloc.decode(data) + //console.log(JSON.stringify(res['type_page'])) + var logVec = res['type_page'][0] + var vecData = decodeTradeLogVec(logVec, res['pages']) + console.log('Trade Log Vec:') + console.log(vecData) + + //console.log(res) + //var pageTableHeaderLen = 130 + //var pageSize = 16384 +} + +async function main() { + var ndjs + var market = process.argv[2] + try { + ndjs = await fs.readFile(market) + } catch (error) { + console.error('File Error: ', error) + } + const mktData = JSON.parse(ndjs.toString()) + const tradeLogPK = new PublicKey(mktData.tradeLog) + const tradeLog = await provider.connection.getAccountInfo(tradeLogPK) + //console.log(orderBook.data) + decodeTradeLog(tradeLog.data) +} + +console.log('Begin') +main().then(() => console.log('Success')).catch(error => { + console.log(error) +})