Skip to content

Commit

Permalink
Merge pull request #26 from galacticcouncil/router-integration
Browse files Browse the repository at this point in the history
router-integration
  • Loading branch information
mrq1911 authored Jan 10, 2025
2 parents 824bc04 + 1d605dc commit a580885
Show file tree
Hide file tree
Showing 14 changed files with 1,926 additions and 1,493 deletions.
3,296 changes: 1,851 additions & 1,445 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
"transform": {}
},
"dependencies": {
"@polkadot/api": "^8.13.1",
"@polkadot/util": "^10.0.2",
"@galacticcouncil/sdk": "^5.1.0",
"@polkadot/api": "~14.0.1",
"@polkadot/util": "~13.1.1",
"dijkstrajs": "^1.0.2",
"discord.js": "^14.0.3",
"dotenv": "^16.0.1",
Expand Down
14 changes: 12 additions & 2 deletions src/api.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import {ApiPromise, WsProvider} from "@polkadot/api";
import {PoolService, TradeRouter} from "@galacticcouncil/sdk";


let initialized = false;
let _api;
let _sdk;
let provider;

export async function initApi(rpc) {
console.warn = () => {};
provider = new WsProvider(rpc);
_api = await ApiPromise.create({provider});
const poolService = new PoolService(_api);
_sdk = new TradeRouter(poolService);
initialized = true;
const version = await _api.query.system.lastRuntimeUpgrade();
const {specVersion, specName} = version.toJSON();
console.log(`connected to ${specName}/${specVersion} on ${rpc}`);
await poolService.syncRegistry();
}

export async function disconnect() {
Expand All @@ -28,5 +34,9 @@ export function api() {
return _api;
}



export function sdk() {
if (!initialized || !_sdk) {
throw new Error('router not synced');
}
return _sdk;
}
2 changes: 1 addition & 1 deletion src/bot.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {initApi, api} from './api.js';
import {initApi, api, sdk} from './api.js';
import {Events} from "./events.js";
import xyk from "./handlers/xyk.js";
import lbp from "./handlers/lbp.js";
Expand Down
17 changes: 14 additions & 3 deletions src/currencies.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {api} from "./api.js";
import {api, sdk} from "./api.js";
import dijkstrajs from "dijkstrajs";
import {usdCurrencyId, whaleAmount} from "./config.js";
import {fromAccount} from "./utils/evm.js";
Expand Down Expand Up @@ -50,11 +50,22 @@ export const recordPrice = (sold, bought) => {
prices[a][b] = pair[0].amount / pair[1].amount;
}

export function usdValue({currencyId, amount}) {
export function recordedUsdValue({currencyId, amount}) {
const price = getPrice(currencyId, usdCurrencyId);
return price ? amount / price : null;
}

export async function usdValue({currencyId, amount}) {
if (currencyId.toString() === usdCurrencyId) return null;
try {
const spot = await sdk().getBestSpotPrice(currencyId.toString(), usdCurrencyId);
return (amount / 10 ** decimals(currencyId)) * spot.amount;
} catch (e) {
console.log('failed to get USD price from router:', e.message);
return recordedUsdValue({currencyId, amount});
}
}

export function getPrice(asset, target) {
if (prices[asset] && prices[asset][target]) {
return prices[asset][target];
Expand Down Expand Up @@ -107,4 +118,4 @@ export const formatUsdValue = value => {
return ` *~ ${new Intl.NumberFormat('en-US', {maximumSignificantDigits: amount < 1 ? 1 : 4, maximumFractionDigits: 2}).format(amount).replace(/,/g, " ")} ${symbol}*`;
};
export const formatUsdNumber = amount => new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}).format(amount);
export const formatAsset = asset => `**${formatAmount(asset)}**${asset.currencyId.toString() === usdCurrencyId ? formatUsdValue(usdValue(asset)) : ''}`;
export const formatAsset = async asset => `**${formatAmount(asset)}**${asset.currencyId.toString() === usdCurrencyId ? formatUsdValue(await usdValue(asset)) : ''}`;
17 changes: 10 additions & 7 deletions src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ export class Events {
return false;
}
}
const addedCallback = payload => callback({...payload, log: iface.parseLog(payload.event.data.log.toHuman())});
const addedCallback = payload => {
payload.log = iface.parseLog(payload.event.data.log.toHuman());
return callback(payload);
};
this.listeners.push({section: 'evm', method: 'Log', filterPredicate, addedCallback});
return this;
}
Expand Down Expand Up @@ -90,13 +93,13 @@ export const loadEvents = async blockNumber => api().rpc.chain.getBlockHash(bloc
.then(hash => api().query.system.events.at(hash))
.then(events => processEvents(events, blockNumber));

export const processEvents = (events, blockNumber) => events.map(event => ({
blockNumber,
siblings: events
export const processEvents = (events, blockNumber) => events.map(event => {
event.blockNumber = blockNumber;
event.siblings = events
.filter(({phase}) => (phase.isInitialization && event.phase.isInitialization)
|| phase.isApplyExtrinsic
&& event.phase.isApplyExtrinsic
&& phase.asApplyExtrinsic.eq(event.phase.asApplyExtrinsic))
.map(({event}) => event),
...event
}));
.map(({event}) => event);
return event;
});
10 changes: 5 additions & 5 deletions src/handlers/borrowing.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,35 @@ export default function borrowingHandler(events) {
async function supply({log: {args: {reserve, amount, onBehalfOf}}}) {
const supplied = {currencyId: ERC20Mapping.decodeEvmAddress(reserve), amount}
const account = await toAccount(onBehalfOf);
const message = `${formatAccount(account)} supplied ${formatAsset(supplied)}`;
const message = `${formatAccount(account)} supplied ${await formatAsset(supplied)}`;
broadcast(message);
}

async function withdraw({log: {args: {reserve, amount, to}}}) {
const withdrew = {currencyId: ERC20Mapping.decodeEvmAddress(reserve), amount}
const account = await toAccount(to);
const message = `${formatAccount(account)} withdrew ${formatAsset(withdrew)}`;
const message = `${formatAccount(account)} withdrew ${await formatAsset(withdrew)}`;
broadcast(message);
}

async function borrow({log: {args: {reserve, amount, onBehalfOf}}}) {
const borrowed = {currencyId: ERC20Mapping.decodeEvmAddress(reserve), amount}
const account = await toAccount(onBehalfOf);
const message = `${formatAccount(account)} borrowed ${formatAsset(borrowed)}`;
const message = `${formatAccount(account)} borrowed ${await formatAsset(borrowed)}`;
broadcast(message);
}

async function repay({log: {args: {reserve, amount, user}}}) {
const repaid = {currencyId: ERC20Mapping.decodeEvmAddress(reserve), amount}
const account = await toAccount(user);
const message = `${formatAccount(account)} repaid ${formatAsset(repaid)}`;
const message = `${formatAccount(account)} repaid ${await formatAsset(repaid)}`;
broadcast(message);
}

async function liquidationCall({log: {args}}) {
const collateral = {currencyId: ERC20Mapping.decodeEvmAddress(args.collateralAsset), amount: args.liquidatedCollateralAmount}
const [liquidator, user] = await Promise.all([toAccount(args.liquidator), toAccount(args.user)]);
const message = `${formatAccount(liquidator)} liquidated ${formatAsset(collateral)} of ${formatAccount(user)}`;
const message = `${formatAccount(liquidator)} liquidated ${await formatAsset(collateral)} of ${formatAccount(user)}`;
broadcast(message);
}

Expand Down
30 changes: 16 additions & 14 deletions src/handlers/dca.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,22 @@ function terminatedHandler({event}) {
function broadcastBuffer(scheduleId) {
const executions = buffer.filter(({id}) => id === scheduleId);
buffer = buffer.filter(({id}) => id !== scheduleId);
const {who} = executions[0];
const {assetIn, assetOut} = executions[0].trade.data;
const amountIn = executions.reduce((sum, {trade}) => sum.add(trade.data.amountIn), new BN(0));
const amountOut = executions.reduce((sum, {trade}) => sum.add(trade.data.amountOut), new BN(0));
if (executions.length === 1) {
return swapHandler({who, assetIn, assetOut, amountIn, amountOut});
} else {
return swapHandler({
who,
assetIn,
assetOut,
amountIn,
amountOut
}, `split over ${executions.length} swaps`);
if (executions[0].trade) {
const {who} = executions[0];
const {assetIn, assetOut} = executions[0].trade.data;
const amountIn = executions.reduce((sum, {trade}) => sum.add(trade.data.amountIn), new BN(0));
const amountOut = executions.reduce((sum, {trade}) => sum.add(trade.data.amountOut), new BN(0));
if (executions.length === 1) {
return swapHandler({who, assetIn, assetOut, amountIn, amountOut});
} else {
return swapHandler({
who,
assetIn,
assetOut,
amountIn,
amountOut
}, `split over ${executions.length} swaps`);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/handlers/omnipool.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function buyHandler({event}) {
async function liquidityAddedHandler({event}) {
const {who, assetId: currencyId, amount} = event.data;
const added = {currencyId, amount};
const value = currencyId.toString() !== usdCurrencyId ? usdValue(added) : null;
const value = currencyId.toString() !== usdCurrencyId ? await usdValue(added) : null;
const message = `💦 omnipool hydrated with **${formatAmount(added)}**${formatUsdValue(value)} by ${formatAccount(who, isWhale(value))}`;
broadcast(message);
}
Expand All @@ -43,7 +43,7 @@ async function liquidityRemovedHandler({event, siblings}) {
lrna = ' + ' + formatAmount(asset);
asset = transfers[1].data;
}
const value = currencyId.toString() !== usdCurrencyId ? usdValue(asset) : null;
const value = currencyId.toString() !== usdCurrencyId ? await usdValue(asset) : null;
const message = `🚰 omnipool dehydrated of **${formatAmount(asset)}**${formatUsdValue(value)}${lrna} by ${formatAccount(who, isWhale(value))}`;
broadcast(message);
}
10 changes: 5 additions & 5 deletions src/handlers/referrals.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ async function transferHandler({event: {data: {amount}}, blockNumber}) {
}
accrued += Number(amount);
if (blockNumber - since > window) {
report();
await report();
accrued = 0;
since = blockNumber;
}
}

function report() {
async function report() {
if (accrued > 0) {
const amount = {amount: accrued, currencyId: 0};
const value = usdValue(amount);
const value = await usdValue(amount);
const message = `💸 **${formatAmount(amount)}**${formatUsdValue(value)} bought for rewards`;
broadcast(message);
}
Expand All @@ -39,8 +39,8 @@ function report() {
['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT',
'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM'
].forEach(sig =>
process.on(sig, () => {
report();
process.on(sig, async () => {
await report();
setTimeout(() => process.exit(0), 500);
}));

4 changes: 2 additions & 2 deletions src/handlers/stableswap.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function stableswapHandler(events) {
async function liquidityAddedHandler({event: {data: {who, poolId, shares, assets}}}) {
const share = {currencyId: poolId, amount: shares};
if (assets.length > 1) {
const value = usdValue(share);
const value = await usdValue(share);
const message = `💦 pool hydrated for **${formatAmount(share)}**${formatUsdValue(value)} shares by ${formatAccount(who, isWhale(value))}`
broadcast(message);
} else {
Expand All @@ -27,7 +27,7 @@ async function liquidityAddedHandler({event: {data: {who, poolId, shares, assets
async function liquidityRemovedHandler({event: {data: {who, poolId, shares, amounts}}}) {
const share = {currencyId: poolId, amount: shares};
if (amounts.length > 1) {
const value = usdValue(share);
const value = await usdValue(share);
const message = `🚰 pool dehydrated for **${formatAmount(share)}**${formatUsdValue(value)} shares by ${formatAccount(who, isWhale(value))}`
broadcast(message);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/transfers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function transfersHandler(events) {

async function transferredHandler({event}) {
const {from, to} = event.data;
const value = usdValue(event.data);
const value = await usdValue(event.data);
if (isWhale(value)) {
const message = `${formatAccount(from, true)} transferred **${formatAmount(event.data)}**${formatUsdValue(value)} to ${formatAccount(to, true)}`;
broadcast(message);
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/xyk.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function swapHandler({who, assetIn, assetOut, amountIn, amountOut},
const sold = {currencyId: assetIn, amount: amountIn};
const bought = {currencyId: assetOut, amount: amountOut};
recordPrice(sold, bought);
const value = usdValue(bought);
const value = await usdValue(bought);
let message = `${formatAccount(who, isWhale(value))} ${action} **${formatAmount(sold)}** for **${formatAmount(bought)}**`;
if (![assetIn, assetOut].map(id => id.toString()).includes(usdCurrencyId)) {
message += formatUsdValue(value);
Expand All @@ -43,7 +43,7 @@ async function liquidityAddedHandler({event}) {
const {who, assetA, assetB, amountA, amountB} = event.data;
const a = {amount: amountA, currencyId: assetA};
const b = {amount: amountB, currencyId: assetB};
const [va, vb] = [a, b].map(usdValue);
const [va, vb] = await Promise.all([a, b].map(usdValue));
const value = va && vb ? va + vb : null;
const message = `💦 liquidity added as **${formatAmount(a)}** + **${formatAmount(b)}**${formatUsdValue(value)} by ${formatAccount(who, isWhale(value))}`;
broadcast(message);
Expand Down
4 changes: 2 additions & 2 deletions src/utils/borrowers.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ export default class Borrowers {
handler(inner) {
return async payload => {
await inner(payload);
const {log: {args: {user}}, event: {data: {log: {address}}}, blockNumber} = payload;
try {
const {log: {args: {user}}, event: {data: {log: {address}}}, blockNumber} = payload;
await this.update(address.toHex(), user);
this.metrics.last_update_block.set(blockNumber);
} catch (e) {
console.error('failed to update borrower health', payload, e);
console.error('failed to update borrower health', address, e);
}
}
}
Expand Down

0 comments on commit a580885

Please sign in to comment.