Skip to content

Instantly share code, notes, and snippets.

@mfw78
Created June 11, 2024 18:13
Show Gist options
  • Save mfw78/1f2c6d926c7496d50b581ab11d01fa7f to your computer and use it in GitHub Desktop.
Save mfw78/1f2c6d926c7496d50b581ab11d01fa7f to your computer and use it in GitHub Desktop.
Show all orders spawning from the most recent drip
<!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