Skip to content

Commit

Permalink
Fix partially all the typings. The code is a not follow any logic so …
Browse files Browse the repository at this point in the history
…i clean more i could (#2905)
  • Loading branch information
AIFlowML authored Jan 28, 2025
1 parent 4251e6c commit c15f4c4
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 130 deletions.
4 changes: 2 additions & 2 deletions packages/plugin-arbitrage/src/actions/arbitrageAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ export const executeArbitrageAction: Action = {
similes: ["TRADE_ARBITRAGE", "RUN_ARBITRAGE"],
description: "Execute arbitrage trades across markets",

validate: async (runtime: IAgentRuntime, message: Memory) => {
validate: async (runtime: IAgentRuntime, _message: Memory) => {
// Validate settings are present
return runtime.getSetting("arbitrage.walletPrivateKey") !== undefined;
},

handler: async (runtime: IAgentRuntime, message: Memory) => {
handler: async (runtime: IAgentRuntime, _message: Memory) => {
const service = runtime.getService(ServiceType.ARBITRAGE) as ArbitrageService;
const markets = await service.evaluateMarkets();

Expand Down
226 changes: 120 additions & 106 deletions packages/plugin-arbitrage/src/core/Arbitrage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { Contract } from "@ethersproject/contracts";
import { Wallet } from "@ethersproject/wallet";
import { Provider } from "@ethersproject/providers";
import { FlashbotsBundleProvider } from "@flashbots/ethers-provider-bundle";
import { WETH_ADDRESS } from "././addresses";
// import { WETH_ADDRESS } from "././addresses";
import { EthMarket } from "././EthMarket";
import { ETHER, bigNumberToDecimal } from "./utils";
// import { ETHER, bigNumberToDecimal } from "./utils";
import { EthMarket as EthMarketType, CrossedMarketDetails, MarketsByToken, MarketType, BuyCalls } from "././types";
import { TransactionResponse } from "@ethersproject/providers";
import { DEFAULT_THRESHOLDS, MarketThresholds } from '../config/thresholds';
import { MarketsByToken as ImportedMarketsByToken, CrossedMarketDetails as ImportedCrossedMarketDetails } from "../type";
// import { TransactionResponse } from "@ethersproject/providers";
// import { DEFAULT_THRESHOLDS, MarketThresholds } from '../config/thresholds';
// import { MarketsByToken as ImportedMarketsByToken, CrossedMarketDetails as ImportedCrossedMarketDetails } from "../type";
export { MarketsByToken, EthMarket, CrossedMarketDetails } from '././types';

export interface BundleEntry {
Expand All @@ -24,12 +24,17 @@ export interface BundleEntry {
signer: string,
}

let CFMM = {
interface ArbitrageTransaction {
hash: string;
wait: () => Promise<{ blockNumber: number }>;
}

const CFMM = {
reserves: {
x: BigNumber.from(0),
y: BigNumber.from(0),
},
getOutputAmount: function (inputAmount: BigNumber, inputReserve: BigNumber, outputReserve: BigNumber) {
getOutputAmount: (inputAmount: BigNumber, inputReserve: BigNumber, outputReserve: BigNumber) => {
const inputAmountWithFee = inputAmount.mul(997);
const numerator = inputAmountWithFee.mul(outputReserve);
const denominator = inputReserve.mul(1000).add(inputAmountWithFee);
Expand All @@ -38,17 +43,17 @@ let CFMM = {
tradingFee: BigNumber.from("3000"),
};

let acceptTrade = (R: BigNumber, deltaPlus: number, deltaMinus: number) => {
let tradingFunctionResult = CFMM.getOutputAmount(R.sub(CFMM.tradingFee.mul(deltaMinus)).sub(deltaPlus), CFMM.reserves.x, CFMM.reserves.y);
let tradingFunctionResult2 = CFMM.getOutputAmount(R, CFMM.reserves.x, CFMM.reserves.y);
const acceptTrade = (R: BigNumber, deltaPlus: number, deltaMinus: number) => {
const tradingFunctionResult = CFMM.getOutputAmount(R.sub(CFMM.tradingFee.mul(deltaMinus)).sub(deltaPlus), CFMM.reserves.x, CFMM.reserves.y);
const tradingFunctionResult2 = CFMM.getOutputAmount(R, CFMM.reserves.x, CFMM.reserves.y);
console.log(`acceptTrade: tradingFunctionResult = ${tradingFunctionResult}, tradingFunctionResult2 = ${tradingFunctionResult2}`);
return tradingFunctionResult.gte(tradingFunctionResult2) && R.sub(CFMM.tradingFee.mul(deltaMinus)).sub(deltaPlus).gte(0);
};


export const dualDecomposition = (referencePrices: string | any[], objectiveFunction: (arg0: any) => any, penaltyVector: number[]) => {
console.log("Entering dualDecomposition");
let T = [];
const T = [];
for (let i = 0; i < referencePrices.length; i++) {
let deltaPlus = referencePrices[i].cumulativePrice;
let deltaMinus = Math.min(referencePrices[i].cumulativePrice, 0);
Expand Down Expand Up @@ -130,60 +135,60 @@ export async function calculateOptimalVolume(

return optimalVolume;
}
// Define the bisection search
// Define the bisection search
let bisectionSearch = (referencePrices: Array<{cumulativePrice: number, marketCount: number}>, objectiveFunction: (arg0: number) => number, penaltyVector: number[]) => {
console.log("Entering bisectionSearch");
let left = 0;
let right = referencePrices.length - 1;
let tolerance = 1e-6;
let psi;

while (right - left > tolerance) {
let mid = Math.floor((left + right) / 2);
let midValue = objectiveFunction(mid);
let penaltyResult = penaltyVector[mid] * mid;

if (midValue > penaltyResult) {
left = mid;
psi = mid;
} else {
right = mid;
}
}
console.log(`bisectionSearch: final psi = ${psi}`);

return psi;
};

let swapMarketArbitrage = (referencePrices: Array<{cumulativePrice: number, marketCount: number}> = [], objectiveFunction: (price: number) => number, penaltyVector: number[]) => {
// Initialize the dual variable ν
console.log("Entering swapMarketArbitrage");

let nu = 0;

// Use bisection or ternary search to solve for the vector Ψ
// Assuming that bisectionSearch accepts a number, not an array
let psi = bisectionSearch(referencePrices, objectiveFunction, penaltyVector);

// Iterate through the ∆i with i = 1, . . . , m
for (let i = 0; i < referencePrices.length; i++) {
// Compute the objective function U(Ψ)
// Ensure psi is used correctly as an index
if (psi !== undefined && psi >= 0 && psi < referencePrices.length) {
const objectiveFunctionResult = objectiveFunction(referencePrices[psi].cumulativePrice);

// Compute the linear penalty in the objective
let penaltyResult = penaltyVector[i] * nu;

// Update the dual variable ν
nu = Math.max(nu, (objectiveFunctionResult - penaltyResult));
}
}
// Return the dual variable ν
console.log(`swapMarketArbitrage: final nu = ${nu}`);
return nu;
};
// // Define the bisection search
// // Define the bisection search
// let bisectionSearch = (referencePrices: Array<{cumulativePrice: number, marketCount: number}>, objectiveFunction: (arg0: number) => number, penaltyVector: number[]) => {
// console.log("Entering bisectionSearch");
// let left = 0;
// let right = referencePrices.length - 1;
// let tolerance = 1e-6;
// let psi;

// while (right - left > tolerance) {
// let mid = Math.floor((left + right) / 2);
// let midValue = objectiveFunction(mid);
// let penaltyResult = penaltyVector[mid] * mid;

// if (midValue > penaltyResult) {
// left = mid;
// psi = mid;
// } else {
// right = mid;
// }
// }
// console.log(`bisectionSearch: final psi = ${psi}`);

// return psi;
// };

// let swapMarketArbitrage = (referencePrices: Array<{cumulativePrice: number, marketCount: number}> = [], objectiveFunction: (price: number) => number, penaltyVector: number[]) => {
// // Initialize the dual variable ν
// console.log("Entering swapMarketArbitrage");

// let nu = 0;

// // Use bisection or ternary search to solve for the vector Ψ
// // Assuming that bisectionSearch accepts a number, not an array
// let psi = bisectionSearch(referencePrices, objectiveFunction, penaltyVector);

// // Iterate through the ∆i with i = 1, . . . , m
// for (let i = 0; i < referencePrices.length; i++) {
// // Compute the objective function U(Ψ)
// // Ensure psi is used correctly as an index
// if (psi !== undefined && psi >= 0 && psi < referencePrices.length) {
// const objectiveFunctionResult = objectiveFunction(referencePrices[psi].cumulativePrice);

// // Compute the linear penalty in the objective
// let penaltyResult = penaltyVector[i] * nu;

// // Update the dual variable ν
// nu = Math.max(nu, (objectiveFunctionResult - penaltyResult));
// }
// }
// // Return the dual variable ν
// console.log(`swapMarketArbitrage: final nu = ${nu}`);
// return nu;
// };

export async function getGasPriceInfo(provider: Provider): Promise<{ currentGasPrice: BigNumber, avgGasPrice: BigNumber }> {
console.log("Entering getGasPriceInfo");
Expand All @@ -205,7 +210,7 @@ export async function getGasPriceInfo(provider: Provider): Promise<{ currentGasP
let transactionCountInBlock = 0;
for (const txHash of transactions) {
const tx = await provider.getTransaction(txHash);
if (tx && tx.gasPrice) {
if (tx?.gasPrice) {
totalGasPriceInBlock = totalGasPriceInBlock.add(tx.gasPrice);
transactionCountInBlock++;
}
Expand All @@ -231,31 +236,40 @@ export async function ensureHigherEffectiveGasPrice(transactionGasPrice: BigNumb
console.log(`ensureHigherEffectiveGasPrice: transactionGasPrice = ${transactionGasPrice}, tailTransactionGasPrice = ${tailTransactionGasPrice}, effectiveGasPrice = ${effectiveGasPrice}`);
return effectiveGasPrice;
}
async function checkBundleGas(bundleGas: BigNumber): Promise<boolean> {
const isValid = bundleGas.gte(42000);
console.log(`checkBundleGas: bundleGas = ${bundleGas}, isValid = ${isValid}`);
return isValid;

// async function checkBundleGas(bundleGas: BigNumber): Promise<boolean> {
// const isValid = bundleGas.gte(42000);
// console.log(`checkBundleGas: bundleGas = ${bundleGas}, isValid = ${isValid}`);
// return isValid;
// }
interface Block {
bundleGasPrice: BigNumber;
}

interface BlocksApi {
getRecentBlocks: () => Promise<Block[]>;
}
export async function monitorCompetingBundlesGasPrices(blocksApi: { getRecentBlocks: () => any; }): Promise<Array<BigNumber>> {

export async function monitorCompetingBundlesGasPrices(blocksApi: BlocksApi): Promise<Array<BigNumber>> {
console.log("Entering monitorCompetingBundlesGasPrices");
const recentBlocks = await blocksApi.getRecentBlocks();
const competingBundlesGasPrices = recentBlocks.map((block: { bundleGasPrice: any; }) => block.bundleGasPrice);
const competingBundlesGasPrices = recentBlocks.map((block: Block) => block.bundleGasPrice);
console.log(`monitorCompetingBundlesGasPrices: competingBundlesGasPrices = ${competingBundlesGasPrices}`);
return competingBundlesGasPrices;
}
export class Arbitrage {
constructor(
private wallet: any,
private flashbotsProvider: any,
private bundleExecutorContract: any
) {}
constructor(
private wallet: Wallet,
private flashbotsProvider: FlashbotsBundleProvider,
private bundleExecutorContract: Contract
) {}

async evaluateMarkets(marketsByToken: MarketsByToken): Promise<CrossedMarketDetails[]> {
async evaluateMarkets(_marketsByToken: MarketsByToken): Promise<CrossedMarketDetails[]> {
// Implement market evaluation logic
return [];
}

async takeCrossedMarkets(markets: CrossedMarketDetails[], currentBlock: number, maxAttempts: number): Promise<void> {
async takeCrossedMarkets(_markets: CrossedMarketDetails[], _currentBlock: number, _maxAttempts: number): Promise<void> {
// Implement arbitrage execution logic
}

Expand All @@ -279,9 +293,9 @@ export class Arbitrage {
sourceRouter: string,
targetRouter: string,
tokenIn: string,
tokenOut: string,
_tokenOut: string,
amountIn: BigNumber
): Promise<any> {
): Promise<ArbitrageTransaction> {
// Create the arbitrage transaction
const markets: CrossedMarketDetails[] = [{
marketPairs: [{
Expand All @@ -301,12 +315,12 @@ export class Arbitrage {
// Return a mock transaction response for now
// In a real implementation, this should return the actual transaction
return {
hash: "0x" + Math.random().toString(16).slice(2),
hash: `0x${Math.random().toString(16).slice(2)}`,
wait: async () => ({ blockNumber: await this.getCurrentBlock() })
};
}

private async getMarketForDex(dexAddress: string): Promise<EthMarket | null> {
private async getMarketForDex(_dexAddress: string): Promise<EthMarket | null> {
// This should be implemented to return the appropriate market instance
// based on the DEX address
return null;
Expand Down Expand Up @@ -341,26 +355,26 @@ export class Arbitrage {
}
}

async function fetchWETHBalance(address: string, provider: Provider, retries = 5, delayMs = 500): Promise<BigNumber | null> {
const WETH_CONTRACT_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const ABI = [
"function balanceOf(address owner) view returns (uint256)"
];
const contract = new Contract(WETH_CONTRACT_ADDRESS, ABI, provider);

for (let attempt = 1; attempt <= retries; attempt++) {
try {
const balance: BigNumber = await contract.balanceOf(address);
return balance;
} catch (error: any) {
console.error(`Attempt ${attempt} - Failed to fetch WETH balance for address ${address}:`, error.message);
if (attempt < retries) {
await new Promise(res => setTimeout(res, delayMs * attempt));
} else {
console.error(`All ${retries} attempts failed for address ${address}`);
return null;
}
}
}
return null;
}
// async function fetchWETHBalance(address: string, provider: Provider, retries = 5, delayMs = 500): Promise<BigNumber | null> {
// const WETH_CONTRACT_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
// const ABI = [
// "function balanceOf(address owner) view returns (uint256)"
// ];
// const contract = new Contract(WETH_CONTRACT_ADDRESS, ABI, provider);

// for (let attempt = 1; attempt <= retries; attempt++) {
// try {
// const balance: BigNumber = await contract.balanceOf(address);
// return balance;
// } catch (error: any) {
// console.error(`Attempt ${attempt} - Failed to fetch WETH balance for address ${address}:`, error.message);
// if (attempt < retries) {
// await new Promise(res => setTimeout(res, delayMs * attempt));
// } else {
// console.error(`All ${retries} attempts failed for address ${address}`);
// return null;
// }
// }
// }
// return null;
// }
14 changes: 7 additions & 7 deletions packages/plugin-arbitrage/src/core/EthMarket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,37 @@ export abstract class EthMarket implements MarketType {
public protocol: any
) {}

async getReserves(tokenAddress: string): Promise<BigNumber> {
async getReserves(_tokenAddress: string): Promise<BigNumber> {
// Implementation
return BigNumber.from(0);
}

async getTokensOut(tokenIn: string, tokenOut: string, amountIn: BigNumber): Promise<BigNumber> {
async getTokensOut(_tokenIn: string, _tokenOut: string, _amountIn: BigNumber): Promise<BigNumber> {
// Implementation
return BigNumber.from(0);
}

async getPriceImpact(tokenAddress: string, tradeSize: BigNumber): Promise<BigNumber> {
async getPriceImpact(_tokenAddress: string, _tradeSize: BigNumber): Promise<BigNumber> {
// Implementation
return BigNumber.from(0);
}

async getTradingFee(tokenAddress: string): Promise<BigNumber> {
async getTradingFee(_tokenAddress: string): Promise<BigNumber> {
// Implementation
return BigNumber.from(0);
}

async getBalance(tokenAddress: string): Promise<BigNumber> {
async getBalance(_tokenAddress: string): Promise<BigNumber> {
// Implementation
return BigNumber.from(0);
}

async sellTokens(tokenAddress: string, volume: BigNumber, recipient: string): Promise<string> {
async sellTokens(_tokenAddress: string, _volume: BigNumber, _recipient: string): Promise<string> {
// Implementation
return "";
}

async sellTokensToNextMarket(tokenAddress: string, volume: BigNumber, nextMarket: MarketType): Promise<BuyCalls> {
async sellTokensToNextMarket(_tokenAddress: string, _volume: BigNumber, _nextMarket: MarketType): Promise<BuyCalls> {
// Implementation
return { targets: [], data: [] };
}
Expand Down
Loading

0 comments on commit c15f4c4

Please sign in to comment.