Multi-Cloud Deployment (#1)

* Introduce instances list to scale bots and add config templating

* Use env var for wallet address if not provided as path param

* Expose SOL price as metric

* Update docs

* Add auto-swap

* Add Panopticon

* implement backoff stategy in autoswap

* Add retry logic for withdraw and swap

* bump drift-sdk, update ctl.sh and docs

* Update filler bot, add tx metrics

* Add user-metrics

* Update build and dashboard
This commit is contained in:
Patrick Balsiger
2024-04-28 07:25:08 +02:00
committed by GitHub
parent 6bd2c3367b
commit f05fac48ca
58 changed files with 9783 additions and 319 deletions

1
user-metrics/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

7
user-metrics/Dockerfile Normal file
View File

@@ -0,0 +1,7 @@
FROM node:18
WORKDIR /app
COPY package.json ./
RUN npm install
COPY src src
CMD ["npm", "start"]

2278
user-metrics/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
user-metrics/package.json Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "dex-metrics",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node --no-warnings=ExperimentalWarning src/main.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"prom-client": "^15.1.0",
"@drift-labs/sdk": "2.78.0-beta.0",
"@solana/web3.js": "^1.89.1",
"bigint-buffer": "^1.1.5",
"dotenv": "^16.4.4"
}
}

94
user-metrics/src/main.js Normal file
View File

@@ -0,0 +1,94 @@
require('dotenv').config()
const web3 = require("@solana/web3.js");
const drift = require("@drift-labs/sdk");
const express = require('express');
const { createMetrics } = require('./metrics');
const LAMPORTS_PER_SOL = 1000000000;
const USDC_INT = 1000000;
const USDC_MARKET = 0;
const SOL_MARKET = 1;
const SOL_MINT_ADDRESS = 'So11111111111111111111111111111111111111112';
const USDC_MINT_ADDRESS = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
const USDC_MINT_PUBLIC_KEY = new web3.PublicKey(USDC_MINT_ADDRESS);
const keyPairFile = process.env.PRIVATE_KEY || process.env.PRIVATE_KEY_FILE;
const wallet = new drift.Wallet(drift.loadKeypair(keyPairFile));
const connection = new web3.Connection(process.env.RPC_ENDPOINT);
const [registry, metrics] = createMetrics();
const app = express();
const driftClient = new drift.DriftClient({
connection,
wallet,
env: 'mainnet-beta',
activeSubAccountId: 0,
subAccountIds: [0],
});
const log = (msg) => {
console.log(`[${new Date().toISOString()}] ${msg}`)
};
const trimWalletAddress = (walletAddress) => {
return `${walletAddress.slice(0,4)}...${walletAddress.slice(walletAddress.length-4, walletAddress.length)}`;
}
const quoteNumber = (val) => {
return drift.convertToNumber(val, drift.QUOTE_PRECISION);
}
const baseNumber = (val) => {
return drift.convertToNumber(val, drift.BASE_PRECISION);
}
const getWalletBalance = async (connection, publicKey) => {
const lamportsBalance = await connection.getBalance(publicKey);
return lamportsBalance / LAMPORTS_PER_SOL;
};
const getUsdcBalance = async (connection, publicKey) => {
const balance = await connection.getParsedTokenAccountsByOwner(
publicKey, { mint: USDC_MINT_PUBLIC_KEY }
);
return balance.value[0]?.account.data.parsed.info.tokenAmount.uiAmount;
};
const init = async() => {
await driftClient.subscribe();
log('DriftClient initialized');
ready = true;
};
let ready = false;
app.get('/metrics', async (req, res) => {
res.setHeader('Content-Type', registry.contentType);
registry.resetMetrics();
if(ready){
let user = driftClient.getUser();
let label = { wallet: wallet.publicKey.toString(), walletShort: trimWalletAddress(wallet.publicKey.toString()) };
metrics.totalCollateral.set(label, quoteNumber(user.getTotalCollateral()));
metrics.unrealizedPNL.set(label, quoteNumber(user.getUnrealizedPNL()));
metrics.solBalance.set(label, await getWalletBalance(connection, wallet.publicKey));
metrics.usdcBalance.set(label, await getUsdcBalance(connection, wallet.publicKey));
}
res.send(await registry.metrics());
});
app.listen(3000, () => {
log("Server is running on port 3000");
init();
});

View File

@@ -0,0 +1,42 @@
const client = require('prom-client');
const createMetrics = () => {
const registry = new client.Registry();
const solBalanceMetric = new client.Gauge({
name: "sol_balance",
help: "SOL Balance",
labelNames: ['wallet','walletShort']
});
const usdcBalanceMetric = new client.Gauge({
name: "usdc_balance",
help: "USDC Balance",
labelNames: ['wallet','walletShort']
});
const totalCollateralMetric = new client.Gauge({
name: "total_collateral",
help: "Total Collateral",
labelNames: ['wallet','walletShort']
});
const unrealizedPNLMetric = new client.Gauge({
name: "unrealized_pnl",
help: "Unrealized PNL",
labelNames: ['wallet','walletShort']
});
registry.registerMetric(usdcBalanceMetric);
registry.registerMetric(solBalanceMetric);
registry.registerMetric(totalCollateralMetric);
registry.registerMetric(unrealizedPNLMetric);
return [registry, {
usdcBalance: usdcBalanceMetric,
solBalance: solBalanceMetric,
totalCollateral: totalCollateralMetric,
unrealizedPNL: unrealizedPNLMetric
}];
};
module.exports = {
createMetrics
}