Created
June 11, 2024 18:13
-
-
Save mfw78/1f2c6d926c7496d50b581ab11d01fa7f to your computer and use it in GitHub Desktop.
Show all orders spawning from the most recent drip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Order Details</title> | |
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"> | |
<script src="https://cdn.ethers.io/lib/ethers-5.7.2.umd.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | |
<style> | |
.loading-spinner { | |
display: none; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1 class="my-4">Order Details</h1> | |
<div class="loading-spinner" id="loading-spinner"> | |
<div class="spinner-border text-primary" role="status"> | |
<span class="sr-only">Loading...</span> | |
</div> | |
</div> | |
<table class="table table-bordered" id="order-table"> | |
<thead class="thead-dark"> | |
<tr> | |
<th>Order UID</th> | |
<th>Sell Amount</th> | |
<th>Sell Token</th> | |
<th>Buy Amount</th> | |
<th>Buy Token</th> | |
<th>Status</th> | |
</tr> | |
</thead> | |
<tbody></tbody> | |
</table> | |
<h2>Total Buy Amount: <span id="total-buy-amount">0</span> <span id="buy-token-symbol"></span></h2> | |
</div> | |
<script type="text/javascript"> | |
const provider = new ethers.providers.JsonRpcProvider("https://rpc.mevblocker.io"); | |
const multicallAddress = "0xcA11bde05977b3631167028862bE2a173976CA11"; // Multicall3 address | |
async function getRecentBlocks() { | |
const currentBlock = await provider.getBlockNumber(); | |
const blockInterval = Math.floor(7 * 24 * 60 * 60 / 12); // 7 days worth of blocks | |
const startBlock = currentBlock - blockInterval; | |
return { startBlock, currentBlock }; | |
} | |
async function getSettlementEvent(startBlock, endBlock) { | |
const settlementContract = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"; | |
const safeSolver = "0x423cEc87f19F0778f549846e0801ee267a917935"; | |
const filter = { | |
address: settlementContract, | |
fromBlock: startBlock, | |
toBlock: endBlock, | |
topics: [ | |
ethers.utils.id("Settlement(address)"), | |
ethers.utils.hexZeroPad(safeSolver, 32) | |
] | |
}; | |
const events = await provider.getLogs(filter); | |
return events.length > 0 ? events[events.length - 1] : null; | |
} | |
async function getPreSignatureEvents(txHash) { | |
const txReceipt = await provider.getTransactionReceipt(txHash); | |
const preSignatureEvents = txReceipt.logs.filter(log => | |
log.topics[0] === ethers.utils.id("PreSignature(address,bytes,bool)") | |
); | |
return preSignatureEvents.map(event => ({ | |
owner: ethers.utils.defaultAbiCoder.decode(['address'], event.topics[1])[0], | |
orderUid: ethers.utils.defaultAbiCoder.decode(['bytes'], event.data)[0] | |
})); | |
} | |
async function getOrderDetails(orderUid) { | |
const response = await axios.get(`https://api.cow.fi/mainnet/api/v1/orders/${orderUid}`); | |
return response.data; | |
} | |
async function getTokenDetailsMulticall(tokenAddresses) { | |
const multicallContract = new ethers.Contract(multicallAddress, [ | |
"function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)" | |
], provider); | |
const calls = tokenAddresses.flatMap(tokenAddress => [ | |
{ target: tokenAddress, callData: ethers.utils.id("symbol()").slice(0, 10) }, | |
{ target: tokenAddress, callData: ethers.utils.id("decimals()").slice(0, 10) } | |
]); | |
const [, returnData] = await multicallContract.aggregate(calls); | |
const tokenDetails = {}; | |
for (let i = 0; i < tokenAddresses.length; i++) { | |
const symbol = ethers.utils.defaultAbiCoder.decode(["string"], returnData[2 * i])[0]; | |
const decimals = ethers.utils.defaultAbiCoder.decode(["uint256"], returnData[2 * i + 1])[0]; | |
tokenDetails[tokenAddresses[i]] = { symbol, decimals }; | |
} | |
return tokenDetails; | |
} | |
async function main() { | |
document.getElementById('loading-spinner').style.display = 'flex'; | |
const { startBlock, currentBlock } = await getRecentBlocks(); | |
const settlementEvent = await getSettlementEvent(startBlock, currentBlock); | |
if (settlementEvent) { | |
const txHash = settlementEvent.transactionHash; | |
const preSignatureEvents = await getPreSignatureEvents(txHash); | |
const orders = []; | |
const tokenAddresses = new Set(); | |
let buyToken = null; | |
for (const event of preSignatureEvents) { | |
const orderDetails = await getOrderDetails(event.orderUid); | |
orders.push({ | |
orderUid: event.orderUid, | |
buyAmount: orderDetails.buyAmount, | |
buyToken: orderDetails.buyToken, | |
sellAmount: orderDetails.sellAmount, | |
sellToken: orderDetails.sellToken, | |
status: orderDetails.status | |
}); | |
tokenAddresses.add(orderDetails.buyToken); | |
tokenAddresses.add(orderDetails.sellToken); | |
if (!buyToken) { | |
buyToken = orderDetails.buyToken; | |
} else if (buyToken !== orderDetails.buyToken) { | |
console.error("Different buyTokens found in the orders."); | |
return; | |
} | |
} | |
const tokenDetails = await getTokenDetailsMulticall([...tokenAddresses]); | |
displayOrders(orders, tokenDetails); | |
calculateTotalBuyAmount(orders, tokenDetails[buyToken]); | |
} else { | |
console.log("No settlement events found in the last 7 days."); | |
} | |
document.getElementById('loading-spinner').style.display = 'none'; | |
} | |
function displayOrders(orders, tokenDetails) { | |
const tableBody = document.getElementById('order-table').querySelector('tbody'); | |
tableBody.innerHTML = ''; | |
orders.forEach(order => { | |
const buyTokenDetails = tokenDetails[order.buyToken]; | |
const sellTokenDetails = tokenDetails[order.sellToken]; | |
const buyAmount = ethers.utils.formatUnits(order.buyAmount, buyTokenDetails.decimals); | |
const sellAmount = ethers.utils.formatUnits(order.sellAmount, sellTokenDetails.decimals); | |
const uid = order.orderUid; | |
const orderLink = `https://explorer.cow.fi/orders/${uid}`; | |
const row = document.createElement('tr'); | |
row.innerHTML = ` | |
<td><a href="${orderLink}" target="_blank">${uid.slice(0, 10)}...${uid.slice(uid.length - 10)}</a></td> | |
<td>${parseFloat(sellAmount).toFixed(6)}</td> | |
<td>${sellTokenDetails.symbol}</td> | |
<td>${parseFloat(buyAmount).toFixed(6)}</td> | |
<td>${buyTokenDetails.symbol}</td> | |
<td>${order.status}</td> | |
`; | |
tableBody.appendChild(row); | |
}); | |
} | |
function calculateTotalBuyAmount(orders, buyTokenDetails) { | |
let totalBuyAmount = ethers.BigNumber.from(0); | |
orders.forEach(order => { | |
totalBuyAmount = totalBuyAmount.add(ethers.BigNumber.from(order.buyAmount)); | |
}); | |
const totalBuyAmountFormatted = ethers.utils.formatUnits(totalBuyAmount, buyTokenDetails.decimals); | |
document.getElementById('total-buy-amount').innerText = parseFloat(totalBuyAmountFormatted).toFixed(6); | |
document.getElementById('buy-token-symbol').innerText = buyTokenDetails.symbol; | |
} | |
main(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment