@guaritos/tracer-engine
Version:
A highly performant and scalable multi-hop, time-aware tracer for account-based blockchain transactions, designed for off-chain risk assessment and flow analysis.
82 lines • 3.29 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TracerEngine = exports.TraceResult = void 0;
const subgraph_1 = require("./items/subgraph");
const ttr_1 = require("./strategies/ttr");
const pino = require('pino');
class TraceResult {
constructor() {
this.strategy_snap_shot_items = {};
this.rank_items = {};
}
}
exports.TraceResult = TraceResult;
class TracerEngine {
constructor(source, options) {
this.class_name = "TracerEngine";
this.log = pino({
transport: {
target: 'pino-pretty'
}
});
this.enable_log = false;
this.strategy = new ttr_1.TTRRedirect(source);
if (options && options.enable_log)
this.enable_log = options.enable_log;
}
*push_pop(node, edges) {
this.enable_log && this.log.info(`[${this.class_name}] Pushing: ${node}, with ${edges.length} transfer`);
this.strategy.push(node, edges);
// generate a strategy context item
const snapshot_data = this.strategy.get_context_snapshot();
yield new subgraph_1.StrategySnapshotItem(snapshot_data);
const ranks = this.strategy.get_node_rank();
yield new subgraph_1.RankItem(ranks);
// pop account from the strategy
const [popped_node, context_kwargs] = this.strategy.pop();
if (popped_node === null) {
return;
}
this.enable_log && this.log.info(`[${this.class_name}] Popping: ${popped_node}, with args {residual: ${context_kwargs.residual}, allow_all_token: ${context_kwargs.allow_all_tokens}}`);
let pop_item = new subgraph_1.PopItem(popped_node);
pop_item.set_context_kwargs(context_kwargs);
yield pop_item;
}
async startTrace(get_edges, trace_options) {
let result = new TraceResult();
let depth = 0;
const edges = await get_edges(this.strategy.source, trace_options?.filters);
const start_time = Date.now();
let data = this.push_pop(this.strategy.source, edges);
let curr = data.next();
while (!curr.done) {
if (trace_options && trace_options.max_depth && depth > trace_options.max_depth) {
break;
}
// StrategySnapshotItem
result.strategy_snap_shot_items = curr.value.data;
// RankItem
curr = data.next();
result.rank_items = curr.value.data;
// PopItem or empty return;
curr = data.next();
if (curr.done) {
break;
}
else if (curr.value instanceof subgraph_1.PopItem) {
const node = curr.value.node;
if (!node)
break;
data = this.push_pop(node, await get_edges(node, trace_options?.filters));
curr = data.next();
}
depth++;
}
const end_time = Date.now();
const time_elapsed = end_time - start_time;
this.enable_log && this.log.info(`${this.class_name} Finish tracing after ${new Date(time_elapsed).toISOString().slice(11, 19)}`);
return result;
}
}
exports.TracerEngine = TracerEngine;
//# sourceMappingURL=tracer_engine.js.map