mirror of
https://github.com/0x1d/drift-keeper.git
synced 2025-12-14 18:35:20 +01:00
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:
1
user-metrics/.gitignore
vendored
Normal file
1
user-metrics/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
7
user-metrics/Dockerfile
Normal file
7
user-metrics/Dockerfile
Normal 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
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
20
user-metrics/package.json
Normal 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
94
user-metrics/src/main.js
Normal 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();
|
||||
});
|
||||
|
||||
42
user-metrics/src/metrics.js
Normal file
42
user-metrics/src/metrics.js
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user