|
export const client = createPublicClient({ |
|
chain: mainnet, |
|
transport: transport, |
|
}); |
|
|
|
export async function delay(ms) { |
|
return new Promise((resolve) => setTimeout(resolve, ms)); |
|
} |
|
|
|
export async function getBlobsFromTx(tx, hostname = "eth.blockscout.com") { |
|
// const json = await fetch(`https://${hostname}/api/v2/transactions/` + id) |
|
// .then((x) => x.json()); |
|
await delay(15_000); |
|
|
|
// console.log(json) |
|
const hashes = tx.blobVersionedHashes; |
|
|
|
const getBlob = async (hash) => { |
|
const res = await fetch(`https://${hostname}/api/v2/blobs/` + hash).then((x) => x.json()); |
|
res.blob_hash = hash; |
|
|
|
// the 0-th is the first transaction that this specific blob content/data is found in, |
|
// if the same exact blob content is found multiple times, there will be more transaction in that array |
|
res.transaction_hash = res.transaction_hashes[0].transaction_hash; |
|
|
|
res.duplicates = res.transaction_hashes.slice(1).map((x) => x.transaction_hash); |
|
|
|
delete res.transaction_hashes; |
|
delete res.hash; |
|
|
|
return res; |
|
}; |
|
|
|
if (hashes.length === 1) { |
|
const res = await getBlob(hashes[0]); |
|
|
|
return [res]; |
|
} else if (hashes.length > 1) { |
|
const data = await Promise.all( |
|
hashes.map(async (hash) => { |
|
const blob = await getBlob(hash); |
|
return blob; |
|
}), |
|
); |
|
|
|
return data; |
|
} |
|
|
|
return []; |
|
} |
|
|
|
export async function trackBlobs(handler, log = false) { |
|
client.watchBlocks({ |
|
pollingInterval: 5_500, |
|
emitMissed: true, |
|
blockTag: "latest", |
|
includeTransactions: true, |
|
onBlock: async (block) => { |
|
const blobTransactions = block.transactions.filter((tx) => tx.type === "eip4844"); |
|
const blobsTxs = await Promise.all( |
|
blobTransactions.map(async (tx) => { |
|
// console.log(tx) |
|
tx.blobs = await getBlobsFromTx(tx); |
|
|
|
return tx; |
|
}), |
|
); |
|
|
|
const slotHash = block.parentBeaconBlockRoot; |
|
const blobs = blobsTxs.map((x) => x.blobs).flat(); |
|
|
|
if (log) { |
|
console.log(blobsTxs.map((x) => x.blobs).flat()); |
|
console.log("Blob Txs:", blobsTxs.length); |
|
console.log( |
|
"Blobs Count:", |
|
blobsTxs.reduce((acc, x) => acc + x.blobVersionedHashes.length, 0), |
|
); |
|
console.log("Block:", block.number); |
|
console.log("====================\n"); |
|
} |
|
|
|
handler({ block, blobTransactions: blobsTxs, slotHash, blobs }); |
|
}, |
|
}); |
|
} |
|
|
|
export function onlyDataURIBlobs({ blobs }, log = false) { |
|
// convert blobs into proper hex data values |
|
const blobsDataHexed = blobs.map((x) => fromBlobs({ blobs: [x.blob_data] })); |
|
|
|
if (blobsDataHexed.length > 0 && blobsDataHexed[0].startsWith('0x646174613a')) { |
|
// combine all hex data values into one |
|
const combinedDataHex = '0x' + (blobsDataHexed.map(x => x.slice(2)).join('')); |
|
|
|
// convert to bytes (uint8array) |
|
const dataBytes = hexToBytes(combinedDataHex as `0x${string}`); |
|
|
|
if (log) { |
|
console.log('bytes:', dataBytes.length); |
|
console.log('data uri:', new TextDecoder().decode(dataBytes)); |
|
} |
|
|
|
return { dataBytes, combinedDataHex } |
|
} |
|
|
|
return {}; |
|
} |