@celo/explorer
Version:
Celo's block explorer consumer
136 lines (135 loc) • 5.26 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogExplorer = exports.newLogExplorer = void 0;
const viem_1 = require("viem");
const base_1 = require("./base");
function newLogExplorer(kit) {
return __awaiter(this, void 0, void 0, function* () {
return new LogExplorer(kit, yield (0, base_1.obtainKitContractDetails)(kit));
});
}
exports.newLogExplorer = newLogExplorer;
class LogExplorer {
constructor(kit, contractDetails) {
this.kit = kit;
this.contractDetails = contractDetails;
this.addressMapping = (0, base_1.mapFromPairs)(contractDetails.map((cd) => [
cd.address,
{
details: cd,
logMapping: (0, base_1.mapFromPairs)(cd.jsonInterface
.filter((ad) => ad.type === 'event')
.map((ad) => [ad.signature, ad])),
},
]));
for (const cd of contractDetails) {
const fnMapping = new Map();
for (const abiDef of cd.jsonInterface) {
if (abiDef.type === 'event') {
fnMapping.set(abiDef.signature, abiDef);
}
}
this.addressMapping.set(cd.address, {
details: cd,
logMapping: fnMapping,
});
}
}
fetchTxReceipt(txhash) {
return __awaiter(this, void 0, void 0, function* () {
try {
return yield this.kit.connection.viemClient.getTransactionReceipt({
hash: txhash,
});
}
catch (_a) {
return null;
}
});
}
getKnownLogs(tx) {
const res = [];
for (const log of tx.logs || []) {
const event = this.tryParseLog(log);
if (event != null) {
res.push(event);
}
}
return res;
}
tryParseLog(log) {
if (log.topics.length === 0) {
return null;
}
const contractMapping = this.addressMapping.get(log.address);
if (contractMapping == null) {
return null;
}
const logSignature = log.topics[0];
if (logSignature == null) {
return null;
}
const matchedAbi = contractMapping.logMapping.get(logSignature);
if (matchedAbi == null) {
return null;
}
const eventInputs = (matchedAbi.inputs || []).map((input) => {
var _a;
return (Object.assign(Object.assign({}, input), { indexed: (_a = input.indexed) !== null && _a !== void 0 ? _a : false }));
});
const eventAbi = [
{ type: 'event', name: matchedAbi.name || 'Event', inputs: eventInputs },
];
// toEventSelector expands tuple components into the canonical signature;
// joining raw input types would hash 'Event(tuple,...)' and never match
const eventSigHash = (0, viem_1.toEventSelector)(eventAbi[0]);
const fullTopics = [eventSigHash, ...log.topics.slice(1)];
try {
const result = (0, viem_1.decodeEventLog)({
abi: eventAbi,
data: (log.data || '0x'),
topics: fullTopics,
});
const decoded = Object.assign({}, result.args);
// bigint to string for backward compat
for (const key of Object.keys(decoded)) {
if (typeof decoded[key] === 'bigint')
decoded[key] = decoded[key].toString();
}
// pending logs carry null block/index fields — Number(null) would
// silently report block 0
if (log.blockNumber == null || log.logIndex == null || log.transactionIndex == null) {
return null;
}
const logEvent = {
address: log.address,
blockHash: log.blockHash,
blockNumber: Number(log.blockNumber),
logIndex: log.logIndex,
transactionIndex: log.transactionIndex,
transactionHash: log.transactionHash,
returnValues: decoded,
event: matchedAbi.name,
signature: logSignature,
raw: {
data: log.data || '',
topics: log.topics || [],
},
};
return logEvent;
}
catch (_a) {
return null;
}
}
}
exports.LogExplorer = LogExplorer;