@pioneer-platform/pioneer-cache 1.0.2 → 1.0.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @pioneer-platform/pioneer-cache
2
2
 
3
+ ## 1.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - cache work
8
+ - Updated dependencies
9
+ - @pioneer-platform/redis-queue@8.11.1
10
+
3
11
  ## 1.0.2
4
12
 
5
13
  ### Patch Changes
@@ -151,9 +151,10 @@ class BaseCache {
151
151
  const t0 = Date.now();
152
152
  try {
153
153
  // Redis timeout for cache reads
154
- // Increased from 100ms to 2000ms - 100ms was too aggressive and caused false cache misses
155
- // Increased from 2000ms to 10000ms - IPv4/IPv6 DNS resolution can cause delays
156
- const timeoutMs = 10000;
154
+ // PERFORMANCE FIX: Reduced from 10000ms to 100ms
155
+ // Local Redis should respond in <10ms. 100ms timeout prevents cascading failures
156
+ // when Redis is overloaded while still catching actual connection issues.
157
+ const timeoutMs = 100;
157
158
  const cached = await Promise.race([
158
159
  this.redis.get(key),
159
160
  new Promise((resolve) => setTimeout(() => {
@@ -21,7 +21,12 @@ export declare class BalanceCache extends BaseCache<BalanceData> {
21
21
  constructor(redis: any, balanceModule: any, config?: Partial<CacheConfig>);
22
22
  /**
23
23
  * Build Redis key for balance data
24
- * Format: balance_v2:caip:pubkey
24
+ * Format: balance_v2:caip:hashedPubkey
25
+ *
26
+ * PRIVACY: Uses SHA-256 hash of pubkey/xpub instead of plaintext
27
+ * - One-way: cannot recover pubkey from hash
28
+ * - Deterministic: same pubkey always produces same key
29
+ * - Fast: ~0.02ms per hash
25
30
  */
26
31
  protected buildKey(params: Record<string, any>): string;
27
32
  /**
@@ -5,10 +5,42 @@
5
5
  Extends BaseCache with balance-specific logic.
6
6
  All common logic is inherited from BaseCache.
7
7
  */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
8
11
  Object.defineProperty(exports, "__esModule", { value: true });
9
12
  exports.BalanceCache = void 0;
10
13
  const base_cache_1 = require("../core/base-cache");
14
+ const crypto_1 = __importDefault(require("crypto"));
11
15
  const log = require('@pioneer-platform/loggerdog')();
16
+ /**
17
+ * Hash pubkey/xpub for privacy-protecting cache keys
18
+ * Uses SHA-256 for fast, deterministic, one-way hashing
19
+ */
20
+ function hashPubkey(pubkey, salt = '') {
21
+ // Detect if this is an xpub (don't lowercase) or regular address (lowercase)
22
+ const isXpub = pubkey.match(/^[xyz]pub[1-9A-HJ-NP-Za-km-z]{100,}/);
23
+ const normalized = isXpub ? pubkey.trim() : pubkey.trim().toLowerCase();
24
+ const hash = crypto_1.default.createHash('sha256');
25
+ hash.update(normalized);
26
+ if (salt)
27
+ hash.update(salt);
28
+ // Return first 128 bits (32 hex chars) for shorter Redis keys
29
+ return hash.digest('hex').substring(0, 32);
30
+ }
31
+ /**
32
+ * Sanitize pubkey for safe logging
33
+ */
34
+ function sanitizePubkey(pubkey) {
35
+ if (!pubkey || pubkey.length < 12)
36
+ return '[invalid]';
37
+ // Check if xpub (show first 8, last 8)
38
+ if (pubkey.match(/^[xyz]pub/)) {
39
+ return `${pubkey.substring(0, 8)}...${pubkey.substring(pubkey.length - 8)}`;
40
+ }
41
+ // Regular address (show first 6, last 4)
42
+ return `${pubkey.substring(0, 6)}...${pubkey.substring(pubkey.length - 4)}`;
43
+ }
12
44
  /**
13
45
  * BalanceCache - Caches blockchain balance data
14
46
  */
@@ -42,7 +74,12 @@ class BalanceCache extends base_cache_1.BaseCache {
42
74
  }
43
75
  /**
44
76
  * Build Redis key for balance data
45
- * Format: balance_v2:caip:pubkey
77
+ * Format: balance_v2:caip:hashedPubkey
78
+ *
79
+ * PRIVACY: Uses SHA-256 hash of pubkey/xpub instead of plaintext
80
+ * - One-way: cannot recover pubkey from hash
81
+ * - Deterministic: same pubkey always produces same key
82
+ * - Fast: ~0.02ms per hash
46
83
  */
47
84
  buildKey(params) {
48
85
  const { caip, pubkey } = params;
@@ -50,9 +87,9 @@ class BalanceCache extends base_cache_1.BaseCache {
50
87
  throw new Error('BalanceCache.buildKey: caip and pubkey required');
51
88
  }
52
89
  const normalizedCaip = caip.toLowerCase();
53
- // Don't lowercase pubkeys - xpub/ypub/zpub are case-sensitive base58
54
- const normalizedPubkey = pubkey;
55
- return `${this.config.keyPrefix}${normalizedCaip}:${normalizedPubkey}`;
90
+ // Hash pubkey for privacy protection
91
+ const hashedPubkey = hashPubkey(pubkey, caip);
92
+ return `${this.config.keyPrefix}${normalizedCaip}:${hashedPubkey}`;
56
93
  }
57
94
  /**
58
95
  * Fetch balance from blockchain via balance module
@@ -61,12 +98,14 @@ class BalanceCache extends base_cache_1.BaseCache {
61
98
  const tag = this.TAG + 'fetchFromSource | ';
62
99
  try {
63
100
  const { caip, pubkey } = params;
64
- // Fetch balance using balance module
101
+ // Log sanitized pubkey for debugging
102
+ log.debug(tag, `Fetching balance for ${caip}/${sanitizePubkey(pubkey)}`);
103
+ // Fetch balance using balance module (still uses real pubkey)
65
104
  const asset = { caip };
66
105
  const owner = { pubkey };
67
106
  const balanceInfo = await this.balanceModule.getBalance(asset, owner);
68
107
  if (!balanceInfo || !balanceInfo.balance) {
69
- log.warn(tag, `No balance returned for ${caip}/${pubkey.substring(0, 10)}...`);
108
+ log.warn(tag, `No balance returned for ${caip}/${sanitizePubkey(pubkey)}`);
70
109
  return {
71
110
  caip,
72
111
  pubkey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pioneer-platform/pioneer-cache",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Unified caching system for Pioneer platform with Redis backend",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -20,9 +20,9 @@
20
20
  "author": "Pioneer Platform",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "@pioneer-platform/loggerdog": "^8.0.0",
24
- "@pioneer-platform/redis-queue": "^8.0.0",
25
- "@pioneer-platform/default-redis": "^8.0.0"
23
+ "@pioneer-platform/loggerdog": "^8.11.0",
24
+ "@pioneer-platform/redis-queue": "^8.11.1",
25
+ "@pioneer-platform/default-redis": "^8.11.7"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^20.0.0",
@@ -185,9 +185,10 @@ export abstract class BaseCache<T> {
185
185
 
186
186
  try {
187
187
  // Redis timeout for cache reads
188
- // Increased from 100ms to 2000ms - 100ms was too aggressive and caused false cache misses
189
- // Increased from 2000ms to 10000ms - IPv4/IPv6 DNS resolution can cause delays
190
- const timeoutMs = 10000;
188
+ // PERFORMANCE FIX: Reduced from 10000ms to 100ms
189
+ // Local Redis should respond in <10ms. 100ms timeout prevents cascading failures
190
+ // when Redis is overloaded while still catching actual connection issues.
191
+ const timeoutMs = 100;
191
192
  const cached = await Promise.race([
192
193
  this.redis.get(key),
193
194
  new Promise<null>((resolve) => setTimeout(() => {
@@ -7,9 +7,42 @@
7
7
 
8
8
  import { BaseCache } from '../core/base-cache';
9
9
  import type { CacheConfig } from '../types';
10
+ import crypto from 'crypto';
10
11
 
11
12
  const log = require('@pioneer-platform/loggerdog')();
12
13
 
14
+ /**
15
+ * Hash pubkey/xpub for privacy-protecting cache keys
16
+ * Uses SHA-256 for fast, deterministic, one-way hashing
17
+ */
18
+ function hashPubkey(pubkey: string, salt: string = ''): string {
19
+ // Detect if this is an xpub (don't lowercase) or regular address (lowercase)
20
+ const isXpub = pubkey.match(/^[xyz]pub[1-9A-HJ-NP-Za-km-z]{100,}/);
21
+ const normalized = isXpub ? pubkey.trim() : pubkey.trim().toLowerCase();
22
+
23
+ const hash = crypto.createHash('sha256');
24
+ hash.update(normalized);
25
+ if (salt) hash.update(salt);
26
+
27
+ // Return first 128 bits (32 hex chars) for shorter Redis keys
28
+ return hash.digest('hex').substring(0, 32);
29
+ }
30
+
31
+ /**
32
+ * Sanitize pubkey for safe logging
33
+ */
34
+ function sanitizePubkey(pubkey: string): string {
35
+ if (!pubkey || pubkey.length < 12) return '[invalid]';
36
+
37
+ // Check if xpub (show first 8, last 8)
38
+ if (pubkey.match(/^[xyz]pub/)) {
39
+ return `${pubkey.substring(0, 8)}...${pubkey.substring(pubkey.length - 8)}`;
40
+ }
41
+
42
+ // Regular address (show first 6, last 4)
43
+ return `${pubkey.substring(0, 6)}...${pubkey.substring(pubkey.length - 4)}`;
44
+ }
45
+
13
46
  /**
14
47
  * Balance data structure
15
48
  */
@@ -61,7 +94,12 @@ export class BalanceCache extends BaseCache<BalanceData> {
61
94
 
62
95
  /**
63
96
  * Build Redis key for balance data
64
- * Format: balance_v2:caip:pubkey
97
+ * Format: balance_v2:caip:hashedPubkey
98
+ *
99
+ * PRIVACY: Uses SHA-256 hash of pubkey/xpub instead of plaintext
100
+ * - One-way: cannot recover pubkey from hash
101
+ * - Deterministic: same pubkey always produces same key
102
+ * - Fast: ~0.02ms per hash
65
103
  */
66
104
  protected buildKey(params: Record<string, any>): string {
67
105
  const { caip, pubkey } = params;
@@ -70,10 +108,11 @@ export class BalanceCache extends BaseCache<BalanceData> {
70
108
  }
71
109
 
72
110
  const normalizedCaip = caip.toLowerCase();
73
- // Don't lowercase pubkeys - xpub/ypub/zpub are case-sensitive base58
74
- const normalizedPubkey = pubkey;
75
111
 
76
- return `${this.config.keyPrefix}${normalizedCaip}:${normalizedPubkey}`;
112
+ // Hash pubkey for privacy protection
113
+ const hashedPubkey = hashPubkey(pubkey, caip);
114
+
115
+ return `${this.config.keyPrefix}${normalizedCaip}:${hashedPubkey}`;
77
116
  }
78
117
 
79
118
  /**
@@ -85,13 +124,16 @@ export class BalanceCache extends BaseCache<BalanceData> {
85
124
  try {
86
125
  const { caip, pubkey } = params;
87
126
 
88
- // Fetch balance using balance module
127
+ // Log sanitized pubkey for debugging
128
+ log.debug(tag, `Fetching balance for ${caip}/${sanitizePubkey(pubkey)}`);
129
+
130
+ // Fetch balance using balance module (still uses real pubkey)
89
131
  const asset = { caip };
90
132
  const owner = { pubkey };
91
133
  const balanceInfo = await this.balanceModule.getBalance(asset, owner);
92
134
 
93
135
  if (!balanceInfo || !balanceInfo.balance) {
94
- log.warn(tag, `No balance returned for ${caip}/${pubkey.substring(0, 10)}...`);
136
+ log.warn(tag, `No balance returned for ${caip}/${sanitizePubkey(pubkey)}`);
95
137
  return {
96
138
  caip,
97
139
  pubkey,