@xdc.org/interaction-detector 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +767 -0
- package/dist/checkpoint/checkpoint.d.ts +32 -0
- package/dist/checkpoint/checkpoint.d.ts.map +1 -0
- package/dist/checkpoint/checkpoint.js +68 -0
- package/dist/checkpoint/checkpoint.js.map +1 -0
- package/dist/decoder/abi-registry.d.ts +49 -0
- package/dist/decoder/abi-registry.d.ts.map +1 -0
- package/dist/decoder/abi-registry.js +88 -0
- package/dist/decoder/abi-registry.js.map +1 -0
- package/dist/decoder/event-decoder.d.ts +31 -0
- package/dist/decoder/event-decoder.d.ts.map +1 -0
- package/dist/decoder/event-decoder.js +142 -0
- package/dist/decoder/event-decoder.js.map +1 -0
- package/dist/explorer/explorer-client.d.ts +65 -0
- package/dist/explorer/explorer-client.d.ts.map +1 -0
- package/dist/explorer/explorer-client.js +164 -0
- package/dist/explorer/explorer-client.js.map +1 -0
- package/dist/explorer/rate-limiter.d.ts +31 -0
- package/dist/explorer/rate-limiter.d.ts.map +1 -0
- package/dist/explorer/rate-limiter.js +79 -0
- package/dist/explorer/rate-limiter.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/rpc/rpc-client.d.ts +70 -0
- package/dist/rpc/rpc-client.d.ts.map +1 -0
- package/dist/rpc/rpc-client.js +136 -0
- package/dist/rpc/rpc-client.js.map +1 -0
- package/dist/rpc/ws-manager.d.ts +27 -0
- package/dist/rpc/ws-manager.d.ts.map +1 -0
- package/dist/rpc/ws-manager.js +161 -0
- package/dist/rpc/ws-manager.js.map +1 -0
- package/dist/scanner/block-scanner.d.ts +45 -0
- package/dist/scanner/block-scanner.d.ts.map +1 -0
- package/dist/scanner/block-scanner.js +180 -0
- package/dist/scanner/block-scanner.js.map +1 -0
- package/dist/tracer/call-tree-parser.d.ts +25 -0
- package/dist/tracer/call-tree-parser.d.ts.map +1 -0
- package/dist/tracer/call-tree-parser.js +80 -0
- package/dist/tracer/call-tree-parser.js.map +1 -0
- package/dist/tracer/state-diff-parser.d.ts +13 -0
- package/dist/tracer/state-diff-parser.d.ts.map +1 -0
- package/dist/tracer/state-diff-parser.js +70 -0
- package/dist/tracer/state-diff-parser.js.map +1 -0
- package/dist/tracer/transaction-tracer.d.ts +52 -0
- package/dist/tracer/transaction-tracer.d.ts.map +1 -0
- package/dist/tracer/transaction-tracer.js +107 -0
- package/dist/tracer/transaction-tracer.js.map +1 -0
- package/dist/types/index.d.ts +262 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/address.d.ts +29 -0
- package/dist/utils/address.d.ts.map +1 -0
- package/dist/utils/address.js +49 -0
- package/dist/utils/address.js.map +1 -0
- package/dist/utils/format.d.ts +20 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +53 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +58 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/watcher/contract-watcher.d.ts +56 -0
- package/dist/watcher/contract-watcher.d.ts.map +1 -0
- package/dist/watcher/contract-watcher.js +353 -0
- package/dist/watcher/contract-watcher.js.map +1 -0
- package/dist/watcher/log-poller.d.ts +24 -0
- package/dist/watcher/log-poller.d.ts.map +1 -0
- package/dist/watcher/log-poller.js +82 -0
- package/dist/watcher/log-poller.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TransactionTracer — Deep transaction analysis via debug_traceTransaction.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the XDC/Geth debug namespace to extract:
|
|
5
|
+
* - Full call tree (callTracer)
|
|
6
|
+
* - State diffs (prestateTracer with diffMode)
|
|
7
|
+
* - Balance changes
|
|
8
|
+
* - All involved contracts
|
|
9
|
+
* - Events emitted during execution
|
|
10
|
+
*
|
|
11
|
+
* NOTE: Requires an archive node for historical transactions.
|
|
12
|
+
* For real-time monitoring (current blocks), a regular full node works.
|
|
13
|
+
*/
|
|
14
|
+
import type { TracerResult, CallTreeNode, StateDiff, BalanceChange, LogLevel } from '../types/index.js';
|
|
15
|
+
export interface TransactionTracerConfig {
|
|
16
|
+
/** RPC URL (must support debug namespace) */
|
|
17
|
+
rpcUrl: string;
|
|
18
|
+
/** Fallback RPC URLs */
|
|
19
|
+
fallbackRpcUrls?: string[];
|
|
20
|
+
/** Request timeout in ms (default: 60000 — tracing can be slow) */
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
/** Log level */
|
|
23
|
+
logLevel?: LogLevel;
|
|
24
|
+
}
|
|
25
|
+
export declare class TransactionTracer {
|
|
26
|
+
private readonly logger;
|
|
27
|
+
private readonly logLevel;
|
|
28
|
+
private readonly rpc;
|
|
29
|
+
private readonly registry;
|
|
30
|
+
private readonly decoder;
|
|
31
|
+
constructor(config: TransactionTracerConfig);
|
|
32
|
+
/**
|
|
33
|
+
* Register an ABI for method name decoding in call trees.
|
|
34
|
+
*/
|
|
35
|
+
registerABI(address: string, abi: any[], name?: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Full trace: call tree + state diffs + balance changes + events.
|
|
38
|
+
*/
|
|
39
|
+
trace(txHash: string): Promise<TracerResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Trace only the call tree (callTracer).
|
|
42
|
+
*/
|
|
43
|
+
traceCallTree(txHash: string): Promise<CallTreeNode>;
|
|
44
|
+
/**
|
|
45
|
+
* Trace only state diffs (prestateTracer with diffMode).
|
|
46
|
+
*/
|
|
47
|
+
traceStateDiffs(txHash: string): Promise<{
|
|
48
|
+
stateDiffs: StateDiff[];
|
|
49
|
+
balanceChanges: BalanceChange[];
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=transaction-tracer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-tracer.d.ts","sourceRoot":"","sources":["../../src/tracer/transaction-tracer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,aAAa,EAEb,QAAQ,EACT,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,uBAAuB;IACtC,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;gBAE3B,MAAM,EAAE,uBAAuB;IAc3C;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAI7D;;OAEG;IACG,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA2ClD;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAM1D;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,SAAS,EAAE,CAAC;QAAC,cAAc,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC;CAQ7G"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TransactionTracer — Deep transaction analysis via debug_traceTransaction.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the XDC/Geth debug namespace to extract:
|
|
5
|
+
* - Full call tree (callTracer)
|
|
6
|
+
* - State diffs (prestateTracer with diffMode)
|
|
7
|
+
* - Balance changes
|
|
8
|
+
* - All involved contracts
|
|
9
|
+
* - Events emitted during execution
|
|
10
|
+
*
|
|
11
|
+
* NOTE: Requires an archive node for historical transactions.
|
|
12
|
+
* For real-time monitoring (current blocks), a regular full node works.
|
|
13
|
+
*/
|
|
14
|
+
import { Logger } from '../utils/logger.js';
|
|
15
|
+
import { RpcClient } from '../rpc/rpc-client.js';
|
|
16
|
+
import { EventDecoder } from '../decoder/event-decoder.js';
|
|
17
|
+
import { AbiRegistry } from '../decoder/abi-registry.js';
|
|
18
|
+
import { parseCallTree, extractInvolvedContracts } from './call-tree-parser.js';
|
|
19
|
+
import { parseStateDiffs, parseBalanceChanges } from './state-diff-parser.js';
|
|
20
|
+
export class TransactionTracer {
|
|
21
|
+
logger;
|
|
22
|
+
logLevel;
|
|
23
|
+
rpc;
|
|
24
|
+
registry;
|
|
25
|
+
decoder;
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.logLevel = config.logLevel ?? 'info';
|
|
28
|
+
this.logger = new Logger('TransactionTracer', this.logLevel);
|
|
29
|
+
this.rpc = new RpcClient(config.rpcUrl, {
|
|
30
|
+
fallbackUrls: config.fallbackRpcUrls,
|
|
31
|
+
timeoutMs: config.timeoutMs ?? 60000,
|
|
32
|
+
logLevel: this.logLevel,
|
|
33
|
+
});
|
|
34
|
+
this.registry = new AbiRegistry(this.logLevel);
|
|
35
|
+
this.decoder = new EventDecoder(this.registry, this.logLevel);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Register an ABI for method name decoding in call trees.
|
|
39
|
+
*/
|
|
40
|
+
registerABI(address, abi, name) {
|
|
41
|
+
this.registry.register(address, abi, name);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Full trace: call tree + state diffs + balance changes + events.
|
|
45
|
+
*/
|
|
46
|
+
async trace(txHash) {
|
|
47
|
+
this.logger.info(`Tracing transaction: ${txHash}`);
|
|
48
|
+
const [callTreeRaw, stateDiffRaw, receipt] = await Promise.all([
|
|
49
|
+
this.rpc.traceTransaction(txHash, { tracer: 'callTracer' }),
|
|
50
|
+
this.rpc.traceTransaction(txHash, {
|
|
51
|
+
tracer: 'prestateTracer',
|
|
52
|
+
tracerConfig: { diffMode: true },
|
|
53
|
+
}).catch((err) => {
|
|
54
|
+
this.logger.warn(`prestateTracer failed: ${err.message}`);
|
|
55
|
+
return null;
|
|
56
|
+
}),
|
|
57
|
+
this.rpc.getTransactionReceipt(txHash),
|
|
58
|
+
]);
|
|
59
|
+
const callTree = parseCallTree(callTreeRaw, 0, this.registry);
|
|
60
|
+
const stateDiffs = stateDiffRaw ? parseStateDiffs(stateDiffRaw) : [];
|
|
61
|
+
const balanceChanges = stateDiffRaw ? parseBalanceChanges(stateDiffRaw) : [];
|
|
62
|
+
const involvedContracts = extractInvolvedContracts(callTree);
|
|
63
|
+
const events = [];
|
|
64
|
+
if (receipt?.logs) {
|
|
65
|
+
for (const log of receipt.logs) {
|
|
66
|
+
const decoded = this.decoder.decode(log);
|
|
67
|
+
if (decoded)
|
|
68
|
+
events.push(decoded);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const blockNumber = receipt?.blockNumber
|
|
72
|
+
? (typeof receipt.blockNumber === 'string' ? parseInt(receipt.blockNumber, 16) : receipt.blockNumber)
|
|
73
|
+
: 0;
|
|
74
|
+
const gasUsed = receipt?.gasUsed
|
|
75
|
+
? (typeof receipt.gasUsed === 'string' ? parseInt(receipt.gasUsed, 16) : receipt.gasUsed)
|
|
76
|
+
: 0;
|
|
77
|
+
this.logger.info(`Trace complete: ${countNodes(callTree)} calls, ${stateDiffs.length} state diffs, ` +
|
|
78
|
+
`${balanceChanges.length} balance changes, ${events.length} events`);
|
|
79
|
+
return { txHash, blockNumber, callTree, stateDiffs, balanceChanges, events, gasUsed, involvedContracts };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Trace only the call tree (callTracer).
|
|
83
|
+
*/
|
|
84
|
+
async traceCallTree(txHash) {
|
|
85
|
+
this.logger.info(`Tracing call tree: ${txHash}`);
|
|
86
|
+
const raw = await this.rpc.traceTransaction(txHash, { tracer: 'callTracer' });
|
|
87
|
+
return parseCallTree(raw, 0, this.registry);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Trace only state diffs (prestateTracer with diffMode).
|
|
91
|
+
*/
|
|
92
|
+
async traceStateDiffs(txHash) {
|
|
93
|
+
this.logger.info(`Tracing state diffs: ${txHash}`);
|
|
94
|
+
const raw = await this.rpc.traceTransaction(txHash, {
|
|
95
|
+
tracer: 'prestateTracer',
|
|
96
|
+
tracerConfig: { diffMode: true },
|
|
97
|
+
});
|
|
98
|
+
return { stateDiffs: parseStateDiffs(raw), balanceChanges: parseBalanceChanges(raw) };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function countNodes(node) {
|
|
102
|
+
let count = 1;
|
|
103
|
+
for (const child of node.calls)
|
|
104
|
+
count += countNodes(child);
|
|
105
|
+
return count;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=transaction-tracer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-tracer.js","sourceRoot":"","sources":["../../src/tracer/transaction-tracer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XDC Interaction Detector — Core Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Standalone types with zero framework dependencies.
|
|
5
|
+
* Covers: configuration, events, logs, tracing, explorer, interactions.
|
|
6
|
+
*/
|
|
7
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
8
|
+
/** Main configuration for ContractWatcher */
|
|
9
|
+
export interface InteractionDetectorConfig {
|
|
10
|
+
/** Primary HTTP RPC URL */
|
|
11
|
+
rpcUrl: string;
|
|
12
|
+
/** WebSocket RPC URL (optional — enables real-time event push) */
|
|
13
|
+
wsUrl?: string;
|
|
14
|
+
/** Contracts to monitor */
|
|
15
|
+
contracts: ContractConfig[];
|
|
16
|
+
/** Block explorer API settings (optional — enables direct/internal tx collection) */
|
|
17
|
+
explorer?: ExplorerConfig;
|
|
18
|
+
/** Polling configuration */
|
|
19
|
+
polling?: PollingConfig;
|
|
20
|
+
/** WebSocket configuration */
|
|
21
|
+
ws?: WsConfig;
|
|
22
|
+
/** Checkpoint persistence configuration */
|
|
23
|
+
checkpoint?: CheckpointConfig;
|
|
24
|
+
/** Log level (default: 'info') */
|
|
25
|
+
logLevel?: LogLevel;
|
|
26
|
+
/** Chain ID (default: 50 for XDC Mainnet) */
|
|
27
|
+
chainId?: number;
|
|
28
|
+
/** Fallback RPC URLs for retry */
|
|
29
|
+
fallbackRpcUrls?: string[];
|
|
30
|
+
}
|
|
31
|
+
/** Per-contract configuration */
|
|
32
|
+
export interface ContractConfig {
|
|
33
|
+
/** Contract address (0x or xdc prefix supported) */
|
|
34
|
+
address: string;
|
|
35
|
+
/** Contract ABI (optional — enables event decoding) */
|
|
36
|
+
abi?: readonly any[] | any[];
|
|
37
|
+
/** Human-readable name (optional — appears in decoded events) */
|
|
38
|
+
name?: string;
|
|
39
|
+
}
|
|
40
|
+
/** Block explorer API configuration (Etherscan-compatible) */
|
|
41
|
+
export interface ExplorerConfig {
|
|
42
|
+
/** Base API URL (e.g. 'https://xdc.blocksscan.io/api' or 'https://api.etherscan.io/v2/api') */
|
|
43
|
+
apiUrl: string;
|
|
44
|
+
/** API key (optional — higher rate limits) */
|
|
45
|
+
apiKey?: string;
|
|
46
|
+
/** Chain ID for Etherscan v2 unified endpoint (required for Etherscan v2) */
|
|
47
|
+
chainId?: number;
|
|
48
|
+
/** Max requests per second (default: 5) */
|
|
49
|
+
rateLimitPerSec?: number;
|
|
50
|
+
/** Polling interval in ms for txlist/txlistinternal (default: 60000) */
|
|
51
|
+
pollIntervalMs?: number;
|
|
52
|
+
}
|
|
53
|
+
/** Polling configuration for eth_getLogs fallback */
|
|
54
|
+
export interface PollingConfig {
|
|
55
|
+
/** Polling interval in ms (default: 30000) */
|
|
56
|
+
intervalMs?: number;
|
|
57
|
+
/** Max blocks per eth_getLogs request (default: 100 for XDC) */
|
|
58
|
+
maxBlockRange?: number;
|
|
59
|
+
/** Number of parallel chunk fetches (default: 3) */
|
|
60
|
+
concurrency?: number;
|
|
61
|
+
}
|
|
62
|
+
/** WebSocket configuration */
|
|
63
|
+
export interface WsConfig {
|
|
64
|
+
/** Enable WebSocket subscription (default: true) */
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
/** Base delay between reconnect attempts in ms (default: 5000) */
|
|
67
|
+
reconnectDelayBaseMs?: number;
|
|
68
|
+
/** Maximum reconnect delay in ms (default: 30000) */
|
|
69
|
+
reconnectDelayMaxMs?: number;
|
|
70
|
+
/** Maximum reconnect attempts before long backoff (default: 20) */
|
|
71
|
+
maxReconnectAttempts?: number;
|
|
72
|
+
/** Heartbeat interval in ms (default: 60000) */
|
|
73
|
+
heartbeatIntervalMs?: number;
|
|
74
|
+
/** Heartbeat timeout in ms (default: 10000) */
|
|
75
|
+
heartbeatTimeoutMs?: number;
|
|
76
|
+
}
|
|
77
|
+
/** Checkpoint persistence configuration */
|
|
78
|
+
export interface CheckpointConfig {
|
|
79
|
+
/** Backend type: 'memory' (dev), 'file' (simple prod), or 'custom' */
|
|
80
|
+
backend: 'memory' | 'file' | 'custom';
|
|
81
|
+
/** File path for 'file' backend (default: './checkpoints') */
|
|
82
|
+
path?: string;
|
|
83
|
+
/** Custom backend implementation */
|
|
84
|
+
custom?: CheckpointBackend;
|
|
85
|
+
}
|
|
86
|
+
export interface CheckpointBackend {
|
|
87
|
+
save(key: string, blockNumber: number): Promise<void>;
|
|
88
|
+
load(key: string): Promise<number | null>;
|
|
89
|
+
}
|
|
90
|
+
export interface RawLog {
|
|
91
|
+
address: string;
|
|
92
|
+
topics: string[];
|
|
93
|
+
data: string;
|
|
94
|
+
blockNumber: string | number;
|
|
95
|
+
transactionHash: string;
|
|
96
|
+
transactionIndex: string | number;
|
|
97
|
+
logIndex: string | number;
|
|
98
|
+
blockHash: string;
|
|
99
|
+
removed?: boolean;
|
|
100
|
+
}
|
|
101
|
+
export interface DecodedEvent {
|
|
102
|
+
/** Normalized contract address (lowercase 0x) */
|
|
103
|
+
contract: string;
|
|
104
|
+
/** Human-readable contract name (from config) */
|
|
105
|
+
contractName?: string;
|
|
106
|
+
/** Event name (e.g. 'Transfer', 'Swap', 'Vote') */
|
|
107
|
+
name: string;
|
|
108
|
+
/** Event signature (e.g. 'transfer(address,uint256)') */
|
|
109
|
+
signature: string;
|
|
110
|
+
/** Decoded event arguments (named) */
|
|
111
|
+
args: Record<string, any>;
|
|
112
|
+
/** Block number */
|
|
113
|
+
blockNumber: number;
|
|
114
|
+
/** Transaction hash */
|
|
115
|
+
txHash: string;
|
|
116
|
+
/** Log index within the transaction */
|
|
117
|
+
logIndex: number;
|
|
118
|
+
/** Block timestamp (Unix seconds) */
|
|
119
|
+
timestamp: number;
|
|
120
|
+
/** Raw log data */
|
|
121
|
+
raw: RawLog;
|
|
122
|
+
}
|
|
123
|
+
/** How a contract was involved in a transaction */
|
|
124
|
+
export type InteractionType = 'event' | 'direct_call' | 'internal_call' | 'delegate_call' | 'static_call' | 'create' | 'self_destruct';
|
|
125
|
+
/** Unified interaction record combining all detection methods */
|
|
126
|
+
export interface ContractInteraction {
|
|
127
|
+
/** How the contract was involved */
|
|
128
|
+
type: InteractionType;
|
|
129
|
+
/** Transaction hash */
|
|
130
|
+
txHash: string;
|
|
131
|
+
/** Block number */
|
|
132
|
+
blockNumber: number;
|
|
133
|
+
/** Block timestamp (Unix seconds) */
|
|
134
|
+
timestamp: number;
|
|
135
|
+
/** Transaction sender (from) */
|
|
136
|
+
from: string;
|
|
137
|
+
/** Transaction recipient / contract address */
|
|
138
|
+
to: string;
|
|
139
|
+
/** Native value transferred (wei) */
|
|
140
|
+
value: string;
|
|
141
|
+
/** Decoded event (if type == 'event') */
|
|
142
|
+
event?: DecodedEvent;
|
|
143
|
+
/** Function selector (first 4 bytes of input) */
|
|
144
|
+
methodId?: string;
|
|
145
|
+
/** Decoded method name (if ABI available) */
|
|
146
|
+
methodName?: string;
|
|
147
|
+
/** Input calldata */
|
|
148
|
+
input?: string;
|
|
149
|
+
/** Gas used */
|
|
150
|
+
gasUsed?: string;
|
|
151
|
+
/** Whether the call failed/reverted */
|
|
152
|
+
isError?: boolean;
|
|
153
|
+
/** Source of the interaction detection */
|
|
154
|
+
source: 'rpc_logs' | 'ws_logs' | 'explorer_txlist' | 'explorer_internal' | 'tracer';
|
|
155
|
+
}
|
|
156
|
+
/** Full trace result for a single transaction */
|
|
157
|
+
export interface TracerResult {
|
|
158
|
+
/** Transaction hash */
|
|
159
|
+
txHash: string;
|
|
160
|
+
/** Block number */
|
|
161
|
+
blockNumber: number;
|
|
162
|
+
/** Full call tree (nested) */
|
|
163
|
+
callTree: CallTreeNode;
|
|
164
|
+
/** Storage slot state diffs */
|
|
165
|
+
stateDiffs: StateDiff[];
|
|
166
|
+
/** Native / token balance changes per address */
|
|
167
|
+
balanceChanges: BalanceChange[];
|
|
168
|
+
/** All events emitted during execution (decoded if ABI available) */
|
|
169
|
+
events: DecodedEvent[];
|
|
170
|
+
/** Total gas used */
|
|
171
|
+
gasUsed: number;
|
|
172
|
+
/** All contract addresses involved in execution */
|
|
173
|
+
involvedContracts: string[];
|
|
174
|
+
}
|
|
175
|
+
/** Single node in the call tree (recursive) */
|
|
176
|
+
export interface CallTreeNode {
|
|
177
|
+
/** Call type: CALL, STATICCALL, DELEGATECALL, CREATE, CREATE2 */
|
|
178
|
+
type: string;
|
|
179
|
+
/** Caller address */
|
|
180
|
+
from: string;
|
|
181
|
+
/** Callee address */
|
|
182
|
+
to: string;
|
|
183
|
+
/** Native value transferred (hex) */
|
|
184
|
+
value: string;
|
|
185
|
+
/** Gas provided */
|
|
186
|
+
gas: string;
|
|
187
|
+
/** Gas used */
|
|
188
|
+
gasUsed: string;
|
|
189
|
+
/** Input calldata (hex) */
|
|
190
|
+
input: string;
|
|
191
|
+
/** Output / return data (hex) */
|
|
192
|
+
output: string;
|
|
193
|
+
/** Decoded method signature (if ABI available) */
|
|
194
|
+
method?: string;
|
|
195
|
+
/** Error message (if call reverted) */
|
|
196
|
+
error?: string;
|
|
197
|
+
/** Nested sub-calls */
|
|
198
|
+
calls: CallTreeNode[];
|
|
199
|
+
/** Depth in the call tree (0 = top-level) */
|
|
200
|
+
depth: number;
|
|
201
|
+
}
|
|
202
|
+
/** Storage slot state diff from prestateTracer */
|
|
203
|
+
export interface StateDiff {
|
|
204
|
+
/** Contract address whose storage changed */
|
|
205
|
+
contract: string;
|
|
206
|
+
/** Storage slot key */
|
|
207
|
+
slot: string;
|
|
208
|
+
/** Value before execution */
|
|
209
|
+
before: string;
|
|
210
|
+
/** Value after execution */
|
|
211
|
+
after: string;
|
|
212
|
+
}
|
|
213
|
+
/** Balance change for an address */
|
|
214
|
+
export interface BalanceChange {
|
|
215
|
+
/** Address that had a balance change */
|
|
216
|
+
address: string;
|
|
217
|
+
/** Token address ('native' for XDC/ETH) */
|
|
218
|
+
token: string;
|
|
219
|
+
/** Balance before */
|
|
220
|
+
before: bigint;
|
|
221
|
+
/** Balance after */
|
|
222
|
+
after: bigint;
|
|
223
|
+
/** Change (after - before) */
|
|
224
|
+
delta: bigint;
|
|
225
|
+
}
|
|
226
|
+
/** Transaction from explorer API (txlist endpoint) */
|
|
227
|
+
export interface ExplorerTransaction {
|
|
228
|
+
hash: string;
|
|
229
|
+
blockNumber: string;
|
|
230
|
+
timeStamp: string;
|
|
231
|
+
from: string;
|
|
232
|
+
to: string;
|
|
233
|
+
value: string;
|
|
234
|
+
gas: string;
|
|
235
|
+
gasUsed: string;
|
|
236
|
+
gasPrice: string;
|
|
237
|
+
input: string;
|
|
238
|
+
methodId: string;
|
|
239
|
+
functionName: string;
|
|
240
|
+
isError: string;
|
|
241
|
+
contractAddress: string;
|
|
242
|
+
/** 'external' from txlist, 'internal' from txlistinternal */
|
|
243
|
+
txType: 'external' | 'internal';
|
|
244
|
+
/** Call type for internal txs (call, delegatecall, staticcall, create) */
|
|
245
|
+
callType?: string;
|
|
246
|
+
}
|
|
247
|
+
/** Block scanner query options */
|
|
248
|
+
export interface ScanOptions {
|
|
249
|
+
/** Contract address to scan */
|
|
250
|
+
address: string;
|
|
251
|
+
/** Contract ABI (optional) */
|
|
252
|
+
abi?: readonly any[] | any[];
|
|
253
|
+
/** Start block (inclusive) */
|
|
254
|
+
fromBlock: number;
|
|
255
|
+
/** End block (inclusive) */
|
|
256
|
+
toBlock: number;
|
|
257
|
+
/** Filter by specific event name (optional) */
|
|
258
|
+
eventFilter?: string;
|
|
259
|
+
/** Progress callback (blocks processed / total) */
|
|
260
|
+
onProgress?: (processed: number, total: number) => void;
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAItE,6CAA6C;AAC7C,MAAM,WAAW,yBAAyB;IACxC,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,qFAAqF;IACrF,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,4BAA4B;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,8BAA8B;IAC9B,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,2CAA2C;IAC3C,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,iCAAiC;AACjC,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,GAAG,CAAC,EAAE,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAC7B,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,8BAA8B;AAC9B,MAAM,WAAW,QAAQ;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qDAAqD;IACrD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mEAAmE;IACnE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtC,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAID,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC3C;AAID,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAID,mDAAmD;AACnD,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,aAAa,GACb,eAAe,GACf,eAAe,GACf,aAAa,GACb,QAAQ,GACR,eAAe,CAAC;AAEpB,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,IAAI,EAAE,eAAe,CAAC;IACtB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,QAAQ,CAAC;CACrF;AAID,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,+BAA+B;IAC/B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,iDAAiD;IACjD,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,qEAAqE;IACrE,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,kDAAkD;AAClD,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oCAAoC;AACpC,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAID,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAC7B,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XDC address utilities.
|
|
3
|
+
*
|
|
4
|
+
* Handles the XDC-specific `xdc` prefix alongside standard `0x`.
|
|
5
|
+
* All internal operations use lowercase `0x` format.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Normalize an address to lowercase `0x` format.
|
|
9
|
+
* Converts `xdc` prefix to `0x`, strips whitespace, lowercases.
|
|
10
|
+
*/
|
|
11
|
+
export declare function normalizeAddress(address: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Convert a `0x` address to `xdc` prefixed format.
|
|
14
|
+
*/
|
|
15
|
+
export declare function toXdcAddress(address: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Convert an `xdc` address to standard `0x` format.
|
|
18
|
+
* Alias for normalizeAddress since it already handles this.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toEthAddress(address: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Validate that a string is a valid hex address (20 bytes).
|
|
23
|
+
*/
|
|
24
|
+
export declare function isAddress(address: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if two addresses are the same (case-insensitive, prefix-aware).
|
|
27
|
+
*/
|
|
28
|
+
export declare function addressEqual(a: string, b: string): boolean;
|
|
29
|
+
//# sourceMappingURL=address.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../../src/utils/address.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAIlD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAE1D"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XDC address utilities.
|
|
3
|
+
*
|
|
4
|
+
* Handles the XDC-specific `xdc` prefix alongside standard `0x`.
|
|
5
|
+
* All internal operations use lowercase `0x` format.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Normalize an address to lowercase `0x` format.
|
|
9
|
+
* Converts `xdc` prefix to `0x`, strips whitespace, lowercases.
|
|
10
|
+
*/
|
|
11
|
+
export function normalizeAddress(address) {
|
|
12
|
+
if (!address)
|
|
13
|
+
return address;
|
|
14
|
+
let normalized = address.trim().toLowerCase();
|
|
15
|
+
if (normalized.startsWith('xdc')) {
|
|
16
|
+
normalized = '0x' + normalized.slice(3);
|
|
17
|
+
}
|
|
18
|
+
return normalized;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Convert a `0x` address to `xdc` prefixed format.
|
|
22
|
+
*/
|
|
23
|
+
export function toXdcAddress(address) {
|
|
24
|
+
const normalized = normalizeAddress(address);
|
|
25
|
+
return 'xdc' + normalized.slice(2);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Convert an `xdc` address to standard `0x` format.
|
|
29
|
+
* Alias for normalizeAddress since it already handles this.
|
|
30
|
+
*/
|
|
31
|
+
export function toEthAddress(address) {
|
|
32
|
+
return normalizeAddress(address);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate that a string is a valid hex address (20 bytes).
|
|
36
|
+
*/
|
|
37
|
+
export function isAddress(address) {
|
|
38
|
+
if (!address)
|
|
39
|
+
return false;
|
|
40
|
+
const normalized = normalizeAddress(address);
|
|
41
|
+
return /^0x[0-9a-f]{40}$/.test(normalized);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if two addresses are the same (case-insensitive, prefix-aware).
|
|
45
|
+
*/
|
|
46
|
+
export function addressEqual(a, b) {
|
|
47
|
+
return normalizeAddress(a) === normalizeAddress(b);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.js","sourceRoot":"","sources":["../../src/utils/address.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC;IAC7B,IAAI,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,UAAU,GAAG,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS,EAAE,CAAS;IAC/C,OAAO,gBAAgB,CAAC,CAAC,CAAC,KAAK,gBAAgB,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting utilities for blockchain values.
|
|
3
|
+
*/
|
|
4
|
+
/** Format XDC amount from wei to human-readable string */
|
|
5
|
+
export declare function formatXDC(weiAmount: bigint): string;
|
|
6
|
+
/** Format native token amount from wei (generic, no unit suffix) */
|
|
7
|
+
export declare function formatWei(weiAmount: bigint, decimals?: number): string;
|
|
8
|
+
/** Parse hex string to number */
|
|
9
|
+
export declare function parseHexOrDecimal(value: string | number): number;
|
|
10
|
+
/** Convert number to hex string with 0x prefix */
|
|
11
|
+
export declare function toHex(value: number): string;
|
|
12
|
+
/** Get current date string (YYYY-MM-DD) */
|
|
13
|
+
export declare function getCurrentDateString(): string;
|
|
14
|
+
/** Get current Unix timestamp in seconds */
|
|
15
|
+
export declare function nowSeconds(): number;
|
|
16
|
+
/** Truncate an address for display: 0x1234...abcd */
|
|
17
|
+
export declare function shortAddress(address: string): string;
|
|
18
|
+
/** Sleep helper */
|
|
19
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,oEAAoE;AACpE,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,GAAG,MAAM,CAK1E;AAED,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAMhE;AAED,kDAAkD;AAClD,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,2CAA2C;AAC3C,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,4CAA4C;AAC5C,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,mBAAmB;AACnB,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting utilities for blockchain values.
|
|
3
|
+
*/
|
|
4
|
+
/** Format XDC amount from wei to human-readable string */
|
|
5
|
+
export function formatXDC(weiAmount) {
|
|
6
|
+
const xdc = Number(weiAmount) / 1e18;
|
|
7
|
+
if (xdc >= 1_000_000)
|
|
8
|
+
return `${(xdc / 1_000_000).toFixed(2)}M XDC`;
|
|
9
|
+
if (xdc >= 1_000)
|
|
10
|
+
return `${(xdc / 1_000).toFixed(2)}K XDC`;
|
|
11
|
+
return `${xdc.toFixed(2)} XDC`;
|
|
12
|
+
}
|
|
13
|
+
/** Format native token amount from wei (generic, no unit suffix) */
|
|
14
|
+
export function formatWei(weiAmount, decimals = 18) {
|
|
15
|
+
const value = Number(weiAmount) / Math.pow(10, decimals);
|
|
16
|
+
if (value >= 1_000_000)
|
|
17
|
+
return `${(value / 1_000_000).toFixed(2)}M`;
|
|
18
|
+
if (value >= 1_000)
|
|
19
|
+
return `${(value / 1_000).toFixed(2)}K`;
|
|
20
|
+
return value.toFixed(4);
|
|
21
|
+
}
|
|
22
|
+
/** Parse hex string to number */
|
|
23
|
+
export function parseHexOrDecimal(value) {
|
|
24
|
+
if (typeof value === 'number')
|
|
25
|
+
return value;
|
|
26
|
+
if (value.startsWith('0x') || value.startsWith('0X')) {
|
|
27
|
+
return parseInt(value, 16);
|
|
28
|
+
}
|
|
29
|
+
return parseInt(value, 10);
|
|
30
|
+
}
|
|
31
|
+
/** Convert number to hex string with 0x prefix */
|
|
32
|
+
export function toHex(value) {
|
|
33
|
+
return '0x' + value.toString(16);
|
|
34
|
+
}
|
|
35
|
+
/** Get current date string (YYYY-MM-DD) */
|
|
36
|
+
export function getCurrentDateString() {
|
|
37
|
+
return new Date().toISOString().slice(0, 10);
|
|
38
|
+
}
|
|
39
|
+
/** Get current Unix timestamp in seconds */
|
|
40
|
+
export function nowSeconds() {
|
|
41
|
+
return Math.floor(Date.now() / 1000);
|
|
42
|
+
}
|
|
43
|
+
/** Truncate an address for display: 0x1234...abcd */
|
|
44
|
+
export function shortAddress(address) {
|
|
45
|
+
if (!address || address.length < 10)
|
|
46
|
+
return address;
|
|
47
|
+
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
48
|
+
}
|
|
49
|
+
/** Sleep helper */
|
|
50
|
+
export function sleep(ms) {
|
|
51
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0DAA0D;AAC1D,MAAM,UAAU,SAAS,CAAC,SAAiB;IACzC,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IACrC,IAAI,GAAG,IAAI,SAAS;QAAE,OAAO,GAAG,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACpE,IAAI,GAAG,IAAI,KAAK;QAAE,OAAO,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC5D,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AACjC,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,SAAS,CAAC,SAAiB,EAAE,WAAmB,EAAE;IAChE,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,IAAI,KAAK,IAAI,KAAK;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5D,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,iBAAiB,CAAC,KAAsB;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,OAAO,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,OAAO,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,OAAO,CAAC;IACpD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,mBAAmB;AACnB,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple structured logger — no external dependencies.
|
|
3
|
+
* Supports log levels: debug, info, warn, error, silent.
|
|
4
|
+
*/
|
|
5
|
+
import type { LogLevel } from '../types/index.js';
|
|
6
|
+
export declare class Logger {
|
|
7
|
+
private readonly context;
|
|
8
|
+
private readonly level;
|
|
9
|
+
constructor(context: string, level?: LogLevel);
|
|
10
|
+
debug(message: string, ...args: any[]): void;
|
|
11
|
+
info(message: string, ...args: any[]): void;
|
|
12
|
+
warn(message: string, ...args: any[]): void;
|
|
13
|
+
error(message: string, ...args: any[]): void;
|
|
14
|
+
private log;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAmBlD,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,QAAiB;IAKrD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM3C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM5C,OAAO,CAAC,GAAG;CAUZ"}
|