@gvnrdao/dh-sdk 0.0.205 → 0.0.206

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/dist/index.mjs CHANGED
@@ -12968,68 +12968,66 @@ var init_deployment_addresses = __esm({
12968
12968
  LOCALHOST_DEPLOYMENT = {
12969
12969
  network: "localhost",
12970
12970
  chainId: 31337,
12971
- timestamp: "2026-04-23T13:26:13.607Z",
12971
+ timestamp: "2026-03-23T15:33:34.068Z",
12972
12972
  deployer: "",
12973
12973
  contracts: {
12974
- MessageHashBuilder: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
12975
- UpgradeValidator: "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
12974
+ MessageHashBuilder: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
12975
+ UpgradeValidator: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
12976
12976
  UCDToken: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
12977
12977
  UCDController: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
12978
- PositionManagerCoreModule: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
12979
- TermManagerModule: "0x9A676e781A523b5d0C0e43731313A708CB607508",
12980
- LoanOperationsManagerModule: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
12978
+ PositionManagerCoreModule: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
12979
+ TermManagerModule: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
12980
+ LoanOperationsManagerModule: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
12981
12981
  BTCSpendAuthorizer: "0x59b670e9fA9D0A427751Af201D676719a970857b",
12982
12982
  CollateralManagerModule: "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
12983
12983
  LiquidationManagerModule: "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
12984
- CircuitBreakerModule: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
12984
+ CircuitBreakerModule: "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
12985
12985
  AdminModule: "0xc5a5C42992dECbae36851359345FE25997F5C42d",
12986
- PositionManagerViews: "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
12987
- PositionManager: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
12988
- OperationAuthorizationRegistry: "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f",
12989
- PKPValidation: "0x04C89607413713Ec9775E14b954286519d836FEf"
12986
+ PositionManagerViews: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
12987
+ PositionManager: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
12988
+ OperationAuthorizationRegistry: "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0",
12989
+ PKPValidation: "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc"
12990
12990
  },
12991
12991
  latestEnv: {
12992
12992
  UCD_TOKEN: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
12993
12993
  UCD_CONTROLLER: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
12994
- POSITION_MANAGER: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
12995
- PKP_VALIDATION_REGISTRY: "0x04C89607413713Ec9775E14b954286519d836FEf",
12996
- PKP_VALIDATION_CID_V1: "0x12200ba1a8948ea70b30205d738407bc9ed00ccb456bf78d8cad1a7574eafd3da24b",
12997
- PKP_VALIDATION_CID_V3: "0x12200ba1a8948ea70b30205d738407bc9ed00ccb456bf78d8cad1a7574eafd3da24b",
12998
- PKP_ETH_ADDRESS: "0xBC9de87F56856F0D424d705911c07dE213544172",
12999
- OPERATION_AUTHORIZATION_REGISTRY: "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f",
13000
- UCD_MINT_VALIDATOR_ADDRESS: "0xC6E57a5d65e43910Fe70667C97D193FAF6dDF598",
12994
+ POSITION_MANAGER: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
12995
+ PKP_VALIDATION_REGISTRY: "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc",
12996
+ PKP_VALIDATION_CID_V1: "QmfHJKA4RnW7RepsdLmrDwKjVTzPXB2K3qMTco3JNPDexm",
12997
+ PKP_ETH_ADDRESS: "0x9624C46073E1d1F5AB975c67Fc899536d599bb57",
12998
+ OPERATION_AUTHORIZATION_REGISTRY: "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0",
12999
+ UCD_MINT_VALIDATOR_ADDRESS: "0x80f81afb9e6dF27afCD752ad46cD286e705e42be",
13001
13000
  UCD_MINT_VALIDATOR_VERSION: 1,
13002
- BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0xe3B7bc797fA187AB9e29266bE8E01d58Cd49A6E9",
13001
+ BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0xa751ad81E1CAe61d6cF5Cf64839Fe8D28A1372Df",
13003
13002
  BTC_WITHDRAWAL_VALIDATOR_VERSION: 1,
13004
- UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x9e1831004c7ccf088468dC18F70b1B80c6Ec0c56",
13003
+ UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x8A40C22B03348bc10df9ae0dc54346b4AE8e909c",
13005
13004
  UPDATE_BALANCE_VALIDATOR_VERSION: 1,
13006
- PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x2297DabE0220a999d01B5BB603Ff2433CF908043",
13005
+ PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x28f50E07532d3aF677b8E0bcF220422d159b0dd6",
13007
13006
  PROCESS_PAYMENT_VALIDATOR_VERSION: 1,
13008
- EXTEND_POSITION_VALIDATOR_ADDRESS: "0x57d0f6E62b8f592dd23DEbD5F60dDEc843cd1835",
13007
+ EXTEND_POSITION_VALIDATOR_ADDRESS: "0xc7aC43F2F907123465449575e853f5D0229898e1",
13009
13008
  EXTEND_POSITION_VALIDATOR_VERSION: 1,
13010
- POSITION_MANAGER_CORE_MODULE: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
13011
- LOAN_OPERATIONS_MANAGER_MODULE: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
13012
- TERM_MANAGER_MODULE: "0x9A676e781A523b5d0C0e43731313A708CB607508",
13013
- COMMUNITY_MANAGER_MODULE: ""
13009
+ POSITION_MANAGER_CORE_MODULE: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
13010
+ LOAN_OPERATIONS_MANAGER_MODULE: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
13011
+ TERM_MANAGER_MODULE: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82"
13014
13012
  }
13015
13013
  };
13016
13014
  LOCALHOST_CONTRACTS = {
13017
- MessageHashBuilder: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
13018
- UpgradeValidator: "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
13015
+ MessageHashBuilder: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
13016
+ UpgradeValidator: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
13019
13017
  UCDToken: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
13020
13018
  UCDController: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
13021
- PositionManagerCoreModule: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
13022
- TermManagerModule: "0x9A676e781A523b5d0C0e43731313A708CB607508",
13023
- LoanOperationsManagerModule: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
13019
+ PositionManagerCoreModule: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
13020
+ TermManagerModule: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
13021
+ LoanOperationsManagerModule: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
13024
13022
  BTCSpendAuthorizer: "0x59b670e9fA9D0A427751Af201D676719a970857b",
13025
13023
  CollateralManagerModule: "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
13026
13024
  LiquidationManagerModule: "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
13027
- CircuitBreakerModule: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
13025
+ CircuitBreakerModule: "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
13028
13026
  AdminModule: "0xc5a5C42992dECbae36851359345FE25997F5C42d",
13029
- PositionManagerViews: "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
13030
- PositionManager: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
13031
- OperationAuthorizationRegistry: "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f",
13032
- PKPValidation: "0x04C89607413713Ec9775E14b954286519d836FEf"
13027
+ PositionManagerViews: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
13028
+ PositionManager: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
13029
+ OperationAuthorizationRegistry: "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0",
13030
+ PKPValidation: "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc"
13033
13031
  };
13034
13032
  ALL_DEPLOYMENTS = {
13035
13033
  sepolia: SEPOLIA_DEPLOYMENT,
@@ -29493,8 +29491,6 @@ function validateQuantumTiming(signedTimestamp, _bufferSeconds = 30) {
29493
29491
  var PKP_NFT_ABI = [
29494
29492
  "function getPubkey(uint256 tokenId) external view returns (bytes memory)"
29495
29493
  ];
29496
- var CHIPOTLE_RPC_URL = "https://yellowstone-rpc.litprotocol.com";
29497
- var CHIPOTLE_CHAIN_ID = 175188;
29498
29494
  async function generateMintAuthorization(positionId, amount, chainId, signerOrPrecomputed) {
29499
29495
  if (typeof signerOrPrecomputed === "object" && "signature" in signerOrPrecomputed && !("signMessage" in signerOrPrecomputed)) {
29500
29496
  const { timestamp: timestamp2, signature: signature3 } = signerOrPrecomputed;
@@ -29594,18 +29590,14 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signer)
29594
29590
  };
29595
29591
  }
29596
29592
  async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAddress) {
29597
- const targetRpc = CHIPOTLE_RPC_URL;
29598
- const targetChainId = CHIPOTLE_CHAIN_ID;
29599
- let litChainProvider;
29600
- if (provider) {
29601
- const network = await provider.getNetwork();
29602
- if (network.chainId === targetChainId) {
29603
- litChainProvider = provider;
29604
- } else {
29605
- litChainProvider = new ethers_exports.providers.JsonRpcProvider(targetRpc);
29606
- }
29607
- } else {
29608
- litChainProvider = new ethers_exports.providers.JsonRpcProvider(targetRpc);
29593
+ const rawHex = pkpTokenId.startsWith("0x") ? pkpTokenId.slice(2) : pkpTokenId;
29594
+ if (rawHex.length === 64 && rawHex.startsWith("000000000000000000000000") && rawHex !== "0".repeat(64)) {
29595
+ throw new Error(
29596
+ `pkpId ${pkpTokenId} is a Chipotle wallet address (ABI-encoded ETH address). Chipotle PKPs are not NFTs and have no on-chain public key lookup. Ensure the PKP public key is populated in cache during position creation.`
29597
+ );
29598
+ }
29599
+ if (!provider) {
29600
+ throw new Error(`provider is required for getPKPPublicKeyFromTokenId`);
29609
29601
  }
29610
29602
  if (!pkpNftContractAddress) {
29611
29603
  throw new Error(
@@ -29615,7 +29607,7 @@ async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAd
29615
29607
  const pkpNft = new ethers_exports.Contract(
29616
29608
  pkpNftContractAddress,
29617
29609
  PKP_NFT_ABI,
29618
- litChainProvider
29610
+ provider
29619
29611
  );
29620
29612
  const tokenIdBN = ethers_exports.BigNumber.from(pkpTokenId);
29621
29613
  const pubkeyBytes = await pkpNft["getPubkey"](tokenIdBN);
@@ -30220,106 +30212,333 @@ function createContractManager(config) {
30220
30212
  }
30221
30213
 
30222
30214
  // src/modules/cache/cache-manager.module.ts
30223
- var Cache = class {
30224
- cache = /* @__PURE__ */ new Map();
30215
+ var LRUCache = class {
30216
+ cache;
30225
30217
  maxSize;
30226
30218
  ttlMs;
30227
- constructor(config) {
30228
- this.maxSize = config.maxSize;
30229
- this.ttlMs = config.ttlMs;
30219
+ debug;
30220
+ name;
30221
+ // Statistics
30222
+ stats = {
30223
+ hits: 0,
30224
+ misses: 0,
30225
+ evictions: 0
30226
+ };
30227
+ constructor(config = {}) {
30228
+ this.cache = /* @__PURE__ */ new Map();
30229
+ this.maxSize = config.maxSize || 1e3;
30230
+ this.ttlMs = config.ttlMs || 6e4;
30231
+ this.debug = config.debug || false;
30232
+ this.name = config.name || "Cache";
30233
+ if (this.debug) {
30234
+ console.log(
30235
+ `\u{1F4BE} [${this.name}] Initialized: maxSize=${this.maxSize}, ttl=${this.ttlMs}ms`
30236
+ );
30237
+ }
30230
30238
  }
30231
30239
  /**
30232
30240
  * Get value from cache
30241
+ *
30242
+ * Returns null if:
30243
+ * - Key not found
30244
+ * - Entry has expired
30245
+ *
30246
+ * @param key - Cache key
30247
+ * @returns Cached value or null
30233
30248
  */
30234
30249
  get(key2) {
30235
30250
  const entry = this.cache.get(key2);
30236
30251
  if (!entry) {
30237
- return void 0;
30252
+ this.stats.misses++;
30253
+ if (this.debug) {
30254
+ console.log(`\u274C [${this.name}] Cache MISS: ${String(key2)}`);
30255
+ }
30256
+ return null;
30238
30257
  }
30239
- const now2 = Date.now();
30240
- if (now2 - entry.timestamp > entry.ttl) {
30258
+ if (this.isExpired(entry)) {
30241
30259
  this.cache.delete(key2);
30242
- return void 0;
30260
+ this.stats.misses++;
30261
+ if (this.debug) {
30262
+ const age = Date.now() - entry.timestamp;
30263
+ console.log(`\u23F0 [${this.name}] Cache EXPIRED: ${String(key2)} (age: ${age}ms)`);
30264
+ }
30265
+ return null;
30266
+ }
30267
+ entry.hits++;
30268
+ entry.lastAccessed = Date.now();
30269
+ this.cache.set(key2, entry);
30270
+ this.stats.hits++;
30271
+ if (this.debug) {
30272
+ const age = Date.now() - entry.timestamp;
30273
+ console.log(
30274
+ `\u2705 [${this.name}] Cache HIT: ${String(key2)} (age: ${age}ms, hits: ${entry.hits})`
30275
+ );
30243
30276
  }
30244
30277
  return entry.value;
30245
30278
  }
30279
+ /**
30280
+ * Get value from cache with Result wrapper
30281
+ *
30282
+ * Useful when you want to distinguish between "not found" and "expired"
30283
+ */
30284
+ getResult(key2) {
30285
+ const value = this.get(key2);
30286
+ if (value === null) {
30287
+ return failure(
30288
+ new SDKError({
30289
+ message: `Cache miss for key: ${String(key2)}`,
30290
+ category: "CACHE" /* CACHE */,
30291
+ severity: "LOW" /* LOW */,
30292
+ originalError: new Error("Cache miss")
30293
+ })
30294
+ );
30295
+ }
30296
+ return success(value);
30297
+ }
30246
30298
  /**
30247
30299
  * Set value in cache
30300
+ *
30301
+ * If cache is full, evicts the least recently used entry
30302
+ *
30303
+ * @param key - Cache key
30304
+ * @param value - Value to cache
30305
+ * @param ttl - Optional custom TTL for this entry (ms)
30248
30306
  */
30249
30307
  set(key2, value, ttl) {
30250
30308
  if (this.cache.size >= this.maxSize && !this.cache.has(key2)) {
30251
- const firstKey = this.cache.keys().next().value;
30252
- if (firstKey) {
30253
- this.cache.delete(firstKey);
30254
- }
30309
+ this.evictLRU();
30255
30310
  }
30256
- this.cache.set(key2, {
30311
+ const entry = {
30257
30312
  value,
30258
30313
  timestamp: Date.now(),
30259
- ttl: ttl || this.ttlMs
30260
- });
30314
+ hits: 0,
30315
+ lastAccessed: Date.now()
30316
+ };
30317
+ this.cache.set(key2, entry);
30318
+ if (this.debug) {
30319
+ const effectiveTtl = ttl || this.ttlMs;
30320
+ console.log(
30321
+ `\u{1F4BE} [${this.name}] Cache SET: ${String(key2)} (ttl: ${effectiveTtl}ms, size: ${this.cache.size}/${this.maxSize})`
30322
+ );
30323
+ }
30261
30324
  }
30262
30325
  /**
30263
- * Check if key exists in cache
30326
+ * Set value in cache with Result wrapper
30327
+ */
30328
+ setResult(key2, value, ttl) {
30329
+ try {
30330
+ this.set(key2, value, ttl);
30331
+ return success(void 0);
30332
+ } catch (error) {
30333
+ return failure(
30334
+ new SDKError({
30335
+ message: `Failed to set cache value for key: ${String(key2)}`,
30336
+ category: "CACHE" /* CACHE */,
30337
+ severity: "MEDIUM" /* MEDIUM */,
30338
+ originalError: error instanceof Error ? error : new Error(String(error))
30339
+ })
30340
+ );
30341
+ }
30342
+ }
30343
+ /**
30344
+ * Check if key exists in cache (without affecting stats)
30264
30345
  */
30265
30346
  has(key2) {
30266
- return this.get(key2) !== void 0;
30347
+ const entry = this.cache.get(key2);
30348
+ return entry !== void 0 && !this.isExpired(entry);
30267
30349
  }
30268
30350
  /**
30269
- * Delete key from cache
30351
+ * Delete specific key from cache
30270
30352
  */
30271
30353
  delete(key2) {
30272
- return this.cache.delete(key2);
30354
+ const deleted = this.cache.delete(key2);
30355
+ if (deleted && this.debug) {
30356
+ console.log(`\u{1F5D1}\uFE0F [${this.name}] Cache DELETE: ${String(key2)}`);
30357
+ }
30358
+ return deleted;
30273
30359
  }
30274
30360
  /**
30275
- * Clear all cache entries
30361
+ * Clear entire cache
30276
30362
  */
30277
30363
  clear() {
30364
+ const previousSize = this.cache.size;
30278
30365
  this.cache.clear();
30366
+ this.stats = {
30367
+ hits: 0,
30368
+ misses: 0,
30369
+ evictions: 0
30370
+ };
30371
+ if (this.debug) {
30372
+ console.log(`\u{1F9F9} [${this.name}] Cache CLEARED: removed ${previousSize} entries`);
30373
+ }
30374
+ }
30375
+ /**
30376
+ * Get current cache size
30377
+ */
30378
+ size() {
30379
+ return this.cache.size;
30380
+ }
30381
+ /**
30382
+ * Get cache statistics
30383
+ */
30384
+ getStats() {
30385
+ const entries = Array.from(this.cache.values());
30386
+ const timestamps = entries.map((e) => e.timestamp);
30387
+ const total = this.stats.hits + this.stats.misses;
30388
+ const hitRate = total === 0 ? 0 : this.stats.hits / total * 100;
30389
+ return {
30390
+ size: this.cache.size,
30391
+ hits: this.stats.hits,
30392
+ misses: this.stats.misses,
30393
+ evictions: this.stats.evictions,
30394
+ oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : 0,
30395
+ newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : 0,
30396
+ hitRate
30397
+ };
30398
+ }
30399
+ /**
30400
+ * Get hit rate percentage
30401
+ */
30402
+ getHitRate() {
30403
+ const total = this.stats.hits + this.stats.misses;
30404
+ return total === 0 ? 0 : this.stats.hits / total * 100;
30405
+ }
30406
+ /**
30407
+ * Get all cached keys (for debugging)
30408
+ */
30409
+ getKeys() {
30410
+ return Array.from(this.cache.keys());
30411
+ }
30412
+ /**
30413
+ * Get all cached values (for debugging)
30414
+ */
30415
+ getValues() {
30416
+ return Array.from(this.cache.values()).map((entry) => entry.value);
30417
+ }
30418
+ /**
30419
+ * Get all cache entries with metadata (for debugging)
30420
+ */
30421
+ getEntries() {
30422
+ return Array.from(this.cache.entries()).map(([key2, entry]) => ({
30423
+ key: key2,
30424
+ value: entry.value,
30425
+ metadata: {
30426
+ timestamp: entry.timestamp,
30427
+ hits: entry.hits,
30428
+ lastAccessed: entry.lastAccessed
30429
+ }
30430
+ }));
30279
30431
  }
30280
30432
  /**
30281
- * Clean expired entries
30433
+ * Clean up expired entries
30434
+ *
30435
+ * Useful for periodic maintenance
30436
+ *
30437
+ * @returns Number of entries cleaned
30282
30438
  */
30283
30439
  cleanExpired() {
30284
30440
  const now2 = Date.now();
30285
- let cleaned = 0;
30441
+ let cleanedCount = 0;
30286
30442
  for (const [key2, entry] of this.cache.entries()) {
30287
- if (now2 - entry.timestamp > entry.ttl) {
30443
+ if (now2 - entry.timestamp > this.ttlMs) {
30288
30444
  this.cache.delete(key2);
30289
- cleaned++;
30445
+ cleanedCount++;
30290
30446
  }
30291
30447
  }
30292
- return cleaned;
30448
+ if (cleanedCount > 0 && this.debug) {
30449
+ console.log(`\u{1F9F9} [${this.name}] Cleaned ${cleanedCount} expired entries`);
30450
+ }
30451
+ return cleanedCount;
30293
30452
  }
30294
30453
  /**
30295
- * Get cache statistics
30454
+ * Check if cache entry is expired
30296
30455
  */
30297
- getStats() {
30298
- return {
30299
- size: this.cache.size,
30300
- maxSize: this.maxSize,
30301
- ttlMs: this.ttlMs
30302
- };
30456
+ isExpired(entry) {
30457
+ return Date.now() - entry.timestamp > this.ttlMs;
30458
+ }
30459
+ /**
30460
+ * Evict least recently used entry
30461
+ */
30462
+ evictLRU() {
30463
+ let oldestKey = null;
30464
+ let oldestAccess = Infinity;
30465
+ for (const [key2, entry] of this.cache.entries()) {
30466
+ if (entry.lastAccessed < oldestAccess) {
30467
+ oldestAccess = entry.lastAccessed;
30468
+ oldestKey = key2;
30469
+ }
30470
+ }
30471
+ if (oldestKey !== null) {
30472
+ this.cache.delete(oldestKey);
30473
+ this.stats.evictions++;
30474
+ if (this.debug) {
30475
+ const timeSinceAccess = Date.now() - oldestAccess;
30476
+ console.log(
30477
+ `\u267B\uFE0F [${this.name}] Cache EVICT (LRU): ${String(oldestKey)} (last accessed: ${timeSinceAccess}ms ago)`
30478
+ );
30479
+ }
30480
+ }
30481
+ }
30482
+ /**
30483
+ * Get or compute value
30484
+ *
30485
+ * If key exists in cache, returns cached value.
30486
+ * Otherwise, computes value using provided function and caches it.
30487
+ *
30488
+ * @param key - Cache key
30489
+ * @param compute - Function to compute value if not in cache
30490
+ * @param ttl - Optional custom TTL for this entry
30491
+ * @returns Cached or computed value
30492
+ */
30493
+ async getOrCompute(key2, compute, ttl) {
30494
+ const cached = this.get(key2);
30495
+ if (cached !== null) {
30496
+ return cached;
30497
+ }
30498
+ const value = await compute();
30499
+ this.set(key2, value, ttl);
30500
+ return value;
30501
+ }
30502
+ /**
30503
+ * Get or compute value with Result wrapper
30504
+ */
30505
+ async getOrComputeResult(key2, compute, ttl) {
30506
+ const cached = this.get(key2);
30507
+ if (cached !== null) {
30508
+ return success(cached);
30509
+ }
30510
+ const result = await compute();
30511
+ if (result.success) {
30512
+ this.set(key2, result.value, ttl);
30513
+ }
30514
+ return result;
30303
30515
  }
30304
30516
  };
30305
30517
  var CacheManager = class {
30306
30518
  caches = /* @__PURE__ */ new Map();
30307
- debug;
30308
- constructor(config = {}) {
30309
- this.debug = config.debug || false;
30519
+ globalConfig;
30520
+ constructor(globalConfig = {}) {
30521
+ this.globalConfig = globalConfig;
30310
30522
  }
30311
30523
  /**
30312
- * Get or create a cache instance
30524
+ * Create or get a named cache
30525
+ *
30526
+ * @param name - Unique cache name
30527
+ * @param config - Optional cache-specific configuration
30528
+ * @returns LRU cache instance
30313
30529
  */
30314
30530
  getCache(name, config) {
30315
- if (this.caches.has(name)) {
30316
- return this.caches.get(name);
30531
+ const existingCache = this.caches.get(name);
30532
+ if (existingCache) {
30533
+ return existingCache;
30317
30534
  }
30318
- const cache = new Cache(config);
30535
+ const mergedConfig = {
30536
+ ...this.globalConfig,
30537
+ ...config,
30538
+ name
30539
+ };
30540
+ const cache = new LRUCache(mergedConfig);
30319
30541
  this.caches.set(name, cache);
30320
- if (this.debug) {
30321
- console.log(`[CacheManager] Created cache: ${name}`, config);
30322
- }
30323
30542
  return cache;
30324
30543
  }
30325
30544
  /**
@@ -30334,11 +30553,11 @@ var CacheManager = class {
30334
30553
  * Clean expired entries from all caches
30335
30554
  */
30336
30555
  cleanAllExpired() {
30337
- let total = 0;
30556
+ let totalCleaned = 0;
30338
30557
  for (const cache of this.caches.values()) {
30339
- total += cache.cleanExpired();
30558
+ totalCleaned += cache.cleanExpired();
30340
30559
  }
30341
- return total;
30560
+ return totalCleaned;
30342
30561
  }
30343
30562
  /**
30344
30563
  * Get statistics for all caches
@@ -30351,11 +30570,16 @@ var CacheManager = class {
30351
30570
  return stats;
30352
30571
  }
30353
30572
  /**
30354
- * Destroy cache manager
30573
+ * Get list of all cache names
30355
30574
  */
30356
- destroy() {
30357
- this.clearAll();
30358
- this.caches.clear();
30575
+ getCacheNames() {
30576
+ return Array.from(this.caches.keys());
30577
+ }
30578
+ /**
30579
+ * Delete a named cache
30580
+ */
30581
+ deleteCache(name) {
30582
+ return this.caches.delete(name);
30359
30583
  }
30360
30584
  };
30361
30585
  function createCacheManager(config) {
@@ -31634,6 +31858,23 @@ function createLoanCreator(config) {
31634
31858
  }
31635
31859
 
31636
31860
  // src/modules/loan/loan-query.module.ts
31861
+ var POSITION_CORE_ABI = [
31862
+ "function getPositionDetails(bytes32) view returns (tuple(bytes32 positionId, bytes32 pkpId, uint256 ucdDebt, string vaultAddress, address borrower, uint40 createdAt, uint40 lastUpdated, uint16 selectedTerm, uint40 expiryAt, bool isActive, uint8 status))"
31863
+ ];
31864
+ function normalizePkpId(pkpId) {
31865
+ const raw = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
31866
+ if (raw.length === 64 && raw.startsWith("000000000000000000000000") && raw !== "0".repeat(64)) {
31867
+ return `0x${raw.slice(24)}`;
31868
+ }
31869
+ return pkpId;
31870
+ }
31871
+ function padPkpIdForSubgraph(pkpId) {
31872
+ const raw = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
31873
+ if (raw.length === 40) {
31874
+ return `0x${"0".repeat(24)}${raw}`;
31875
+ }
31876
+ return pkpId;
31877
+ }
31637
31878
  var LoanQuery = class {
31638
31879
  config;
31639
31880
  defaultPageSize;
@@ -31662,7 +31903,7 @@ var LoanQuery = class {
31662
31903
  const borrowerCreatedAt = typeof rawLoan.borrower === "object" && rawLoan.borrower?.createdAt ? Number(rawLoan.borrower.createdAt) : 0;
31663
31904
  const loanData = {
31664
31905
  id: rawLoan.id,
31665
- pkpId: rawLoan.pkpId,
31906
+ pkpId: normalizePkpId(rawLoan.pkpId),
31666
31907
  borrower: {
31667
31908
  createdAt: borrowerCreatedAt,
31668
31909
  id: borrowerId
@@ -31708,6 +31949,7 @@ var LoanQuery = class {
31708
31949
  * @returns Loan data
31709
31950
  */
31710
31951
  async getLoanByPkpId(pkpId, enrichBalance = false) {
31952
+ pkpId = padPkpIdForSubgraph(pkpId);
31711
31953
  if (this.config.debug) {
31712
31954
  log.info("\u{1F50D} Querying loan by PKP ID", { pkpId, enrichBalance });
31713
31955
  }
@@ -31730,7 +31972,7 @@ var LoanQuery = class {
31730
31972
  const borrowerCreatedAt = typeof rawLoan.borrower === "object" && rawLoan.borrower?.createdAt ? Number(rawLoan.borrower.createdAt) : 0;
31731
31973
  const loanData = {
31732
31974
  id: rawLoan.id,
31733
- pkpId: rawLoan.pkpId,
31975
+ pkpId: normalizePkpId(rawLoan.pkpId),
31734
31976
  borrower: {
31735
31977
  createdAt: borrowerCreatedAt,
31736
31978
  id: borrowerId
@@ -31909,10 +32151,30 @@ var LoanQuery = class {
31909
32151
  await Promise.all(
31910
32152
  batch.map(async (loan) => {
31911
32153
  try {
31912
- const pkpPublicKey = await getPKPPublicKeyFromTokenId(
31913
- loan.pkpId,
31914
- this.config.provider
31915
- );
32154
+ const rawId = loan.pkpId?.startsWith("0x") ? loan.pkpId.slice(2) : loan.pkpId;
32155
+ const isChipotlePkpId = typeof rawId === "string" && rawId.length === 40 && !rawId.toLowerCase().startsWith("04");
32156
+ if (isChipotlePkpId) {
32157
+ if (this.config.positionManagerCoreAddress && this.config.provider) {
32158
+ const pmContract = new ethers_exports.Contract(
32159
+ this.config.positionManagerCoreAddress,
32160
+ POSITION_CORE_ABI,
32161
+ this.config.provider
32162
+ );
32163
+ const pos = await pmContract["getPositionDetails"](loan.id);
32164
+ const vaultAddr = pos.vaultAddress ?? pos[3] ?? "";
32165
+ if (vaultAddr) {
32166
+ loan.collateral.vaultAddress = vaultAddr;
32167
+ if (this.config.debug) {
32168
+ log.info(`\u2705 Vault address from contract for loan ${loan.id}`, { vaultAddr });
32169
+ }
32170
+ }
32171
+ } else if (this.config.debug) {
32172
+ log.warn(`\u26A0\uFE0F Chipotle pkpId for loan ${loan.id} but no positionManagerCoreAddress configured`);
32173
+ }
32174
+ return;
32175
+ }
32176
+ const isUncompressedPubKey = typeof rawId === "string" && rawId.length === 130 && rawId.toLowerCase().startsWith("04");
32177
+ const pkpPublicKey = isUncompressedPubKey ? loan.pkpId.startsWith("0x") ? loan.pkpId : `0x${loan.pkpId}` : await getPKPPublicKeyFromTokenId(loan.pkpId, this.config.provider);
31916
32178
  const addressesResult = await this.config.bitcoinOperations.deriveAddresses(pkpPublicKey);
31917
32179
  if (addressesResult.success) {
31918
32180
  loan.collateral.vaultAddress = addressesResult.value;
@@ -33348,6 +33610,13 @@ var GraphClient = class {
33348
33610
  var THE_GRAPH_MAX_BATCH_SIZE = 1e3;
33349
33611
 
33350
33612
  // src/graphs/diamond-hands.ts
33613
+ function normalizePkpId2(pkpId) {
33614
+ const raw = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
33615
+ if (raw.length === 64 && raw.startsWith("000000000000000000000000") && raw !== "0".repeat(64)) {
33616
+ return `0x${raw.slice(24)}`;
33617
+ }
33618
+ return pkpId;
33619
+ }
33351
33620
  var DiamondHandsGraph = class {
33352
33621
  client;
33353
33622
  defaultPageSize;
@@ -33370,7 +33639,7 @@ var DiamondHandsGraph = class {
33370
33639
  const ucdDebt = graphPosition.ucdDebt ? Number(graphPosition.ucdDebt) : 0;
33371
33640
  return {
33372
33641
  id: graphPosition.id,
33373
- pkpId: graphPosition.pkpId,
33642
+ pkpId: normalizePkpId2(graphPosition.pkpId),
33374
33643
  borrower: {
33375
33644
  createdAt: graphPosition.borrower?.createdAt ? Number(graphPosition.borrower.createdAt) : 0,
33376
33645
  id: graphPosition.borrower?.id || graphPosition.borrower
@@ -34632,39 +34901,6 @@ try {
34632
34901
  } catch (error) {
34633
34902
  console.warn("Telegram bot API not available:", error instanceof Error ? error.message : String(error));
34634
34903
  }
34635
- async function sendTelegramMessage(chatId, chatToken, message, threadId) {
34636
- try {
34637
- if (typeof window !== "undefined") {
34638
- if (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") {
34639
- console.log("[Browser] Telegram messaging not available - skipping notification");
34640
- }
34641
- return;
34642
- }
34643
- if (!TelegramBot) {
34644
- console.warn("Telegram bot API not available in this environment");
34645
- return;
34646
- }
34647
- const bot = new TelegramBot(chatToken, { polling: false });
34648
- const options = {
34649
- disable_web_page_preview: true
34650
- };
34651
- if (threadId !== void 0) {
34652
- options.message_thread_id = threadId;
34653
- }
34654
- console.log("\u{1F4F1} Sending Telegram message...");
34655
- console.log(` Chat ID: ${chatId}`);
34656
- console.log(` Thread ID: ${threadId || "none"}`);
34657
- console.log(` Message: ${message}`);
34658
- const result = await bot.sendMessage(chatId, message, options);
34659
- console.log("\u2705 Telegram message sent successfully!");
34660
- console.log(` Message ID: ${result.message_id}`);
34661
- } catch (error) {
34662
- console.error("\u274C Failed to send Telegram message:", error);
34663
- if (error instanceof Error) {
34664
- console.error(` Error message: ${error.message}`);
34665
- }
34666
- }
34667
- }
34668
34904
  function formatMintMessage(mintAmount, loanId, txHash) {
34669
34905
  return `${mintAmount} UCD was minted for loan id: ${loanId} Tx: https://sepolia.etherscan.io/tx/${txHash}`;
34670
34906
  }
@@ -34983,6 +35219,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
34983
35219
  network: config.litNetwork || DEFAULT_LIT_NETWORK,
34984
35220
  signer: config.mode === "standalone" ? config.litOpsSigner : void 0,
34985
35221
  serviceEndpoint: isServiceModeConfig(config) ? config.serviceEndpoint : void 0,
35222
+ serviceAuthToken: isServiceModeConfig(config) ? config.serviceAuthToken : void 0,
34986
35223
  debug: config.debug,
34987
35224
  litNodeConnectTimeoutMs: config.litNodeConnectTimeoutMs
34988
35225
  // TODO Round 2: Add litActionExecution config when added to config.i.ts interface
@@ -35040,19 +35277,21 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35040
35277
  );
35041
35278
  }
35042
35279
  this.pkpManager = pkpManagerResult.value;
35043
- const graphEndpoint = config.subgraphs?.diamondHandsUrl;
35280
+ const serviceMode = isServiceModeConfig(config);
35281
+ const graphEndpoint = serviceMode ? `${config.serviceEndpoint}/api/lit/graph/query` : config.subgraphs?.diamondHandsUrl;
35044
35282
  if (!graphEndpoint) {
35045
35283
  throw new Error(
35046
35284
  "Diamond Hands subgraph URL is required. Please provide config.subgraphs.diamondHandsUrl"
35047
35285
  );
35048
35286
  }
35287
+ const graphHeaders = serviceMode && config.serviceAuthToken ? { Authorization: `Bearer ${config.serviceAuthToken}` } : config.graphApiKey ? { Authorization: `Bearer ${config.graphApiKey}` } : void 0;
35049
35288
  this.graphClient = new DiamondHandsGraph(
35050
35289
  {
35051
35290
  endpoint: graphEndpoint,
35052
35291
  requestTimeoutMs: config.graphOptions?.requestTimeoutMs,
35053
35292
  maxRetries: config.graphOptions?.maxRetries,
35054
35293
  defaultPageSize: config.graphOptions?.pageSize,
35055
- headers: config.graphApiKey ? { Authorization: `Bearer ${config.graphApiKey}` } : void 0
35294
+ headers: graphHeaders
35056
35295
  },
35057
35296
  this.bitcoinOperations
35058
35297
  );
@@ -35060,6 +35299,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35060
35299
  graphClient: this.graphClient,
35061
35300
  bitcoinOperations: this.bitcoinOperations,
35062
35301
  provider: config.provider,
35302
+ positionManagerCoreAddress: config.contractAddresses?.positionManagerCore,
35063
35303
  cache: this.cacheManager.getCache("loan-data", {
35064
35304
  maxSize: 200,
35065
35305
  ttlMs: 3e4
@@ -35451,6 +35691,30 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35451
35691
  /**
35452
35692
  * Check if SDK is ready for operations
35453
35693
  */
35694
+ async _relayNotification(message) {
35695
+ if (this.config.mode !== "service")
35696
+ return;
35697
+ const endpoint = this.config.serviceEndpoint;
35698
+ if (!endpoint)
35699
+ return;
35700
+ const token = this.config.serviceAuthToken;
35701
+ try {
35702
+ await fetch(`${endpoint}/api/lit/notifications/send`, {
35703
+ method: "POST",
35704
+ headers: {
35705
+ "Content-Type": "application/json",
35706
+ ...token ? { Authorization: `Bearer ${token}` } : {}
35707
+ },
35708
+ body: JSON.stringify({ message })
35709
+ });
35710
+ } catch (err) {
35711
+ if (this.config.debug) {
35712
+ log.warn("Notification relay failed", {
35713
+ error: err instanceof Error ? err.message : String(err)
35714
+ });
35715
+ }
35716
+ }
35717
+ }
35454
35718
  checkInitialized() {
35455
35719
  if (!this.isInitialized) {
35456
35720
  return failure(
@@ -35526,7 +35790,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35526
35790
  return failure(initCheck.error);
35527
35791
  }
35528
35792
  const result = await this.loanCreator.createLoan(request);
35529
- if (result.success && this.config.telegram && result.value.positionId) {
35793
+ if (result.success && result.value.positionId) {
35530
35794
  try {
35531
35795
  const message = formatLoanCreationMessage(
35532
35796
  result.value.positionId,
@@ -35538,12 +35802,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35538
35802
  "\u{1F4F1} Attempting to send loan creation Telegram message..."
35539
35803
  );
35540
35804
  }
35541
- await sendTelegramMessage(
35542
- this.config.telegram.chatId,
35543
- this.config.telegram.chatToken,
35544
- message,
35545
- this.config.telegram.threadId
35546
- );
35805
+ await this._relayNotification(message);
35547
35806
  if (this.config.debug) {
35548
35807
  console.log("\u2705 Loan creation Telegram message sent successfully");
35549
35808
  }
@@ -36717,7 +36976,7 @@ Error data: ${errorData || "none"}`
36717
36976
  amountMintedUCD: Number(amountMinted) / 10 ** 18
36718
36977
  };
36719
36978
  try {
36720
- if (this.config.telegram && result.transactionHash) {
36979
+ if (result.transactionHash) {
36721
36980
  const mintAmount = result.amountMintedUCD || request.amount;
36722
36981
  const loanId = result.positionId || request.positionId;
36723
36982
  const message = formatMintMessage(
@@ -36725,12 +36984,7 @@ Error data: ${errorData || "none"}`
36725
36984
  loanId,
36726
36985
  result.transactionHash
36727
36986
  );
36728
- await sendTelegramMessage(
36729
- this.config.telegram.chatId,
36730
- this.config.telegram.chatToken,
36731
- message,
36732
- this.config.telegram.threadId
36733
- );
36987
+ await this._relayNotification(message);
36734
36988
  }
36735
36989
  } catch (err) {
36736
36990
  }
@@ -36992,39 +37246,32 @@ Error data: ${errorData || "none"}`
36992
37246
  }
36993
37247
  if (!shouldLiquidate) {
36994
37248
  try {
36995
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
36996
- if (this.config.debug) {
36997
- log.info(`\u{1F4F1} Sending liquidation skipped Telegram message...`);
36998
- }
36999
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37000
- const btcPrice2 = litActionResult.btcPrice || "0";
37001
- const btcVaultBalance = litActionResult.btcAmountSats || positionDetails.btcVaultBalance || "0";
37002
- const usdPricePerBTC = Number(btcPrice2) / 1e8;
37003
- const btcAmount = Number(btcVaultBalance) / 1e8;
37004
- const btcValueUSD = btcAmount * usdPricePerBTC;
37005
- const debtUSD = Number(debt) / 1e18;
37006
- const ratio = debtUSD > 0 ? (btcValueUSD / debtUSD * 100).toFixed(2) : "0.00";
37007
- const message = formatLiquidationSkippedMessage(
37008
- request.positionId,
37009
- ratio,
37010
- `${liquidationThreshold / 100}`,
37011
- // Convert to percentage
37012
- positionDetails.vaultAddress || "unknown",
37013
- btcVaultBalance,
37014
- debt,
37015
- btcPrice2
37016
- );
37017
- await sendTelegramMessage(
37018
- this.config.telegram.chatId,
37019
- this.config.telegram.chatToken,
37020
- message,
37021
- this.config.telegram.threadId
37249
+ if (this.config.debug) {
37250
+ log.info(`\u{1F4F1} Sending liquidation skipped Telegram message...`);
37251
+ }
37252
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37253
+ const btcPrice2 = litActionResult.btcPrice || "0";
37254
+ const btcVaultBalance = litActionResult.btcAmountSats || positionDetails.btcVaultBalance || "0";
37255
+ const usdPricePerBTC = Number(btcPrice2) / 1e8;
37256
+ const btcAmount = Number(btcVaultBalance) / 1e8;
37257
+ const btcValueUSD = btcAmount * usdPricePerBTC;
37258
+ const debtUSD = Number(debt) / 1e18;
37259
+ const ratio = debtUSD > 0 ? (btcValueUSD / debtUSD * 100).toFixed(2) : "0.00";
37260
+ const message = formatLiquidationSkippedMessage(
37261
+ request.positionId,
37262
+ ratio,
37263
+ `${liquidationThreshold / 100}`,
37264
+ // Convert to percentage
37265
+ positionDetails.vaultAddress || "unknown",
37266
+ btcVaultBalance,
37267
+ debt,
37268
+ btcPrice2
37269
+ );
37270
+ await this._relayNotification(message);
37271
+ if (this.config.debug) {
37272
+ log.info(
37273
+ `\u2705 Liquidation skipped Telegram message sent successfully`
37022
37274
  );
37023
- if (this.config.debug) {
37024
- log.info(
37025
- `\u2705 Liquidation skipped Telegram message sent successfully`
37026
- );
37027
- }
37028
37275
  }
37029
37276
  } catch (telegramError) {
37030
37277
  if (this.config.debug) {
@@ -37079,32 +37326,25 @@ Error data: ${errorData || "none"}`
37079
37326
  });
37080
37327
  }
37081
37328
  try {
37082
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37083
- if (this.config.debug) {
37084
- log.info(`\u{1F4F1} Sending LIT action rejection Telegram message...`);
37085
- }
37086
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37087
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37088
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37089
- const message = formatLiquidationFailureMessage(
37090
- request.positionId,
37091
- `LIT Action rejected liquidation: ${litActionResult.reason || litActionResult.error || "Unknown error"}`,
37092
- positionDetails.vaultAddress || "unknown",
37093
- btcVaultBalance,
37094
- debt,
37095
- btcPrice2
37096
- );
37097
- await sendTelegramMessage(
37098
- this.config.telegram.chatId,
37099
- this.config.telegram.chatToken,
37100
- message,
37101
- this.config.telegram.threadId
37329
+ if (this.config.debug) {
37330
+ log.info(`\u{1F4F1} Sending LIT action rejection Telegram message...`);
37331
+ }
37332
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37333
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37334
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37335
+ const message = formatLiquidationFailureMessage(
37336
+ request.positionId,
37337
+ `LIT Action rejected liquidation: ${litActionResult.reason || litActionResult.error || "Unknown error"}`,
37338
+ positionDetails.vaultAddress || "unknown",
37339
+ btcVaultBalance,
37340
+ debt,
37341
+ btcPrice2
37342
+ );
37343
+ await this._relayNotification(message);
37344
+ if (this.config.debug) {
37345
+ log.info(
37346
+ `\u2705 LIT action rejection Telegram message sent successfully`
37102
37347
  );
37103
- if (this.config.debug) {
37104
- log.info(
37105
- `\u2705 LIT action rejection Telegram message sent successfully`
37106
- );
37107
- }
37108
37348
  }
37109
37349
  } catch (telegramError) {
37110
37350
  if (this.config.debug) {
@@ -37126,32 +37366,25 @@ Error data: ${errorData || "none"}`
37126
37366
  );
37127
37367
  }
37128
37368
  try {
37129
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37130
- if (this.config.debug) {
37131
- log.info(`\u{1F4F1} Sending forced liquidation Telegram message...`);
37132
- }
37133
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37134
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37135
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37136
- const message = formatLiquidationFailureMessage(
37137
- request.positionId,
37138
- `FORCED LIQUIDATION: LIT Action rejected but forceContractCall=true - proceeding with liquidation`,
37139
- positionDetails.vaultAddress || "unknown",
37140
- btcVaultBalance,
37141
- debt,
37142
- btcPrice2
37143
- );
37144
- await sendTelegramMessage(
37145
- this.config.telegram.chatId,
37146
- this.config.telegram.chatToken,
37147
- message,
37148
- this.config.telegram.threadId
37369
+ if (this.config.debug) {
37370
+ log.info(`\u{1F4F1} Sending forced liquidation Telegram message...`);
37371
+ }
37372
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37373
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37374
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37375
+ const message = formatLiquidationFailureMessage(
37376
+ request.positionId,
37377
+ `FORCED LIQUIDATION: LIT Action rejected but forceContractCall=true - proceeding with liquidation`,
37378
+ positionDetails.vaultAddress || "unknown",
37379
+ btcVaultBalance,
37380
+ debt,
37381
+ btcPrice2
37382
+ );
37383
+ await this._relayNotification(message);
37384
+ if (this.config.debug) {
37385
+ log.info(
37386
+ `\u2705 Forced liquidation Telegram message sent successfully`
37149
37387
  );
37150
- if (this.config.debug) {
37151
- log.info(
37152
- `\u2705 Forced liquidation Telegram message sent successfully`
37153
- );
37154
- }
37155
37388
  }
37156
37389
  } catch (telegramError) {
37157
37390
  if (this.config.debug) {
@@ -37184,34 +37417,27 @@ Error data: ${errorData || "none"}`
37184
37417
  );
37185
37418
  }
37186
37419
  try {
37187
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37188
- if (this.config.debug) {
37189
- log.info(
37190
- `\u{1F4F1} Sending forced liquidation without signature Telegram message...`
37191
- );
37192
- }
37193
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37194
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37195
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37196
- const message = formatLiquidationFailureMessage(
37197
- request.positionId,
37198
- "FORCED LIQUIDATION: LIT Action did not provide signature but forceContractCall=true - proceeding without signature",
37199
- positionDetails.vaultAddress || "unknown",
37200
- btcVaultBalance,
37201
- debt,
37202
- btcPrice2
37420
+ if (this.config.debug) {
37421
+ log.info(
37422
+ `\u{1F4F1} Sending forced liquidation without signature Telegram message...`
37203
37423
  );
37204
- await sendTelegramMessage(
37205
- this.config.telegram.chatId,
37206
- this.config.telegram.chatToken,
37207
- message,
37208
- this.config.telegram.threadId
37424
+ }
37425
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37426
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37427
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37428
+ const message = formatLiquidationFailureMessage(
37429
+ request.positionId,
37430
+ "FORCED LIQUIDATION: LIT Action did not provide signature but forceContractCall=true - proceeding without signature",
37431
+ positionDetails.vaultAddress || "unknown",
37432
+ btcVaultBalance,
37433
+ debt,
37434
+ btcPrice2
37435
+ );
37436
+ await this._relayNotification(message);
37437
+ if (this.config.debug) {
37438
+ log.info(
37439
+ `\u2705 Forced liquidation without signature Telegram message sent successfully`
37209
37440
  );
37210
- if (this.config.debug) {
37211
- log.info(
37212
- `\u2705 Forced liquidation without signature Telegram message sent successfully`
37213
- );
37214
- }
37215
37441
  }
37216
37442
  } catch (telegramError) {
37217
37443
  if (this.config.debug) {
@@ -37225,32 +37451,25 @@ Error data: ${errorData || "none"}`
37225
37451
  }
37226
37452
  } else {
37227
37453
  try {
37228
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37229
- if (this.config.debug) {
37230
- log.info(`\u{1F4F1} Sending missing signature Telegram message...`);
37231
- }
37232
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37233
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37234
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37235
- const message = formatLiquidationFailureMessage(
37236
- request.positionId,
37237
- "LIT Action did not provide required signature for liquidation",
37238
- positionDetails.vaultAddress || "unknown",
37239
- btcVaultBalance,
37240
- debt,
37241
- btcPrice2
37242
- );
37243
- await sendTelegramMessage(
37244
- this.config.telegram.chatId,
37245
- this.config.telegram.chatToken,
37246
- message,
37247
- this.config.telegram.threadId
37454
+ if (this.config.debug) {
37455
+ log.info(`\u{1F4F1} Sending missing signature Telegram message...`);
37456
+ }
37457
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37458
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37459
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37460
+ const message = formatLiquidationFailureMessage(
37461
+ request.positionId,
37462
+ "LIT Action did not provide required signature for liquidation",
37463
+ positionDetails.vaultAddress || "unknown",
37464
+ btcVaultBalance,
37465
+ debt,
37466
+ btcPrice2
37467
+ );
37468
+ await this._relayNotification(message);
37469
+ if (this.config.debug) {
37470
+ log.info(
37471
+ `\u2705 Missing signature Telegram message sent successfully`
37248
37472
  );
37249
- if (this.config.debug) {
37250
- log.info(
37251
- `\u2705 Missing signature Telegram message sent successfully`
37252
- );
37253
- }
37254
37473
  }
37255
37474
  } catch (telegramError) {
37256
37475
  if (this.config.debug) {
@@ -37489,34 +37708,27 @@ Error data: ${errorData || "none"}`
37489
37708
  });
37490
37709
  }
37491
37710
  try {
37492
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37493
- if (this.config.debug) {
37494
- log.info(`\u{1F4F1} Sending liquidation success Telegram message...`);
37495
- }
37496
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37497
- const btcPrice2 = litActionResult.btcPrice || "0";
37498
- const ratio = debt !== "0" ? (Number(positionDetails.btcVaultBalance || "0") * Number(btcPrice2) / Number(debt) * 100 / 1e8).toFixed(2) : "0.00";
37499
- const message = formatLiquidationSuccessMessage(
37500
- request.positionId,
37501
- ratio,
37502
- `${liquidationThreshold / 100}`,
37503
- // Convert to percentage
37504
- positionDetails.btcVault || "unknown",
37505
- positionDetails.btcVaultBalance || "0",
37506
- debt,
37507
- btcPrice2
37508
- );
37509
- await sendTelegramMessage(
37510
- this.config.telegram.chatId,
37511
- this.config.telegram.chatToken,
37512
- message,
37513
- this.config.telegram.threadId
37711
+ if (this.config.debug) {
37712
+ log.info(`\u{1F4F1} Sending liquidation success Telegram message...`);
37713
+ }
37714
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37715
+ const btcPrice2 = litActionResult.btcPrice || "0";
37716
+ const ratio = debt !== "0" ? (Number(positionDetails.btcVaultBalance || "0") * Number(btcPrice2) / Number(debt) * 100 / 1e8).toFixed(2) : "0.00";
37717
+ const message = formatLiquidationSuccessMessage(
37718
+ request.positionId,
37719
+ ratio,
37720
+ `${liquidationThreshold / 100}`,
37721
+ // Convert to percentage
37722
+ positionDetails.btcVault || "unknown",
37723
+ positionDetails.btcVaultBalance || "0",
37724
+ debt,
37725
+ btcPrice2
37726
+ );
37727
+ await this._relayNotification(message);
37728
+ if (this.config.debug) {
37729
+ log.info(
37730
+ `\u2705 Liquidation success Telegram message sent successfully`
37514
37731
  );
37515
- if (this.config.debug) {
37516
- log.info(
37517
- `\u2705 Liquidation success Telegram message sent successfully`
37518
- );
37519
- }
37520
37732
  }
37521
37733
  } catch (telegramError) {
37522
37734
  if (this.config.debug) {
@@ -37548,31 +37760,24 @@ Error data: ${errorData || "none"}`
37548
37760
  transaction: contractError.transaction
37549
37761
  });
37550
37762
  try {
37551
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37552
- if (this.config.debug) {
37553
- log.info(`\u{1F4F1} Sending liquidation failure Telegram message...`);
37554
- }
37555
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37556
- const btcPrice2 = litActionResult.btcPrice || "0";
37557
- const message = formatLiquidationFailureMessage(
37558
- request.positionId,
37559
- contractError.message || "Unknown contract error",
37560
- positionDetails.btcVault || "unknown",
37561
- positionDetails.btcVaultBalance || "0",
37562
- debt,
37563
- btcPrice2
37564
- );
37565
- await sendTelegramMessage(
37566
- this.config.telegram.chatId,
37567
- this.config.telegram.chatToken,
37568
- message,
37569
- this.config.telegram.threadId
37763
+ if (this.config.debug) {
37764
+ log.info(`\u{1F4F1} Sending liquidation failure Telegram message...`);
37765
+ }
37766
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37767
+ const btcPrice2 = litActionResult.btcPrice || "0";
37768
+ const message = formatLiquidationFailureMessage(
37769
+ request.positionId,
37770
+ contractError.message || "Unknown contract error",
37771
+ positionDetails.btcVault || "unknown",
37772
+ positionDetails.btcVaultBalance || "0",
37773
+ debt,
37774
+ btcPrice2
37775
+ );
37776
+ await this._relayNotification(message);
37777
+ if (this.config.debug) {
37778
+ log.info(
37779
+ `\u2705 Liquidation failure Telegram message sent successfully`
37570
37780
  );
37571
- if (this.config.debug) {
37572
- log.info(
37573
- `\u2705 Liquidation failure Telegram message sent successfully`
37574
- );
37575
- }
37576
37781
  }
37577
37782
  } catch (telegramError) {
37578
37783
  if (this.config.debug) {
@@ -37722,26 +37927,19 @@ Error data: ${errorData || "none"}`
37722
37927
  )} (${potentialNewExpiry}), max allowed: ${formatDate(
37723
37928
  maxAllowedTimestamp
37724
37929
  )} (${maxAllowedTimestamp})`;
37725
- if (this.config.telegram) {
37726
- try {
37727
- await sendTelegramMessage(
37728
- this.config.telegram.chatId,
37729
- this.config.telegram.chatToken,
37730
- formatLoanRenewalFailureMessage(
37731
- _positionId,
37732
- `Loan could not be renewed: ${errorMessage}`
37733
- ),
37734
- this.config.telegram.threadId
37930
+ try {
37931
+ await this._relayNotification(formatLoanRenewalFailureMessage(
37932
+ _positionId,
37933
+ `Loan could not be renewed: ${errorMessage}`
37934
+ ));
37935
+ } catch (e) {
37936
+ if (this.config.debug) {
37937
+ log.warn(
37938
+ "Failed to send Telegram notification for renewal rule violation",
37939
+ {
37940
+ error: e instanceof Error ? e.message : String(e)
37941
+ }
37735
37942
  );
37736
- } catch (e) {
37737
- if (this.config.debug) {
37738
- log.warn(
37739
- "Failed to send Telegram notification for renewal rule violation",
37740
- {
37741
- error: e instanceof Error ? e.message : String(e)
37742
- }
37743
- );
37744
- }
37745
37943
  }
37746
37944
  }
37747
37945
  throw new Error(errorMessage);
@@ -37793,19 +37991,12 @@ Error data: ${errorData || "none"}`
37793
37991
  error: errorMessage
37794
37992
  });
37795
37993
  }
37796
- if (this.config.telegram) {
37797
- try {
37798
- await sendTelegramMessage(
37799
- this.config.telegram.chatId,
37800
- this.config.telegram.chatToken,
37801
- formatLoanRenewalFailureMessage(
37802
- _positionId,
37803
- `LIT Action failed: ${errorMessage}`
37804
- ),
37805
- this.config.telegram.threadId
37806
- );
37807
- } catch (e) {
37808
- }
37994
+ try {
37995
+ await this._relayNotification(formatLoanRenewalFailureMessage(
37996
+ _positionId,
37997
+ `LIT Action failed: ${errorMessage}`
37998
+ ));
37999
+ } catch (e) {
37809
38000
  }
37810
38001
  throw litError;
37811
38002
  }
@@ -37815,31 +38006,17 @@ Error data: ${errorData || "none"}`
37815
38006
  if (!litActionResult.approved) {
37816
38007
  const reason = litActionResult.reason ?? litActionResult.error ?? "Extension not approved";
37817
38008
  const errorMessage = `Extension not approved: ${reason}`;
37818
- if (this.config.telegram) {
37819
- try {
37820
- await sendTelegramMessage(
37821
- this.config.telegram.chatId,
37822
- this.config.telegram.chatToken,
37823
- formatLoanRenewalFailureMessage(_positionId, errorMessage),
37824
- this.config.telegram.threadId
37825
- );
37826
- } catch (e) {
37827
- }
38009
+ try {
38010
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, errorMessage));
38011
+ } catch (e) {
37828
38012
  }
37829
38013
  throw new Error(errorMessage);
37830
38014
  }
37831
38015
  if (!litActionResult.signature || litActionResult.btcPrice === void 0 || litActionResult.btcPrice === null || litActionResult.availableBTCBalance === void 0 || litActionResult.availableBTCBalance === null || (litActionResult.quantumTimestamp === void 0 || litActionResult.quantumTimestamp === null) || litActionResult.proRataRenewalFee === void 0 || litActionResult.proRataRenewalFee === null) {
37832
38016
  const errorMessage = "LIT Action result missing required fields: signature, btcPrice, availableBTCBalance, quantumTimestamp, proRataRenewalFee";
37833
- if (this.config.telegram) {
37834
- try {
37835
- await sendTelegramMessage(
37836
- this.config.telegram.chatId,
37837
- this.config.telegram.chatToken,
37838
- formatLoanRenewalFailureMessage(_positionId, errorMessage),
37839
- this.config.telegram.threadId
37840
- );
37841
- } catch (e) {
37842
- }
38017
+ try {
38018
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, errorMessage));
38019
+ } catch (e) {
37843
38020
  }
37844
38021
  throw new Error(errorMessage);
37845
38022
  }
@@ -37926,66 +38103,38 @@ Error data: ${errorData || "none"}`
37926
38103
  { hash: txWithProvider.hash, error: errorMessage }
37927
38104
  );
37928
38105
  }
37929
- if (this.config.telegram) {
37930
- try {
37931
- await sendTelegramMessage(
37932
- this.config.telegram.chatId,
37933
- this.config.telegram.chatToken,
37934
- formatLoanRenewalFailureMessage(
37935
- _positionId,
37936
- `Transaction confirmation failed: ${errorMessage}`
37937
- ),
37938
- this.config.telegram.threadId
37939
- );
37940
- } catch (e) {
37941
- }
38106
+ try {
38107
+ await this._relayNotification(formatLoanRenewalFailureMessage(
38108
+ _positionId,
38109
+ `Transaction confirmation failed: ${errorMessage}`
38110
+ ));
38111
+ } catch (e) {
37942
38112
  }
37943
38113
  throw waitError;
37944
38114
  }
37945
38115
  if (!receipt) {
37946
38116
  const error = "Transaction receipt is null - transaction may have failed";
37947
- if (this.config.telegram) {
37948
- try {
37949
- await sendTelegramMessage(
37950
- this.config.telegram.chatId,
37951
- this.config.telegram.chatToken,
37952
- formatLoanRenewalFailureMessage(_positionId, error),
37953
- this.config.telegram.threadId
37954
- );
37955
- } catch (e) {
37956
- }
38117
+ try {
38118
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, error));
38119
+ } catch (e) {
37957
38120
  }
37958
38121
  throw new Error(error);
37959
38122
  }
37960
38123
  if (receipt.status === 0) {
37961
38124
  const error = `Transaction reverted (tx: ${receipt.transactionHash})`;
37962
- if (this.config.telegram) {
37963
- try {
37964
- await sendTelegramMessage(
37965
- this.config.telegram.chatId,
37966
- this.config.telegram.chatToken,
37967
- formatLoanRenewalFailureMessage(_positionId, error),
37968
- this.config.telegram.threadId
37969
- );
37970
- } catch (e) {
37971
- }
38125
+ try {
38126
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, error));
38127
+ } catch (e) {
37972
38128
  }
37973
38129
  throw new Error(error);
37974
38130
  }
37975
- if (this.config.telegram) {
37976
- try {
37977
- await sendTelegramMessage(
37978
- this.config.telegram.chatId,
37979
- this.config.telegram.chatToken,
37980
- formatLoanRenewalMessage(_positionId, receipt.transactionHash),
37981
- this.config.telegram.threadId
37982
- );
37983
- } catch (e) {
37984
- if (this.config.debug) {
37985
- log.warn("Failed to send Telegram notification for extension", {
37986
- error: e instanceof Error ? e.message : String(e)
37987
- });
37988
- }
38131
+ try {
38132
+ await this._relayNotification(formatLoanRenewalMessage(_positionId, receipt.transactionHash));
38133
+ } catch (e) {
38134
+ if (this.config.debug) {
38135
+ log.warn("Failed to send Telegram notification for extension", {
38136
+ error: e instanceof Error ? e.message : String(e)
38137
+ });
37989
38138
  }
37990
38139
  }
37991
38140
  return receipt;
@@ -38099,16 +38248,9 @@ Error data: ${errorData || "none"}`
38099
38248
  const initCheck = this.checkInitialized();
38100
38249
  if (!initCheck.success) {
38101
38250
  const error = `SDK not initialized: ${initCheck.error.message}`;
38102
- if (this.config.telegram) {
38103
- try {
38104
- await sendTelegramMessage(
38105
- this.config.telegram.chatId,
38106
- this.config.telegram.chatToken,
38107
- formatBalanceConfirmationFailureMessage(positionId),
38108
- this.config.telegram.threadId
38109
- );
38110
- } catch (e) {
38111
- }
38251
+ try {
38252
+ await this._relayNotification(formatBalanceConfirmationFailureMessage(positionId));
38253
+ } catch (e) {
38112
38254
  }
38113
38255
  return {
38114
38256
  success: false,
@@ -38248,21 +38390,14 @@ Error data: ${errorData || "none"}`
38248
38390
  gasUsed: receipt.gasUsed.toString()
38249
38391
  });
38250
38392
  }
38251
- if (this.config.telegram) {
38252
- try {
38253
- const message = formatBalanceConfirmationMessage(positionId);
38254
- await sendTelegramMessage(
38255
- this.config.telegram.chatId,
38256
- this.config.telegram.chatToken,
38257
- message,
38258
- this.config.telegram.threadId
38259
- );
38260
- } catch (telegramError) {
38261
- if (this.config.debug) {
38262
- log.warn("\u26A0\uFE0F Failed to send Telegram notification", {
38263
- error: telegramError instanceof Error ? telegramError.message : String(telegramError)
38264
- });
38265
- }
38393
+ try {
38394
+ const message = formatBalanceConfirmationMessage(positionId);
38395
+ await this._relayNotification(message);
38396
+ } catch (telegramError) {
38397
+ if (this.config.debug) {
38398
+ log.warn("\u26A0\uFE0F Failed to send Telegram notification", {
38399
+ error: telegramError instanceof Error ? telegramError.message : String(telegramError)
38400
+ });
38266
38401
  }
38267
38402
  }
38268
38403
  return {
@@ -38285,17 +38420,10 @@ Error data: ${errorData || "none"}`
38285
38420
  positionId
38286
38421
  });
38287
38422
  }
38288
- if (this.config.telegram) {
38289
- try {
38290
- const message = formatBalanceConfirmationFailureMessage(positionId);
38291
- await sendTelegramMessage(
38292
- this.config.telegram.chatId,
38293
- this.config.telegram.chatToken,
38294
- message,
38295
- this.config.telegram.threadId
38296
- );
38297
- } catch (telegramError) {
38298
- }
38423
+ try {
38424
+ const message = formatBalanceConfirmationFailureMessage(positionId);
38425
+ await this._relayNotification(message);
38426
+ } catch (telegramError) {
38299
38427
  }
38300
38428
  return {
38301
38429
  success: false,
@@ -38844,17 +38972,12 @@ Error data: ${errorData || "none"}`
38844
38972
  }
38845
38973
  if (receipt.status === 0) {
38846
38974
  try {
38847
- if (this.config.telegram && tx.hash) {
38975
+ if (tx.hash) {
38848
38976
  const message = formatPartialPaymentFailureMessage(
38849
38977
  request.paymentAmount,
38850
38978
  request.positionId
38851
38979
  );
38852
- await sendTelegramMessage(
38853
- this.config.telegram.chatId,
38854
- this.config.telegram.chatToken,
38855
- message,
38856
- this.config.telegram.threadId
38857
- );
38980
+ await this._relayNotification(message);
38858
38981
  }
38859
38982
  } catch (telegramError) {
38860
38983
  if (this.config.debug) {
@@ -38876,18 +38999,13 @@ Error data: ${errorData || "none"}`
38876
38999
  log.info(`\u2705 Transaction confirmed in block ${receipt.blockNumber}`);
38877
39000
  }
38878
39001
  try {
38879
- if (this.config.telegram && tx.hash) {
39002
+ if (tx.hash) {
38880
39003
  const message = formatPartialPaymentMessage(
38881
39004
  request.paymentAmount,
38882
39005
  request.positionId,
38883
39006
  tx.hash
38884
39007
  );
38885
- await sendTelegramMessage(
38886
- this.config.telegram.chatId,
38887
- this.config.telegram.chatToken,
38888
- message,
38889
- this.config.telegram.threadId
38890
- );
39008
+ await this._relayNotification(message);
38891
39009
  }
38892
39010
  } catch (telegramError) {
38893
39011
  if (this.config.debug) {
@@ -38941,19 +39059,12 @@ Error data: ${errorData || "none"}`
38941
39059
  });
38942
39060
  }
38943
39061
  try {
38944
- if (this.config.telegram) {
38945
- const message = formatPartialPaymentFailureMessage(
38946
- request.paymentAmount,
38947
- request.positionId,
38948
- transactionHash
38949
- );
38950
- await sendTelegramMessage(
38951
- this.config.telegram.chatId,
38952
- this.config.telegram.chatToken,
38953
- message,
38954
- this.config.telegram.threadId
38955
- );
38956
- }
39062
+ const message = formatPartialPaymentFailureMessage(
39063
+ request.paymentAmount,
39064
+ request.positionId,
39065
+ transactionHash
39066
+ );
39067
+ await this._relayNotification(message);
38957
39068
  } catch (telegramError) {
38958
39069
  if (this.config.debug) {
38959
39070
  log.warn("\u26A0\uFE0F Failed to send Telegram failure notification", {
@@ -39269,22 +39380,15 @@ Error data: ${errorData || "none"}`
39269
39380
  });
39270
39381
  }
39271
39382
  try {
39272
- if (this.config.telegram) {
39273
- const position2 = await this.getPosition(positionId);
39274
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39275
- const message = formatBTCWithdrawalFailureMessage(
39276
- btcAmount,
39277
- position2?.vaultAddress || "unknown",
39278
- withdrawalAddress,
39279
- positionId
39280
- );
39281
- await sendTelegramMessage(
39282
- this.config.telegram.chatId,
39283
- this.config.telegram.chatToken,
39284
- message,
39285
- this.config.telegram.threadId
39286
- );
39287
- }
39383
+ const position2 = await this.getPosition(positionId);
39384
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39385
+ const message = formatBTCWithdrawalFailureMessage(
39386
+ btcAmount,
39387
+ position2?.vaultAddress || "unknown",
39388
+ withdrawalAddress,
39389
+ positionId
39390
+ );
39391
+ await this._relayNotification(message);
39288
39392
  } catch (telegramError) {
39289
39393
  console.error(
39290
39394
  "Telegram notification failed:",
@@ -39316,22 +39420,15 @@ Error data: ${errorData || "none"}`
39316
39420
  });
39317
39421
  }
39318
39422
  try {
39319
- if (this.config.telegram) {
39320
- const position = await this.getPosition(positionId);
39321
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39322
- const message = formatBTCWithdrawalFailureMessage(
39323
- btcAmount,
39324
- position?.vaultAddress || "unknown",
39325
- withdrawalAddress,
39326
- positionId
39327
- );
39328
- await sendTelegramMessage(
39329
- this.config.telegram.chatId,
39330
- this.config.telegram.chatToken,
39331
- message,
39332
- this.config.telegram.threadId
39333
- );
39334
- }
39423
+ const position = await this.getPosition(positionId);
39424
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39425
+ const message = formatBTCWithdrawalFailureMessage(
39426
+ btcAmount,
39427
+ position?.vaultAddress || "unknown",
39428
+ withdrawalAddress,
39429
+ positionId
39430
+ );
39431
+ await this._relayNotification(message);
39335
39432
  } catch (telegramError) {
39336
39433
  console.error(
39337
39434
  "Telegram notification failed:",
@@ -39485,22 +39582,15 @@ Error data: ${errorData || "none"}`
39485
39582
  });
39486
39583
  }
39487
39584
  try {
39488
- if (this.config.telegram) {
39489
- const position = await this.getPosition(positionId);
39490
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39491
- const message = formatBTCWithdrawalFailureMessage(
39492
- btcAmount,
39493
- position?.vaultAddress || "unknown",
39494
- withdrawalAddress,
39495
- positionId
39496
- );
39497
- await sendTelegramMessage(
39498
- this.config.telegram.chatId,
39499
- this.config.telegram.chatToken,
39500
- message,
39501
- this.config.telegram.threadId
39502
- );
39503
- }
39585
+ const position = await this.getPosition(positionId);
39586
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39587
+ const message = formatBTCWithdrawalFailureMessage(
39588
+ btcAmount,
39589
+ position?.vaultAddress || "unknown",
39590
+ withdrawalAddress,
39591
+ positionId
39592
+ );
39593
+ await this._relayNotification(message);
39504
39594
  } catch (telegramError) {
39505
39595
  console.error(
39506
39596
  "Telegram notification failed:",
@@ -39540,22 +39630,15 @@ Error data: ${errorData || "none"}`
39540
39630
  });
39541
39631
  }
39542
39632
  try {
39543
- if (this.config.telegram) {
39544
- const position = await this.getPosition(positionId);
39545
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39546
- const message = formatBTCWithdrawalSuccessMessage(
39547
- btcAmount,
39548
- position?.vaultAddress || "unknown",
39549
- validationResponse.destinationAddress,
39550
- positionId
39551
- );
39552
- await sendTelegramMessage(
39553
- this.config.telegram.chatId,
39554
- this.config.telegram.chatToken,
39555
- message,
39556
- this.config.telegram.threadId
39557
- );
39558
- }
39633
+ const position = await this.getPosition(positionId);
39634
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39635
+ const message = formatBTCWithdrawalSuccessMessage(
39636
+ btcAmount,
39637
+ position?.vaultAddress || "unknown",
39638
+ validationResponse.destinationAddress,
39639
+ positionId
39640
+ );
39641
+ await this._relayNotification(message);
39559
39642
  } catch (telegramError) {
39560
39643
  console.error(
39561
39644
  "Telegram notification failed:",
@@ -39581,22 +39664,15 @@ Error data: ${errorData || "none"}`
39581
39664
  });
39582
39665
  }
39583
39666
  try {
39584
- if (this.config.telegram) {
39585
- const position = await this.getPosition(positionId);
39586
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39587
- const message = formatBTCWithdrawalFailureMessage(
39588
- btcAmount,
39589
- position?.vaultAddress || "unknown",
39590
- withdrawalAddress,
39591
- positionId
39592
- );
39593
- await sendTelegramMessage(
39594
- this.config.telegram.chatId,
39595
- this.config.telegram.chatToken,
39596
- message,
39597
- this.config.telegram.threadId
39598
- );
39599
- }
39667
+ const position = await this.getPosition(positionId);
39668
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39669
+ const message = formatBTCWithdrawalFailureMessage(
39670
+ btcAmount,
39671
+ position?.vaultAddress || "unknown",
39672
+ withdrawalAddress,
39673
+ positionId
39674
+ );
39675
+ await this._relayNotification(message);
39600
39676
  } catch (telegramError) {
39601
39677
  console.error(
39602
39678
  "Telegram notification failed:",
@@ -39660,7 +39736,34 @@ Error data: ${errorData || "none"}`
39660
39736
  const bitcoinNetwork = this.getBitcoinNetwork();
39661
39737
  const mode = chainId === 1337 || chainId === 31337 || bitcoinNetwork === "regtest" ? "dev" : "prod";
39662
39738
  const bitcoin = await import("bitcoinjs-lib");
39663
- const { witnessStackToScriptWitness } = await import("bitcoinjs-lib/src/psbt/psbtutils");
39739
+ const encodeBitcoinVarInt = (value) => {
39740
+ if (value < 253) {
39741
+ return Buffer.from([value]);
39742
+ }
39743
+ if (value <= 65535) {
39744
+ const buf2 = Buffer.allocUnsafe(3);
39745
+ buf2[0] = 253;
39746
+ buf2.writeUInt16LE(value, 1);
39747
+ return buf2;
39748
+ }
39749
+ if (value <= 4294967295) {
39750
+ const buf2 = Buffer.allocUnsafe(5);
39751
+ buf2[0] = 254;
39752
+ buf2.writeUInt32LE(value, 1);
39753
+ return buf2;
39754
+ }
39755
+ const buf = Buffer.allocUnsafe(9);
39756
+ buf[0] = 255;
39757
+ buf.writeBigUInt64LE(BigInt(value), 1);
39758
+ return buf;
39759
+ };
39760
+ const witnessStackToScriptWitness = (witness) => {
39761
+ const serializedChunks = [encodeBitcoinVarInt(witness.length)];
39762
+ for (const item of witness) {
39763
+ serializedChunks.push(encodeBitcoinVarInt(item.length), item);
39764
+ }
39765
+ return Buffer.concat(serializedChunks);
39766
+ };
39664
39767
  const networks2 = bitcoinNetwork === "mainnet" ? bitcoin.networks.bitcoin : bitcoinNetwork === "regtest" ? bitcoin.networks.regtest : bitcoin.networks.testnet;
39665
39768
  if (this.config.debug) {
39666
39769
  log.info("\u{1F4CB} Network configuration", {
@@ -41475,7 +41578,7 @@ export {
41475
41578
  ErrorSeverity,
41476
41579
  EventHelpers,
41477
41580
  LOCALHOST_CONTRACTS,
41478
- Cache as LRUCache,
41581
+ LRUCache,
41479
41582
  LoanCreator,
41480
41583
  LoanQuery,
41481
41584
  LoanStatus,