@pioneer-platform/pioneer-history 0.2.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.
@@ -0,0 +1,2 @@
1
+
2
+ $ tsc -p .
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # @pioneer-platform/pioneer-history
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - chore: feat(pioneer-sdk): Add transaction history integration
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @pioneer-platform/eth-network@8.30.0
13
+ - @pioneer-platform/utxo-network@8.27.0
14
+
15
+ ## 0.1.0
16
+
17
+ ### Minor Changes
18
+
19
+ - feat(pioneer-sdk): Add transaction history integration
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies
24
+ - @pioneer-platform/eth-network@8.29.0
25
+ - @pioneer-platform/utxo-network@8.26.0
package/lib/index.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ export declare const UTXO_SUPPORT: string[];
2
+ export declare const TENDERMINT_SUPPORT: string[];
3
+ export declare const OTHER_SUPPORT: string[];
4
+ export declare const SUPPORTED_CAIPS: {
5
+ UTXO: string[];
6
+ TENDERMINT: string[];
7
+ EIP155: string[];
8
+ OTHER: string[];
9
+ };
10
+ export interface HistoryQuery {
11
+ caip: string;
12
+ pubkey: string;
13
+ }
14
+ export interface HistoryOptions {
15
+ limit?: number;
16
+ offset?: number;
17
+ page?: number;
18
+ dateRange?: {
19
+ from?: string;
20
+ to?: string;
21
+ };
22
+ }
23
+ export interface Transaction {
24
+ txid: string;
25
+ caip: string;
26
+ networkId: string;
27
+ direction: 'sent' | 'received' | 'self';
28
+ type: 'transfer' | 'token_transfer' | 'swap' | 'stake' | 'unstake' | 'reward' | 'contract';
29
+ status: 'confirmed' | 'pending' | 'failed';
30
+ blockHeight?: number;
31
+ timestamp: number;
32
+ confirmations?: number;
33
+ from: string[];
34
+ to: string[];
35
+ value: string;
36
+ fee?: string;
37
+ memo?: string;
38
+ raw?: any;
39
+ }
40
+ export * from './schemas/history-response';
41
+ export declare class History {
42
+ private blockchains;
43
+ private nodes;
44
+ private networks;
45
+ constructor(config: any);
46
+ init(): Promise<boolean>;
47
+ classifyCaip(caip: string): Promise<string>;
48
+ private normalizeUtxoTransactions;
49
+ private normalizeEvmTransactions;
50
+ private normalizeTendermintTransactions;
51
+ private normalizeRippleTransactions;
52
+ getHistory(query: HistoryQuery | HistoryQuery[], options?: HistoryOptions): Promise<any>;
53
+ }
package/lib/index.js ADDED
@@ -0,0 +1,530 @@
1
+ "use strict";
2
+ /*
3
+
4
+ Pioneer History Module
5
+
6
+ Query transaction history on any network
7
+
8
+ pioneer-network map
9
+
10
+ utxo,
11
+ ethereum,
12
+ ripple,
13
+ cosmos,
14
+ thorchain,
15
+ osmosis,
16
+ mayachain
17
+
18
+ */
19
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ var desc = Object.getOwnPropertyDescriptor(m, k);
22
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
23
+ desc = { enumerable: true, get: function() { return m[k]; } };
24
+ }
25
+ Object.defineProperty(o, k2, desc);
26
+ }) : (function(o, m, k, k2) {
27
+ if (k2 === undefined) k2 = k;
28
+ o[k2] = m[k];
29
+ }));
30
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
31
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
32
+ };
33
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
34
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
35
+ return new (P || (P = Promise))(function (resolve, reject) {
36
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
37
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
38
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
39
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
40
+ });
41
+ };
42
+ var __generator = (this && this.__generator) || function (thisArg, body) {
43
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
44
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
45
+ function verb(n) { return function (v) { return step([n, v]); }; }
46
+ function step(op) {
47
+ if (f) throw new TypeError("Generator is already executing.");
48
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
49
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
50
+ if (y = 0, t) op = [op[0] & 2, t.value];
51
+ switch (op[0]) {
52
+ case 0: case 1: t = op; break;
53
+ case 4: _.label++; return { value: op[1], done: false };
54
+ case 5: _.label++; y = op[1]; op = [0]; continue;
55
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
56
+ default:
57
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
58
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
59
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
60
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
61
+ if (t[2]) _.ops.pop();
62
+ _.trys.pop(); continue;
63
+ }
64
+ op = body.call(thisArg, _);
65
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
66
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
67
+ }
68
+ };
69
+ Object.defineProperty(exports, "__esModule", { value: true });
70
+ exports.History = exports.SUPPORTED_CAIPS = exports.OTHER_SUPPORT = exports.TENDERMINT_SUPPORT = exports.UTXO_SUPPORT = void 0;
71
+ var TAG = " | pioneer-history | ";
72
+ var log = require('@pioneer-platform/loggerdog')();
73
+ var caipToNetworkId = require('@pioneer-platform/pioneer-caip').caipToNetworkId;
74
+ // CAIP support constants (reuse from pioneer-balance)
75
+ exports.UTXO_SUPPORT = [
76
+ 'bip122:000000000019d6689c085ae165831e93/slip44:0', // BTC
77
+ 'bip122:000000000000000000651ef99cb9fcbe/slip44:145', // BCH
78
+ 'bip122:000007d91d1254d60e2dd1ae58038307/slip44:5', // DASH
79
+ 'bip122:00000000001a91e3dace36e2be3bf030/slip44:3', // DOGE
80
+ 'bip122:12a765e31ffd4059bada1e25190f6e98/slip44:2', // LTC
81
+ 'bip122:4da631f2ac1bed857bd968c67c913978/slip44:20', // DGB
82
+ 'bip122:00040fe8ec8471911baa1db1266ea15d/slip44:133', // ZEC
83
+ ];
84
+ exports.TENDERMINT_SUPPORT = [
85
+ 'cosmos:mayachain-mainnet-v1/slip44:931',
86
+ 'cosmos:mayachain-mainnet-v1/denom:maya',
87
+ 'cosmos:osmosis-1/slip44:118',
88
+ 'cosmos:cosmoshub-4/slip44:118',
89
+ 'cosmos:thorchain-mainnet-v1/slip44:931',
90
+ ];
91
+ exports.OTHER_SUPPORT = ['ripple:4109c6f2045fc7eff4cde8f9905d19c2/slip44:144'];
92
+ exports.SUPPORTED_CAIPS = {
93
+ UTXO: exports.UTXO_SUPPORT,
94
+ TENDERMINT: exports.TENDERMINT_SUPPORT,
95
+ EIP155: ['eip155:*'],
96
+ OTHER: exports.OTHER_SUPPORT,
97
+ };
98
+ // Export schemas
99
+ __exportStar(require("./schemas/history-response"), exports);
100
+ var History = /** @class */ (function () {
101
+ function History(config) {
102
+ log.debug(TAG, "🏗️ History constructor called");
103
+ this.blockchains = config.wss || [];
104
+ this.nodes = config.nodes || [];
105
+ // CRITICAL: Use globally initialized networks if available (server environment)
106
+ var globalNetworks = global.pioneerNetworks;
107
+ if (globalNetworks) {
108
+ log.debug(TAG, "✅ Using globally initialized networks from pioneer-network");
109
+ log.debug(TAG, " Available networks:", Object.keys(globalNetworks));
110
+ this.networks = { networks: globalNetworks };
111
+ }
112
+ else {
113
+ log.debug(TAG, "⚠️ No global networks found - creating local instances (backward compatibility mode)");
114
+ // Fallback: Import individual network modules
115
+ var utxo = require('@pioneer-platform/utxo-network');
116
+ var ethereum = require('@pioneer-platform/eth-network');
117
+ var ripple = require('@pioneer-platform/ripple-network');
118
+ var cosmos = require('@pioneer-platform/cosmos-network');
119
+ var thorchain = require('@pioneer-platform/thor-network');
120
+ var osmosis = require('@pioneer-platform/osmosis-network');
121
+ var mayachain = require('@pioneer-platform/maya-network');
122
+ this.networks = {
123
+ networks: {
124
+ utxo: utxo,
125
+ ethereum: ethereum,
126
+ ripple: ripple,
127
+ cosmos: cosmos,
128
+ thorchain: thorchain,
129
+ osmosis: osmosis,
130
+ mayachain: mayachain,
131
+ }
132
+ };
133
+ }
134
+ log.debug(TAG, "✅ History constructor complete");
135
+ this.init = this.init.bind(this);
136
+ this.getHistory = this.getHistory.bind(this);
137
+ this.classifyCaip = this.classifyCaip.bind(this);
138
+ }
139
+ History.prototype.init = function () {
140
+ return __awaiter(this, void 0, void 0, function () {
141
+ var tag, globalNetworks, networkChecks, _i, networkChecks_1, check, isOnline, e_1;
142
+ return __generator(this, function (_a) {
143
+ switch (_a.label) {
144
+ case 0:
145
+ tag = TAG + " | init | ";
146
+ _a.label = 1;
147
+ case 1:
148
+ _a.trys.push([1, 11, , 12]);
149
+ globalNetworks = global.pioneerNetworks;
150
+ if (!globalNetworks) return [3 /*break*/, 2];
151
+ // CRITICAL: If using globally initialized networks, skip re-initialization
152
+ log.debug(tag, "✅ Using pre-initialized global networks - skipping network init");
153
+ log.debug(tag, " Verifying network online status:");
154
+ networkChecks = [
155
+ { name: 'utxo', module: this.networks.networks.utxo },
156
+ { name: 'ethereum', module: this.networks.networks.ethereum },
157
+ { name: 'ripple', module: this.networks.networks.ripple },
158
+ { name: 'cosmos', module: this.networks.networks.cosmos },
159
+ { name: 'thorchain', module: this.networks.networks.thorchain },
160
+ { name: 'osmosis', module: this.networks.networks.osmosis },
161
+ { name: 'mayachain', module: this.networks.networks.mayachain },
162
+ ];
163
+ for (_i = 0, networkChecks_1 = networkChecks; _i < networkChecks_1.length; _i++) {
164
+ check = networkChecks_1[_i];
165
+ isOnline = check.module.isOnline ? check.module.isOnline() : true;
166
+ log.debug(tag, " ".concat(check.name, ": ").concat(isOnline ? '✅ online' : '❌ offline'));
167
+ if (!isOnline) {
168
+ log.warn(tag, "\u26A0\uFE0F WARNING: ".concat(check.name, " network is not online - history fetches may fail"));
169
+ }
170
+ }
171
+ return [3 /*break*/, 10];
172
+ case 2:
173
+ // Fallback: Initialize local network instances
174
+ log.debug(tag, "⚠️ Initializing local network instances (backward compatibility)");
175
+ return [4 /*yield*/, this.networks.networks.utxo.init()];
176
+ case 3:
177
+ _a.sent();
178
+ return [4 /*yield*/, this.networks.networks.ethereum.init()];
179
+ case 4:
180
+ _a.sent();
181
+ return [4 /*yield*/, this.networks.networks.ripple.init()];
182
+ case 5:
183
+ _a.sent();
184
+ return [4 /*yield*/, this.networks.networks.cosmos.init()];
185
+ case 6:
186
+ _a.sent();
187
+ return [4 /*yield*/, this.networks.networks.thorchain.init()];
188
+ case 7:
189
+ _a.sent();
190
+ return [4 /*yield*/, this.networks.networks.osmosis.init()];
191
+ case 8:
192
+ _a.sent();
193
+ return [4 /*yield*/, this.networks.networks.mayachain.init()];
194
+ case 9:
195
+ _a.sent();
196
+ _a.label = 10;
197
+ case 10: return [2 /*return*/, true];
198
+ case 11:
199
+ e_1 = _a.sent();
200
+ console.error(tag, e_1);
201
+ throw e_1;
202
+ case 12: return [2 /*return*/];
203
+ }
204
+ });
205
+ });
206
+ };
207
+ History.prototype.classifyCaip = function (caip) {
208
+ return __awaiter(this, void 0, void 0, function () {
209
+ return __generator(this, function (_a) {
210
+ // Use startsWith for chains where CAIP format might vary
211
+ if (caip.startsWith('bip122:'))
212
+ return [2 /*return*/, 'UTXO'];
213
+ if (caip.startsWith('cosmos:'))
214
+ return [2 /*return*/, 'TENDERMINT'];
215
+ if (caip.startsWith('eip155'))
216
+ return [2 /*return*/, 'EIP155'];
217
+ if (caip.startsWith('ripple:'))
218
+ return [2 /*return*/, 'OTHER'];
219
+ // Fallback to exact match for OTHER category
220
+ if (exports.SUPPORTED_CAIPS.OTHER.includes(caip))
221
+ return [2 /*return*/, 'OTHER'];
222
+ throw new Error("FAIL FAST: Unsupported CAIP: ".concat(caip, " - Add support for this chain or fix CAIP format"));
223
+ });
224
+ });
225
+ };
226
+ History.prototype.normalizeUtxoTransactions = function (rawTxs, userXpub, caip) {
227
+ var tag = TAG + " | normalizeUtxoTransactions | ";
228
+ if (!Array.isArray(rawTxs)) {
229
+ log.warn(tag, "rawTxs is not an array, returning empty array");
230
+ return [];
231
+ }
232
+ return rawTxs.map(function (tx) {
233
+ var _a, _b, _c, _d;
234
+ // Determine direction based on isOwn flags
235
+ var hasOwnInput = (_a = tx.vin) === null || _a === void 0 ? void 0 : _a.some(function (input) { return input.isOwn; });
236
+ var hasOwnOutput = (_b = tx.vout) === null || _b === void 0 ? void 0 : _b.some(function (output) { return output.isOwn; });
237
+ var direction;
238
+ if (hasOwnInput && hasOwnOutput) {
239
+ direction = 'self';
240
+ }
241
+ else if (hasOwnInput) {
242
+ direction = 'sent';
243
+ }
244
+ else {
245
+ direction = 'received';
246
+ }
247
+ return {
248
+ txid: tx.txid,
249
+ caip: caip,
250
+ networkId: caipToNetworkId(caip),
251
+ direction: direction,
252
+ type: 'transfer',
253
+ status: tx.confirmations > 0 ? 'confirmed' : 'pending',
254
+ blockHeight: tx.blockHeight,
255
+ timestamp: tx.blockTime,
256
+ confirmations: tx.confirmations,
257
+ from: ((_c = tx.vin) === null || _c === void 0 ? void 0 : _c.flatMap(function (i) { return i.addresses || []; })) || [],
258
+ to: ((_d = tx.vout) === null || _d === void 0 ? void 0 : _d.flatMap(function (o) { return o.addresses || []; })) || [],
259
+ value: tx.value || '0',
260
+ fee: tx.fees,
261
+ memo: undefined,
262
+ raw: tx
263
+ };
264
+ });
265
+ };
266
+ History.prototype.normalizeEvmTransactions = function (rawTxs, userAddress, caip) {
267
+ var tag = TAG + " | normalizeEvmTransactions | ";
268
+ if (!Array.isArray(rawTxs)) {
269
+ log.warn(tag, "rawTxs is not an array, returning empty array");
270
+ return [];
271
+ }
272
+ return rawTxs.map(function (tx) {
273
+ var _a;
274
+ var direction = ((_a = tx.from) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === userAddress.toLowerCase()
275
+ ? 'sent'
276
+ : 'received';
277
+ // Parse timestamp - handle both ISO string and Unix timestamp formats
278
+ var timestamp;
279
+ if (tx.timestamp) {
280
+ if (typeof tx.timestamp === 'string') {
281
+ // ISO string format from eth-network - convert to Unix timestamp
282
+ timestamp = Math.floor(new Date(tx.timestamp).getTime() / 1000);
283
+ }
284
+ else {
285
+ // Already a Unix timestamp number
286
+ timestamp = parseInt(tx.timestamp);
287
+ }
288
+ }
289
+ else if (tx.timeStamp) {
290
+ timestamp = parseInt(tx.timeStamp);
291
+ }
292
+ else {
293
+ timestamp = Math.floor(Date.now() / 1000);
294
+ }
295
+ return {
296
+ txid: tx.hash || tx.txid,
297
+ caip: caip,
298
+ networkId: caipToNetworkId(caip),
299
+ direction: direction,
300
+ type: tx.contractAddress ? 'token_transfer' : 'transfer',
301
+ status: tx.status === 'success' || tx.status === '1' ? 'confirmed' : 'failed',
302
+ blockHeight: tx.blockNumber ? parseInt(tx.blockNumber) : undefined,
303
+ timestamp: timestamp,
304
+ confirmations: tx.confirmations,
305
+ from: tx.from ? [tx.from] : [],
306
+ to: tx.to ? [tx.to] : [],
307
+ value: tx.value || '0',
308
+ fee: tx.gasUsed && tx.gasPrice
309
+ ? (BigInt(tx.gasUsed) * BigInt(tx.gasPrice)).toString()
310
+ : undefined,
311
+ memo: undefined,
312
+ raw: tx
313
+ };
314
+ });
315
+ };
316
+ History.prototype.normalizeTendermintTransactions = function (rawTxs, userAddress, caip) {
317
+ var tag = TAG + " | normalizeTendermintTransactions | ";
318
+ if (!Array.isArray(rawTxs)) {
319
+ log.warn(tag, "rawTxs is not an array, returning empty array");
320
+ return [];
321
+ }
322
+ return rawTxs.map(function (tx) {
323
+ var _a, _b;
324
+ return ({
325
+ txid: tx.txid || tx.txhash || tx.hash,
326
+ caip: caip,
327
+ networkId: caipToNetworkId(caip),
328
+ direction: 'received', // TODO: Determine from messages
329
+ type: tx.type || 'transfer',
330
+ status: tx.status === 'success' || tx.code === 0 ? 'confirmed' : 'failed',
331
+ blockHeight: tx.height || tx.blockHeight,
332
+ timestamp: tx.timestamp ? (typeof tx.timestamp === 'string' ? new Date(tx.timestamp).getTime() / 1000 : tx.timestamp) : Date.now() / 1000,
333
+ confirmations: undefined,
334
+ from: [], // TODO: Extract from messages
335
+ to: [], // TODO: Extract from messages
336
+ value: '0', // TODO: Extract from messages
337
+ fee: undefined,
338
+ memo: tx.memo || ((_b = (_a = tx.tx) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.memo),
339
+ raw: tx
340
+ });
341
+ });
342
+ };
343
+ History.prototype.normalizeRippleTransactions = function (rawTxs, userAddress, caip) {
344
+ var tag = TAG + " | normalizeRippleTransactions | ";
345
+ if (!Array.isArray(rawTxs)) {
346
+ log.warn(tag, "rawTxs is not an array, returning empty array");
347
+ return [];
348
+ }
349
+ return rawTxs.map(function (tx) {
350
+ var _a, _b;
351
+ var txData = tx.tx || tx;
352
+ var direction = ((_a = txData.Account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === userAddress.toLowerCase()
353
+ ? 'sent'
354
+ : 'received';
355
+ return {
356
+ txid: txData.hash || tx.hash,
357
+ caip: caip,
358
+ networkId: caipToNetworkId(caip),
359
+ direction: direction,
360
+ type: 'transfer',
361
+ status: tx.validated || ((_b = tx.meta) === null || _b === void 0 ? void 0 : _b.TransactionResult) === 'tesSUCCESS' ? 'confirmed' : 'pending',
362
+ blockHeight: tx.ledger_index || tx.ledgerIndex,
363
+ timestamp: txData.date ? txData.date + 946684800 : Date.now() / 1000, // Ripple epoch offset
364
+ confirmations: tx.validated ? 1 : 0,
365
+ from: txData.Account ? [txData.Account] : [],
366
+ to: txData.Destination ? [txData.Destination] : [],
367
+ value: txData.Amount || '0',
368
+ fee: txData.Fee,
369
+ memo: txData.Memos ? JSON.stringify(txData.Memos) : undefined,
370
+ raw: tx
371
+ };
372
+ });
373
+ };
374
+ History.prototype.getHistory = function (query, options) {
375
+ return __awaiter(this, void 0, void 0, function () {
376
+ var tag, queries, results, _i, queries_1, q, networkId, type, asset, pubkey, _a, networkIdToSymbol, coin, rawTxs, rawTxs, rawTxs, rawTxs, error_1;
377
+ return __generator(this, function (_b) {
378
+ switch (_b.label) {
379
+ case 0:
380
+ tag = TAG + " | getHistory | ";
381
+ log.debug(tag, "🔍 HISTORY QUERY START");
382
+ queries = Array.isArray(query) ? query : [query];
383
+ log.debug(tag, "Processing ".concat(queries.length, " ").concat(queries.length === 1 ? 'query' : 'queries'));
384
+ results = [];
385
+ _i = 0, queries_1 = queries;
386
+ _b.label = 1;
387
+ case 1:
388
+ if (!(_i < queries_1.length)) return [3 /*break*/, 30];
389
+ q = queries_1[_i];
390
+ // Input validation - FAIL FAST
391
+ if (!q.caip)
392
+ throw new Error("caip required!");
393
+ if (!q.pubkey)
394
+ throw new Error("pubkey required!");
395
+ log.debug(tag, "Query:", { caip: q.caip, pubkey: q.pubkey.substring(0, 20) + '...' });
396
+ networkId = caipToNetworkId(q.caip);
397
+ return [4 /*yield*/, this.classifyCaip(q.caip)];
398
+ case 2:
399
+ type = _b.sent();
400
+ log.debug(tag, "🎯 Classified CAIP type:", type);
401
+ asset = { caip: q.caip };
402
+ pubkey = { pubkey: q.pubkey };
403
+ _b.label = 3;
404
+ case 3:
405
+ _b.trys.push([3, 28, , 29]);
406
+ _a = type;
407
+ switch (_a) {
408
+ case 'UTXO': return [3 /*break*/, 4];
409
+ case 'EIP155': return [3 /*break*/, 6];
410
+ case 'TENDERMINT': return [3 /*break*/, 10];
411
+ case 'OTHER': return [3 /*break*/, 22];
412
+ }
413
+ return [3 /*break*/, 26];
414
+ case 4:
415
+ networkIdToSymbol = {
416
+ 'bip122:000000000019d6689c085ae165831e93': 'BTC',
417
+ 'bip122:000000000000000000651ef99cb9fcbe': 'BCH',
418
+ 'bip122:000007d91d1254d60e2dd1ae58038307': 'DASH',
419
+ 'bip122:00000000001a91e3dace36e2be3bf030': 'DOGE',
420
+ 'bip122:12a765e31ffd4059bada1e25190f6e98': 'LTC',
421
+ 'bip122:4da631f2ac1bed857bd968c67c913978': 'DGB',
422
+ 'bip122:00040fe8ec8471911baa1db1266ea15d': 'ZEC',
423
+ };
424
+ coin = networkIdToSymbol[networkId];
425
+ if (!coin) {
426
+ throw new Error("Unsupported UTXO network ID: ".concat(networkId));
427
+ }
428
+ log.debug(tag, 'Fetching UTXO transactions for', coin);
429
+ return [4 /*yield*/, this.networks.networks.utxo.txsByXpub(coin, pubkey.pubkey)];
430
+ case 5:
431
+ rawTxs = _b.sent();
432
+ log.debug(tag, "Received ".concat((rawTxs === null || rawTxs === void 0 ? void 0 : rawTxs.length) || 0, " UTXO transactions"));
433
+ asset.transactions = this.normalizeUtxoTransactions(rawTxs || [], pubkey.pubkey, q.caip);
434
+ results.push(asset);
435
+ return [3 /*break*/, 27];
436
+ case 6:
437
+ log.debug(tag, 'Fetching EVM transactions for networkId:', networkId);
438
+ if (!this.networks.networks.ethereum.getTransactionsByNetwork) return [3 /*break*/, 8];
439
+ return [4 /*yield*/, this.networks.networks.ethereum.getTransactionsByNetwork(networkId, pubkey.pubkey, options)];
440
+ case 7:
441
+ rawTxs = _b.sent();
442
+ log.debug(tag, "Received ".concat((rawTxs === null || rawTxs === void 0 ? void 0 : rawTxs.length) || 0, " EVM transactions"));
443
+ asset.transactions = this.normalizeEvmTransactions(rawTxs || [], pubkey.pubkey, q.caip);
444
+ return [3 /*break*/, 9];
445
+ case 8:
446
+ log.warn(tag, 'EVM transaction history not available - method not found');
447
+ asset.transactions = [];
448
+ _b.label = 9;
449
+ case 9:
450
+ results.push(asset);
451
+ return [3 /*break*/, 27];
452
+ case 10:
453
+ log.debug(tag, 'Fetching Tendermint transactions for', q.caip);
454
+ rawTxs = [];
455
+ if (!q.caip.startsWith('cosmos:mayachain-mainnet-v1')) return [3 /*break*/, 13];
456
+ if (!this.networks.networks.mayachain.getTransactions) return [3 /*break*/, 12];
457
+ return [4 /*yield*/, this.networks.networks.mayachain.getTransactions(pubkey.pubkey)];
458
+ case 11:
459
+ rawTxs = _b.sent();
460
+ _b.label = 12;
461
+ case 12: return [3 /*break*/, 21];
462
+ case 13:
463
+ if (!q.caip.startsWith('cosmos:osmosis-1')) return [3 /*break*/, 16];
464
+ if (!this.networks.networks.osmosis.getTransactions) return [3 /*break*/, 15];
465
+ return [4 /*yield*/, this.networks.networks.osmosis.getTransactions(pubkey.pubkey)];
466
+ case 14:
467
+ rawTxs = _b.sent();
468
+ _b.label = 15;
469
+ case 15: return [3 /*break*/, 21];
470
+ case 16:
471
+ if (!q.caip.startsWith('cosmos:thorchain-mainnet-v1')) return [3 /*break*/, 19];
472
+ if (!this.networks.networks.thorchain.getTransactions) return [3 /*break*/, 18];
473
+ return [4 /*yield*/, this.networks.networks.thorchain.getTransactions(pubkey.pubkey)];
474
+ case 17:
475
+ rawTxs = _b.sent();
476
+ _b.label = 18;
477
+ case 18: return [3 /*break*/, 21];
478
+ case 19:
479
+ if (!q.caip.startsWith('cosmos:cosmoshub-4')) return [3 /*break*/, 21];
480
+ if (!this.networks.networks.cosmos.getTransactions) return [3 /*break*/, 21];
481
+ return [4 /*yield*/, this.networks.networks.cosmos.getTransactions(pubkey.pubkey)];
482
+ case 20:
483
+ rawTxs = _b.sent();
484
+ _b.label = 21;
485
+ case 21:
486
+ log.debug(tag, "Received ".concat((rawTxs === null || rawTxs === void 0 ? void 0 : rawTxs.length) || 0, " Tendermint transactions"));
487
+ asset.transactions = this.normalizeTendermintTransactions(rawTxs || [], pubkey.pubkey, q.caip);
488
+ results.push(asset);
489
+ return [3 /*break*/, 27];
490
+ case 22:
491
+ if (!(q.caip === 'ripple:4109c6f2045fc7eff4cde8f9905d19c2/slip44:144')) return [3 /*break*/, 25];
492
+ log.debug(tag, 'Fetching Ripple transactions');
493
+ if (!this.networks.networks.ripple.getTransactions) return [3 /*break*/, 24];
494
+ return [4 /*yield*/, this.networks.networks.ripple.getTransactions(pubkey.pubkey)];
495
+ case 23:
496
+ rawTxs = _b.sent();
497
+ log.debug(tag, "Received ".concat((rawTxs === null || rawTxs === void 0 ? void 0 : rawTxs.length) || 0, " Ripple transactions"));
498
+ asset.transactions = this.normalizeRippleTransactions(rawTxs || [], pubkey.pubkey, q.caip);
499
+ return [3 /*break*/, 25];
500
+ case 24:
501
+ log.warn(tag, 'Ripple transaction history not available');
502
+ asset.transactions = [];
503
+ _b.label = 25;
504
+ case 25:
505
+ results.push(asset);
506
+ return [3 /*break*/, 27];
507
+ case 26: throw new Error("FAIL FAST: Unsupported chain type: ".concat(type));
508
+ case 27: return [3 /*break*/, 29];
509
+ case 28:
510
+ error_1 = _b.sent();
511
+ log.error(tag, "Error fetching history for ".concat(q.caip, ":"), error_1);
512
+ // Add empty result so batch processing continues
513
+ asset.transactions = [];
514
+ asset.error = error_1.message;
515
+ results.push(asset);
516
+ return [3 /*break*/, 29];
517
+ case 29:
518
+ _i++;
519
+ return [3 /*break*/, 1];
520
+ case 30:
521
+ log.debug(tag, "✅ HISTORY QUERY COMPLETE");
522
+ // Return single result if single query, array if batch
523
+ return [2 /*return*/, Array.isArray(query) ? results : results[0]];
524
+ }
525
+ });
526
+ });
527
+ };
528
+ return History;
529
+ }());
530
+ exports.History = History;
@@ -0,0 +1,133 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Transaction schema for API responses
4
+ */
5
+ export declare const TransactionSchema: z.ZodObject<{
6
+ txid: z.ZodString;
7
+ caip: z.ZodString;
8
+ networkId: z.ZodString;
9
+ direction: z.ZodEnum<{
10
+ sent: "sent";
11
+ received: "received";
12
+ self: "self";
13
+ }>;
14
+ type: z.ZodEnum<{
15
+ transfer: "transfer";
16
+ token_transfer: "token_transfer";
17
+ swap: "swap";
18
+ stake: "stake";
19
+ unstake: "unstake";
20
+ reward: "reward";
21
+ contract: "contract";
22
+ }>;
23
+ status: z.ZodEnum<{
24
+ confirmed: "confirmed";
25
+ pending: "pending";
26
+ failed: "failed";
27
+ }>;
28
+ blockHeight: z.ZodOptional<z.ZodNumber>;
29
+ timestamp: z.ZodNumber;
30
+ confirmations: z.ZodOptional<z.ZodNumber>;
31
+ from: z.ZodArray<z.ZodString>;
32
+ to: z.ZodArray<z.ZodString>;
33
+ value: z.ZodString;
34
+ fee: z.ZodOptional<z.ZodString>;
35
+ memo: z.ZodOptional<z.ZodString>;
36
+ raw: z.ZodOptional<z.ZodAny>;
37
+ }, z.core.$strip>;
38
+ /**
39
+ * Individual history result schema
40
+ */
41
+ export declare const HistoryResultSchema: z.ZodObject<{
42
+ caip: z.ZodString;
43
+ pubkey: z.ZodString;
44
+ transactions: z.ZodArray<z.ZodObject<{
45
+ txid: z.ZodString;
46
+ caip: z.ZodString;
47
+ networkId: z.ZodString;
48
+ direction: z.ZodEnum<{
49
+ sent: "sent";
50
+ received: "received";
51
+ self: "self";
52
+ }>;
53
+ type: z.ZodEnum<{
54
+ transfer: "transfer";
55
+ token_transfer: "token_transfer";
56
+ swap: "swap";
57
+ stake: "stake";
58
+ unstake: "unstake";
59
+ reward: "reward";
60
+ contract: "contract";
61
+ }>;
62
+ status: z.ZodEnum<{
63
+ confirmed: "confirmed";
64
+ pending: "pending";
65
+ failed: "failed";
66
+ }>;
67
+ blockHeight: z.ZodOptional<z.ZodNumber>;
68
+ timestamp: z.ZodNumber;
69
+ confirmations: z.ZodOptional<z.ZodNumber>;
70
+ from: z.ZodArray<z.ZodString>;
71
+ to: z.ZodArray<z.ZodString>;
72
+ value: z.ZodString;
73
+ fee: z.ZodOptional<z.ZodString>;
74
+ memo: z.ZodOptional<z.ZodString>;
75
+ raw: z.ZodOptional<z.ZodAny>;
76
+ }, z.core.$strip>>;
77
+ fetchedAt: z.ZodNumber;
78
+ fetchedAtISO: z.ZodString;
79
+ page: z.ZodNumber;
80
+ cached: z.ZodBoolean;
81
+ fresh: z.ZodBoolean;
82
+ }, z.core.$strip>;
83
+ /**
84
+ * GetTransactionHistory API response schema
85
+ */
86
+ export declare const TransactionHistoryResponseSchema: z.ZodObject<{
87
+ success: z.ZodBoolean;
88
+ histories: z.ZodArray<z.ZodObject<{
89
+ caip: z.ZodString;
90
+ pubkey: z.ZodString;
91
+ transactions: z.ZodArray<z.ZodObject<{
92
+ txid: z.ZodString;
93
+ caip: z.ZodString;
94
+ networkId: z.ZodString;
95
+ direction: z.ZodEnum<{
96
+ sent: "sent";
97
+ received: "received";
98
+ self: "self";
99
+ }>;
100
+ type: z.ZodEnum<{
101
+ transfer: "transfer";
102
+ token_transfer: "token_transfer";
103
+ swap: "swap";
104
+ stake: "stake";
105
+ unstake: "unstake";
106
+ reward: "reward";
107
+ contract: "contract";
108
+ }>;
109
+ status: z.ZodEnum<{
110
+ confirmed: "confirmed";
111
+ pending: "pending";
112
+ failed: "failed";
113
+ }>;
114
+ blockHeight: z.ZodOptional<z.ZodNumber>;
115
+ timestamp: z.ZodNumber;
116
+ confirmations: z.ZodOptional<z.ZodNumber>;
117
+ from: z.ZodArray<z.ZodString>;
118
+ to: z.ZodArray<z.ZodString>;
119
+ value: z.ZodString;
120
+ fee: z.ZodOptional<z.ZodString>;
121
+ memo: z.ZodOptional<z.ZodString>;
122
+ raw: z.ZodOptional<z.ZodAny>;
123
+ }, z.core.$strip>>;
124
+ fetchedAt: z.ZodNumber;
125
+ fetchedAtISO: z.ZodString;
126
+ page: z.ZodNumber;
127
+ cached: z.ZodBoolean;
128
+ fresh: z.ZodBoolean;
129
+ }, z.core.$strip>>;
130
+ }, z.core.$strip>;
131
+ export type Transaction = z.infer<typeof TransactionSchema>;
132
+ export type HistoryResult = z.infer<typeof HistoryResultSchema>;
133
+ export type TransactionHistoryResponse = z.infer<typeof TransactionHistoryResponseSchema>;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransactionHistoryResponseSchema = exports.HistoryResultSchema = exports.TransactionSchema = void 0;
4
+ var zod_1 = require("zod");
5
+ /**
6
+ * Transaction schema for API responses
7
+ */
8
+ exports.TransactionSchema = zod_1.z.object({
9
+ txid: zod_1.z.string().min(1),
10
+ caip: zod_1.z.string().min(1),
11
+ networkId: zod_1.z.string().min(1),
12
+ direction: zod_1.z.enum(['sent', 'received', 'self']),
13
+ type: zod_1.z.enum(['transfer', 'token_transfer', 'swap', 'stake', 'unstake', 'reward', 'contract']),
14
+ status: zod_1.z.enum(['confirmed', 'pending', 'failed']),
15
+ blockHeight: zod_1.z.number().int().optional(),
16
+ timestamp: zod_1.z.number().positive(),
17
+ confirmations: zod_1.z.number().int().nonnegative().optional(),
18
+ from: zod_1.z.array(zod_1.z.string()),
19
+ to: zod_1.z.array(zod_1.z.string()),
20
+ value: zod_1.z.string(),
21
+ fee: zod_1.z.string().optional(),
22
+ memo: zod_1.z.string().optional(),
23
+ raw: zod_1.z.any().optional(),
24
+ });
25
+ /**
26
+ * Individual history result schema
27
+ */
28
+ exports.HistoryResultSchema = zod_1.z.object({
29
+ caip: zod_1.z.string(),
30
+ pubkey: zod_1.z.string(),
31
+ transactions: zod_1.z.array(exports.TransactionSchema),
32
+ fetchedAt: zod_1.z.number(),
33
+ fetchedAtISO: zod_1.z.string(),
34
+ page: zod_1.z.number(),
35
+ cached: zod_1.z.boolean(),
36
+ fresh: zod_1.z.boolean(),
37
+ });
38
+ /**
39
+ * GetTransactionHistory API response schema
40
+ */
41
+ exports.TransactionHistoryResponseSchema = zod_1.z.object({
42
+ success: zod_1.z.boolean(),
43
+ histories: zod_1.z.array(exports.HistoryResultSchema),
44
+ });
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@pioneer-platform/pioneer-history",
3
+ "version": "0.2.0",
4
+ "description": "Transaction history aggregation across all blockchain networks",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "scripts": {
8
+ "npm": "pnpm i",
9
+ "test": "pnpm run build && node __tests__/test-module.js",
10
+ "lint": "prettier --write '**/**/*.ts'",
11
+ "dev": "pnpm run build && pnpm run test",
12
+ "build": "tsc -p .",
13
+ "build:watch": "pnpm run build && onchange 'src/**/*.ts' -- pnpm run build",
14
+ "prepublish": "pnpm run build",
15
+ "refresh": "rm -rf ./node_modules ./package-lock.json && pnpm install"
16
+ },
17
+ "dependencies": {
18
+ "@pioneer-platform/loggerdog": "workspace:*",
19
+ "@pioneer-platform/utxo-network": "workspace:*",
20
+ "@pioneer-platform/eth-network": "workspace:*",
21
+ "@pioneer-platform/cosmos-network": "workspace:*",
22
+ "@pioneer-platform/osmosis-network": "workspace:*",
23
+ "@pioneer-platform/thor-network": "workspace:*",
24
+ "@pioneer-platform/maya-network": "workspace:*",
25
+ "@pioneer-platform/ripple-network": "workspace:*",
26
+ "@pioneer-platform/solana-network": "workspace:*",
27
+ "@pioneer-platform/tron-network": "workspace:*",
28
+ "@pioneer-platform/ton-network": "workspace:*"
29
+ },
30
+ "devDependencies": {
31
+ "dotenv": "^16.0.0",
32
+ "typescript": "^5.0.0"
33
+ }
34
+ }