@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.js CHANGED
@@ -12962,68 +12962,66 @@ var init_deployment_addresses = __esm({
12962
12962
  LOCALHOST_DEPLOYMENT = {
12963
12963
  network: "localhost",
12964
12964
  chainId: 31337,
12965
- timestamp: "2026-04-23T13:26:13.607Z",
12965
+ timestamp: "2026-03-23T15:33:34.068Z",
12966
12966
  deployer: "",
12967
12967
  contracts: {
12968
- MessageHashBuilder: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
12969
- UpgradeValidator: "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
12968
+ MessageHashBuilder: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
12969
+ UpgradeValidator: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
12970
12970
  UCDToken: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
12971
12971
  UCDController: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
12972
- PositionManagerCoreModule: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
12973
- TermManagerModule: "0x9A676e781A523b5d0C0e43731313A708CB607508",
12974
- LoanOperationsManagerModule: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
12972
+ PositionManagerCoreModule: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
12973
+ TermManagerModule: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
12974
+ LoanOperationsManagerModule: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
12975
12975
  BTCSpendAuthorizer: "0x59b670e9fA9D0A427751Af201D676719a970857b",
12976
12976
  CollateralManagerModule: "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
12977
12977
  LiquidationManagerModule: "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
12978
- CircuitBreakerModule: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
12978
+ CircuitBreakerModule: "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
12979
12979
  AdminModule: "0xc5a5C42992dECbae36851359345FE25997F5C42d",
12980
- PositionManagerViews: "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
12981
- PositionManager: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
12982
- OperationAuthorizationRegistry: "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f",
12983
- PKPValidation: "0x04C89607413713Ec9775E14b954286519d836FEf"
12980
+ PositionManagerViews: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
12981
+ PositionManager: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
12982
+ OperationAuthorizationRegistry: "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0",
12983
+ PKPValidation: "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc"
12984
12984
  },
12985
12985
  latestEnv: {
12986
12986
  UCD_TOKEN: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
12987
12987
  UCD_CONTROLLER: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
12988
- POSITION_MANAGER: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
12989
- PKP_VALIDATION_REGISTRY: "0x04C89607413713Ec9775E14b954286519d836FEf",
12990
- PKP_VALIDATION_CID_V1: "0x12200ba1a8948ea70b30205d738407bc9ed00ccb456bf78d8cad1a7574eafd3da24b",
12991
- PKP_VALIDATION_CID_V3: "0x12200ba1a8948ea70b30205d738407bc9ed00ccb456bf78d8cad1a7574eafd3da24b",
12992
- PKP_ETH_ADDRESS: "0xBC9de87F56856F0D424d705911c07dE213544172",
12993
- OPERATION_AUTHORIZATION_REGISTRY: "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f",
12994
- UCD_MINT_VALIDATOR_ADDRESS: "0xC6E57a5d65e43910Fe70667C97D193FAF6dDF598",
12988
+ POSITION_MANAGER: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
12989
+ PKP_VALIDATION_REGISTRY: "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc",
12990
+ PKP_VALIDATION_CID_V1: "QmfHJKA4RnW7RepsdLmrDwKjVTzPXB2K3qMTco3JNPDexm",
12991
+ PKP_ETH_ADDRESS: "0x9624C46073E1d1F5AB975c67Fc899536d599bb57",
12992
+ OPERATION_AUTHORIZATION_REGISTRY: "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0",
12993
+ UCD_MINT_VALIDATOR_ADDRESS: "0x80f81afb9e6dF27afCD752ad46cD286e705e42be",
12995
12994
  UCD_MINT_VALIDATOR_VERSION: 1,
12996
- BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0xe3B7bc797fA187AB9e29266bE8E01d58Cd49A6E9",
12995
+ BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0xa751ad81E1CAe61d6cF5Cf64839Fe8D28A1372Df",
12997
12996
  BTC_WITHDRAWAL_VALIDATOR_VERSION: 1,
12998
- UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x9e1831004c7ccf088468dC18F70b1B80c6Ec0c56",
12997
+ UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x8A40C22B03348bc10df9ae0dc54346b4AE8e909c",
12999
12998
  UPDATE_BALANCE_VALIDATOR_VERSION: 1,
13000
- PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x2297DabE0220a999d01B5BB603Ff2433CF908043",
12999
+ PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x28f50E07532d3aF677b8E0bcF220422d159b0dd6",
13001
13000
  PROCESS_PAYMENT_VALIDATOR_VERSION: 1,
13002
- EXTEND_POSITION_VALIDATOR_ADDRESS: "0x57d0f6E62b8f592dd23DEbD5F60dDEc843cd1835",
13001
+ EXTEND_POSITION_VALIDATOR_ADDRESS: "0xc7aC43F2F907123465449575e853f5D0229898e1",
13003
13002
  EXTEND_POSITION_VALIDATOR_VERSION: 1,
13004
- POSITION_MANAGER_CORE_MODULE: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
13005
- LOAN_OPERATIONS_MANAGER_MODULE: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
13006
- TERM_MANAGER_MODULE: "0x9A676e781A523b5d0C0e43731313A708CB607508",
13007
- COMMUNITY_MANAGER_MODULE: ""
13003
+ POSITION_MANAGER_CORE_MODULE: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
13004
+ LOAN_OPERATIONS_MANAGER_MODULE: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
13005
+ TERM_MANAGER_MODULE: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82"
13008
13006
  }
13009
13007
  };
13010
13008
  LOCALHOST_CONTRACTS = {
13011
- MessageHashBuilder: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
13012
- UpgradeValidator: "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
13009
+ MessageHashBuilder: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
13010
+ UpgradeValidator: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
13013
13011
  UCDToken: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
13014
13012
  UCDController: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
13015
- PositionManagerCoreModule: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
13016
- TermManagerModule: "0x9A676e781A523b5d0C0e43731313A708CB607508",
13017
- LoanOperationsManagerModule: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
13013
+ PositionManagerCoreModule: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
13014
+ TermManagerModule: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
13015
+ LoanOperationsManagerModule: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
13018
13016
  BTCSpendAuthorizer: "0x59b670e9fA9D0A427751Af201D676719a970857b",
13019
13017
  CollateralManagerModule: "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
13020
13018
  LiquidationManagerModule: "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
13021
- CircuitBreakerModule: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
13019
+ CircuitBreakerModule: "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
13022
13020
  AdminModule: "0xc5a5C42992dECbae36851359345FE25997F5C42d",
13023
- PositionManagerViews: "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
13024
- PositionManager: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
13025
- OperationAuthorizationRegistry: "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f",
13026
- PKPValidation: "0x04C89607413713Ec9775E14b954286519d836FEf"
13021
+ PositionManagerViews: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
13022
+ PositionManager: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
13023
+ OperationAuthorizationRegistry: "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0",
13024
+ PKPValidation: "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc"
13027
13025
  };
13028
13026
  ALL_DEPLOYMENTS = {
13029
13027
  sepolia: SEPOLIA_DEPLOYMENT,
@@ -13349,7 +13347,7 @@ __export(src_exports, {
13349
13347
  ErrorSeverity: () => ErrorSeverity,
13350
13348
  EventHelpers: () => EventHelpers,
13351
13349
  LOCALHOST_CONTRACTS: () => LOCALHOST_CONTRACTS,
13352
- LRUCache: () => Cache,
13350
+ LRUCache: () => LRUCache,
13353
13351
  LoanCreator: () => LoanCreator,
13354
13352
  LoanQuery: () => LoanQuery,
13355
13353
  LoanStatus: () => LoanStatus,
@@ -29565,8 +29563,6 @@ function validateQuantumTiming(signedTimestamp, _bufferSeconds = 30) {
29565
29563
  var PKP_NFT_ABI = [
29566
29564
  "function getPubkey(uint256 tokenId) external view returns (bytes memory)"
29567
29565
  ];
29568
- var CHIPOTLE_RPC_URL = "https://yellowstone-rpc.litprotocol.com";
29569
- var CHIPOTLE_CHAIN_ID = 175188;
29570
29566
  async function generateMintAuthorization(positionId, amount, chainId, signerOrPrecomputed) {
29571
29567
  if (typeof signerOrPrecomputed === "object" && "signature" in signerOrPrecomputed && !("signMessage" in signerOrPrecomputed)) {
29572
29568
  const { timestamp: timestamp2, signature: signature3 } = signerOrPrecomputed;
@@ -29666,18 +29662,14 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signer)
29666
29662
  };
29667
29663
  }
29668
29664
  async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAddress) {
29669
- const targetRpc = CHIPOTLE_RPC_URL;
29670
- const targetChainId = CHIPOTLE_CHAIN_ID;
29671
- let litChainProvider;
29672
- if (provider) {
29673
- const network = await provider.getNetwork();
29674
- if (network.chainId === targetChainId) {
29675
- litChainProvider = provider;
29676
- } else {
29677
- litChainProvider = new ethers_exports.providers.JsonRpcProvider(targetRpc);
29678
- }
29679
- } else {
29680
- litChainProvider = new ethers_exports.providers.JsonRpcProvider(targetRpc);
29665
+ const rawHex = pkpTokenId.startsWith("0x") ? pkpTokenId.slice(2) : pkpTokenId;
29666
+ if (rawHex.length === 64 && rawHex.startsWith("000000000000000000000000") && rawHex !== "0".repeat(64)) {
29667
+ throw new Error(
29668
+ `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.`
29669
+ );
29670
+ }
29671
+ if (!provider) {
29672
+ throw new Error(`provider is required for getPKPPublicKeyFromTokenId`);
29681
29673
  }
29682
29674
  if (!pkpNftContractAddress) {
29683
29675
  throw new Error(
@@ -29687,7 +29679,7 @@ async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAd
29687
29679
  const pkpNft = new ethers_exports.Contract(
29688
29680
  pkpNftContractAddress,
29689
29681
  PKP_NFT_ABI,
29690
- litChainProvider
29682
+ provider
29691
29683
  );
29692
29684
  const tokenIdBN = ethers_exports.BigNumber.from(pkpTokenId);
29693
29685
  const pubkeyBytes = await pkpNft["getPubkey"](tokenIdBN);
@@ -30292,106 +30284,333 @@ function createContractManager(config) {
30292
30284
  }
30293
30285
 
30294
30286
  // src/modules/cache/cache-manager.module.ts
30295
- var Cache = class {
30296
- cache = /* @__PURE__ */ new Map();
30287
+ var LRUCache = class {
30288
+ cache;
30297
30289
  maxSize;
30298
30290
  ttlMs;
30299
- constructor(config) {
30300
- this.maxSize = config.maxSize;
30301
- this.ttlMs = config.ttlMs;
30291
+ debug;
30292
+ name;
30293
+ // Statistics
30294
+ stats = {
30295
+ hits: 0,
30296
+ misses: 0,
30297
+ evictions: 0
30298
+ };
30299
+ constructor(config = {}) {
30300
+ this.cache = /* @__PURE__ */ new Map();
30301
+ this.maxSize = config.maxSize || 1e3;
30302
+ this.ttlMs = config.ttlMs || 6e4;
30303
+ this.debug = config.debug || false;
30304
+ this.name = config.name || "Cache";
30305
+ if (this.debug) {
30306
+ console.log(
30307
+ `\u{1F4BE} [${this.name}] Initialized: maxSize=${this.maxSize}, ttl=${this.ttlMs}ms`
30308
+ );
30309
+ }
30302
30310
  }
30303
30311
  /**
30304
30312
  * Get value from cache
30313
+ *
30314
+ * Returns null if:
30315
+ * - Key not found
30316
+ * - Entry has expired
30317
+ *
30318
+ * @param key - Cache key
30319
+ * @returns Cached value or null
30305
30320
  */
30306
30321
  get(key2) {
30307
30322
  const entry = this.cache.get(key2);
30308
30323
  if (!entry) {
30309
- return void 0;
30324
+ this.stats.misses++;
30325
+ if (this.debug) {
30326
+ console.log(`\u274C [${this.name}] Cache MISS: ${String(key2)}`);
30327
+ }
30328
+ return null;
30310
30329
  }
30311
- const now2 = Date.now();
30312
- if (now2 - entry.timestamp > entry.ttl) {
30330
+ if (this.isExpired(entry)) {
30313
30331
  this.cache.delete(key2);
30314
- return void 0;
30332
+ this.stats.misses++;
30333
+ if (this.debug) {
30334
+ const age = Date.now() - entry.timestamp;
30335
+ console.log(`\u23F0 [${this.name}] Cache EXPIRED: ${String(key2)} (age: ${age}ms)`);
30336
+ }
30337
+ return null;
30338
+ }
30339
+ entry.hits++;
30340
+ entry.lastAccessed = Date.now();
30341
+ this.cache.set(key2, entry);
30342
+ this.stats.hits++;
30343
+ if (this.debug) {
30344
+ const age = Date.now() - entry.timestamp;
30345
+ console.log(
30346
+ `\u2705 [${this.name}] Cache HIT: ${String(key2)} (age: ${age}ms, hits: ${entry.hits})`
30347
+ );
30315
30348
  }
30316
30349
  return entry.value;
30317
30350
  }
30351
+ /**
30352
+ * Get value from cache with Result wrapper
30353
+ *
30354
+ * Useful when you want to distinguish between "not found" and "expired"
30355
+ */
30356
+ getResult(key2) {
30357
+ const value = this.get(key2);
30358
+ if (value === null) {
30359
+ return failure(
30360
+ new SDKError({
30361
+ message: `Cache miss for key: ${String(key2)}`,
30362
+ category: "CACHE" /* CACHE */,
30363
+ severity: "LOW" /* LOW */,
30364
+ originalError: new Error("Cache miss")
30365
+ })
30366
+ );
30367
+ }
30368
+ return success(value);
30369
+ }
30318
30370
  /**
30319
30371
  * Set value in cache
30372
+ *
30373
+ * If cache is full, evicts the least recently used entry
30374
+ *
30375
+ * @param key - Cache key
30376
+ * @param value - Value to cache
30377
+ * @param ttl - Optional custom TTL for this entry (ms)
30320
30378
  */
30321
30379
  set(key2, value, ttl) {
30322
30380
  if (this.cache.size >= this.maxSize && !this.cache.has(key2)) {
30323
- const firstKey = this.cache.keys().next().value;
30324
- if (firstKey) {
30325
- this.cache.delete(firstKey);
30326
- }
30381
+ this.evictLRU();
30327
30382
  }
30328
- this.cache.set(key2, {
30383
+ const entry = {
30329
30384
  value,
30330
30385
  timestamp: Date.now(),
30331
- ttl: ttl || this.ttlMs
30332
- });
30386
+ hits: 0,
30387
+ lastAccessed: Date.now()
30388
+ };
30389
+ this.cache.set(key2, entry);
30390
+ if (this.debug) {
30391
+ const effectiveTtl = ttl || this.ttlMs;
30392
+ console.log(
30393
+ `\u{1F4BE} [${this.name}] Cache SET: ${String(key2)} (ttl: ${effectiveTtl}ms, size: ${this.cache.size}/${this.maxSize})`
30394
+ );
30395
+ }
30333
30396
  }
30334
30397
  /**
30335
- * Check if key exists in cache
30398
+ * Set value in cache with Result wrapper
30399
+ */
30400
+ setResult(key2, value, ttl) {
30401
+ try {
30402
+ this.set(key2, value, ttl);
30403
+ return success(void 0);
30404
+ } catch (error) {
30405
+ return failure(
30406
+ new SDKError({
30407
+ message: `Failed to set cache value for key: ${String(key2)}`,
30408
+ category: "CACHE" /* CACHE */,
30409
+ severity: "MEDIUM" /* MEDIUM */,
30410
+ originalError: error instanceof Error ? error : new Error(String(error))
30411
+ })
30412
+ );
30413
+ }
30414
+ }
30415
+ /**
30416
+ * Check if key exists in cache (without affecting stats)
30336
30417
  */
30337
30418
  has(key2) {
30338
- return this.get(key2) !== void 0;
30419
+ const entry = this.cache.get(key2);
30420
+ return entry !== void 0 && !this.isExpired(entry);
30339
30421
  }
30340
30422
  /**
30341
- * Delete key from cache
30423
+ * Delete specific key from cache
30342
30424
  */
30343
30425
  delete(key2) {
30344
- return this.cache.delete(key2);
30426
+ const deleted = this.cache.delete(key2);
30427
+ if (deleted && this.debug) {
30428
+ console.log(`\u{1F5D1}\uFE0F [${this.name}] Cache DELETE: ${String(key2)}`);
30429
+ }
30430
+ return deleted;
30345
30431
  }
30346
30432
  /**
30347
- * Clear all cache entries
30433
+ * Clear entire cache
30348
30434
  */
30349
30435
  clear() {
30436
+ const previousSize = this.cache.size;
30350
30437
  this.cache.clear();
30438
+ this.stats = {
30439
+ hits: 0,
30440
+ misses: 0,
30441
+ evictions: 0
30442
+ };
30443
+ if (this.debug) {
30444
+ console.log(`\u{1F9F9} [${this.name}] Cache CLEARED: removed ${previousSize} entries`);
30445
+ }
30446
+ }
30447
+ /**
30448
+ * Get current cache size
30449
+ */
30450
+ size() {
30451
+ return this.cache.size;
30452
+ }
30453
+ /**
30454
+ * Get cache statistics
30455
+ */
30456
+ getStats() {
30457
+ const entries = Array.from(this.cache.values());
30458
+ const timestamps = entries.map((e) => e.timestamp);
30459
+ const total = this.stats.hits + this.stats.misses;
30460
+ const hitRate = total === 0 ? 0 : this.stats.hits / total * 100;
30461
+ return {
30462
+ size: this.cache.size,
30463
+ hits: this.stats.hits,
30464
+ misses: this.stats.misses,
30465
+ evictions: this.stats.evictions,
30466
+ oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : 0,
30467
+ newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : 0,
30468
+ hitRate
30469
+ };
30470
+ }
30471
+ /**
30472
+ * Get hit rate percentage
30473
+ */
30474
+ getHitRate() {
30475
+ const total = this.stats.hits + this.stats.misses;
30476
+ return total === 0 ? 0 : this.stats.hits / total * 100;
30477
+ }
30478
+ /**
30479
+ * Get all cached keys (for debugging)
30480
+ */
30481
+ getKeys() {
30482
+ return Array.from(this.cache.keys());
30483
+ }
30484
+ /**
30485
+ * Get all cached values (for debugging)
30486
+ */
30487
+ getValues() {
30488
+ return Array.from(this.cache.values()).map((entry) => entry.value);
30489
+ }
30490
+ /**
30491
+ * Get all cache entries with metadata (for debugging)
30492
+ */
30493
+ getEntries() {
30494
+ return Array.from(this.cache.entries()).map(([key2, entry]) => ({
30495
+ key: key2,
30496
+ value: entry.value,
30497
+ metadata: {
30498
+ timestamp: entry.timestamp,
30499
+ hits: entry.hits,
30500
+ lastAccessed: entry.lastAccessed
30501
+ }
30502
+ }));
30351
30503
  }
30352
30504
  /**
30353
- * Clean expired entries
30505
+ * Clean up expired entries
30506
+ *
30507
+ * Useful for periodic maintenance
30508
+ *
30509
+ * @returns Number of entries cleaned
30354
30510
  */
30355
30511
  cleanExpired() {
30356
30512
  const now2 = Date.now();
30357
- let cleaned = 0;
30513
+ let cleanedCount = 0;
30358
30514
  for (const [key2, entry] of this.cache.entries()) {
30359
- if (now2 - entry.timestamp > entry.ttl) {
30515
+ if (now2 - entry.timestamp > this.ttlMs) {
30360
30516
  this.cache.delete(key2);
30361
- cleaned++;
30517
+ cleanedCount++;
30362
30518
  }
30363
30519
  }
30364
- return cleaned;
30520
+ if (cleanedCount > 0 && this.debug) {
30521
+ console.log(`\u{1F9F9} [${this.name}] Cleaned ${cleanedCount} expired entries`);
30522
+ }
30523
+ return cleanedCount;
30365
30524
  }
30366
30525
  /**
30367
- * Get cache statistics
30526
+ * Check if cache entry is expired
30368
30527
  */
30369
- getStats() {
30370
- return {
30371
- size: this.cache.size,
30372
- maxSize: this.maxSize,
30373
- ttlMs: this.ttlMs
30374
- };
30528
+ isExpired(entry) {
30529
+ return Date.now() - entry.timestamp > this.ttlMs;
30530
+ }
30531
+ /**
30532
+ * Evict least recently used entry
30533
+ */
30534
+ evictLRU() {
30535
+ let oldestKey = null;
30536
+ let oldestAccess = Infinity;
30537
+ for (const [key2, entry] of this.cache.entries()) {
30538
+ if (entry.lastAccessed < oldestAccess) {
30539
+ oldestAccess = entry.lastAccessed;
30540
+ oldestKey = key2;
30541
+ }
30542
+ }
30543
+ if (oldestKey !== null) {
30544
+ this.cache.delete(oldestKey);
30545
+ this.stats.evictions++;
30546
+ if (this.debug) {
30547
+ const timeSinceAccess = Date.now() - oldestAccess;
30548
+ console.log(
30549
+ `\u267B\uFE0F [${this.name}] Cache EVICT (LRU): ${String(oldestKey)} (last accessed: ${timeSinceAccess}ms ago)`
30550
+ );
30551
+ }
30552
+ }
30553
+ }
30554
+ /**
30555
+ * Get or compute value
30556
+ *
30557
+ * If key exists in cache, returns cached value.
30558
+ * Otherwise, computes value using provided function and caches it.
30559
+ *
30560
+ * @param key - Cache key
30561
+ * @param compute - Function to compute value if not in cache
30562
+ * @param ttl - Optional custom TTL for this entry
30563
+ * @returns Cached or computed value
30564
+ */
30565
+ async getOrCompute(key2, compute, ttl) {
30566
+ const cached = this.get(key2);
30567
+ if (cached !== null) {
30568
+ return cached;
30569
+ }
30570
+ const value = await compute();
30571
+ this.set(key2, value, ttl);
30572
+ return value;
30573
+ }
30574
+ /**
30575
+ * Get or compute value with Result wrapper
30576
+ */
30577
+ async getOrComputeResult(key2, compute, ttl) {
30578
+ const cached = this.get(key2);
30579
+ if (cached !== null) {
30580
+ return success(cached);
30581
+ }
30582
+ const result = await compute();
30583
+ if (result.success) {
30584
+ this.set(key2, result.value, ttl);
30585
+ }
30586
+ return result;
30375
30587
  }
30376
30588
  };
30377
30589
  var CacheManager = class {
30378
30590
  caches = /* @__PURE__ */ new Map();
30379
- debug;
30380
- constructor(config = {}) {
30381
- this.debug = config.debug || false;
30591
+ globalConfig;
30592
+ constructor(globalConfig = {}) {
30593
+ this.globalConfig = globalConfig;
30382
30594
  }
30383
30595
  /**
30384
- * Get or create a cache instance
30596
+ * Create or get a named cache
30597
+ *
30598
+ * @param name - Unique cache name
30599
+ * @param config - Optional cache-specific configuration
30600
+ * @returns LRU cache instance
30385
30601
  */
30386
30602
  getCache(name, config) {
30387
- if (this.caches.has(name)) {
30388
- return this.caches.get(name);
30603
+ const existingCache = this.caches.get(name);
30604
+ if (existingCache) {
30605
+ return existingCache;
30389
30606
  }
30390
- const cache = new Cache(config);
30607
+ const mergedConfig = {
30608
+ ...this.globalConfig,
30609
+ ...config,
30610
+ name
30611
+ };
30612
+ const cache = new LRUCache(mergedConfig);
30391
30613
  this.caches.set(name, cache);
30392
- if (this.debug) {
30393
- console.log(`[CacheManager] Created cache: ${name}`, config);
30394
- }
30395
30614
  return cache;
30396
30615
  }
30397
30616
  /**
@@ -30406,11 +30625,11 @@ var CacheManager = class {
30406
30625
  * Clean expired entries from all caches
30407
30626
  */
30408
30627
  cleanAllExpired() {
30409
- let total = 0;
30628
+ let totalCleaned = 0;
30410
30629
  for (const cache of this.caches.values()) {
30411
- total += cache.cleanExpired();
30630
+ totalCleaned += cache.cleanExpired();
30412
30631
  }
30413
- return total;
30632
+ return totalCleaned;
30414
30633
  }
30415
30634
  /**
30416
30635
  * Get statistics for all caches
@@ -30423,11 +30642,16 @@ var CacheManager = class {
30423
30642
  return stats;
30424
30643
  }
30425
30644
  /**
30426
- * Destroy cache manager
30645
+ * Get list of all cache names
30427
30646
  */
30428
- destroy() {
30429
- this.clearAll();
30430
- this.caches.clear();
30647
+ getCacheNames() {
30648
+ return Array.from(this.caches.keys());
30649
+ }
30650
+ /**
30651
+ * Delete a named cache
30652
+ */
30653
+ deleteCache(name) {
30654
+ return this.caches.delete(name);
30431
30655
  }
30432
30656
  };
30433
30657
  function createCacheManager(config) {
@@ -31706,6 +31930,23 @@ function createLoanCreator(config) {
31706
31930
  }
31707
31931
 
31708
31932
  // src/modules/loan/loan-query.module.ts
31933
+ var POSITION_CORE_ABI = [
31934
+ "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))"
31935
+ ];
31936
+ function normalizePkpId(pkpId) {
31937
+ const raw = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
31938
+ if (raw.length === 64 && raw.startsWith("000000000000000000000000") && raw !== "0".repeat(64)) {
31939
+ return `0x${raw.slice(24)}`;
31940
+ }
31941
+ return pkpId;
31942
+ }
31943
+ function padPkpIdForSubgraph(pkpId) {
31944
+ const raw = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
31945
+ if (raw.length === 40) {
31946
+ return `0x${"0".repeat(24)}${raw}`;
31947
+ }
31948
+ return pkpId;
31949
+ }
31709
31950
  var LoanQuery = class {
31710
31951
  config;
31711
31952
  defaultPageSize;
@@ -31734,7 +31975,7 @@ var LoanQuery = class {
31734
31975
  const borrowerCreatedAt = typeof rawLoan.borrower === "object" && rawLoan.borrower?.createdAt ? Number(rawLoan.borrower.createdAt) : 0;
31735
31976
  const loanData = {
31736
31977
  id: rawLoan.id,
31737
- pkpId: rawLoan.pkpId,
31978
+ pkpId: normalizePkpId(rawLoan.pkpId),
31738
31979
  borrower: {
31739
31980
  createdAt: borrowerCreatedAt,
31740
31981
  id: borrowerId
@@ -31780,6 +32021,7 @@ var LoanQuery = class {
31780
32021
  * @returns Loan data
31781
32022
  */
31782
32023
  async getLoanByPkpId(pkpId, enrichBalance = false) {
32024
+ pkpId = padPkpIdForSubgraph(pkpId);
31783
32025
  if (this.config.debug) {
31784
32026
  log.info("\u{1F50D} Querying loan by PKP ID", { pkpId, enrichBalance });
31785
32027
  }
@@ -31802,7 +32044,7 @@ var LoanQuery = class {
31802
32044
  const borrowerCreatedAt = typeof rawLoan.borrower === "object" && rawLoan.borrower?.createdAt ? Number(rawLoan.borrower.createdAt) : 0;
31803
32045
  const loanData = {
31804
32046
  id: rawLoan.id,
31805
- pkpId: rawLoan.pkpId,
32047
+ pkpId: normalizePkpId(rawLoan.pkpId),
31806
32048
  borrower: {
31807
32049
  createdAt: borrowerCreatedAt,
31808
32050
  id: borrowerId
@@ -31981,10 +32223,30 @@ var LoanQuery = class {
31981
32223
  await Promise.all(
31982
32224
  batch.map(async (loan) => {
31983
32225
  try {
31984
- const pkpPublicKey = await getPKPPublicKeyFromTokenId(
31985
- loan.pkpId,
31986
- this.config.provider
31987
- );
32226
+ const rawId = loan.pkpId?.startsWith("0x") ? loan.pkpId.slice(2) : loan.pkpId;
32227
+ const isChipotlePkpId = typeof rawId === "string" && rawId.length === 40 && !rawId.toLowerCase().startsWith("04");
32228
+ if (isChipotlePkpId) {
32229
+ if (this.config.positionManagerCoreAddress && this.config.provider) {
32230
+ const pmContract = new ethers_exports.Contract(
32231
+ this.config.positionManagerCoreAddress,
32232
+ POSITION_CORE_ABI,
32233
+ this.config.provider
32234
+ );
32235
+ const pos = await pmContract["getPositionDetails"](loan.id);
32236
+ const vaultAddr = pos.vaultAddress ?? pos[3] ?? "";
32237
+ if (vaultAddr) {
32238
+ loan.collateral.vaultAddress = vaultAddr;
32239
+ if (this.config.debug) {
32240
+ log.info(`\u2705 Vault address from contract for loan ${loan.id}`, { vaultAddr });
32241
+ }
32242
+ }
32243
+ } else if (this.config.debug) {
32244
+ log.warn(`\u26A0\uFE0F Chipotle pkpId for loan ${loan.id} but no positionManagerCoreAddress configured`);
32245
+ }
32246
+ return;
32247
+ }
32248
+ const isUncompressedPubKey = typeof rawId === "string" && rawId.length === 130 && rawId.toLowerCase().startsWith("04");
32249
+ const pkpPublicKey = isUncompressedPubKey ? loan.pkpId.startsWith("0x") ? loan.pkpId : `0x${loan.pkpId}` : await getPKPPublicKeyFromTokenId(loan.pkpId, this.config.provider);
31988
32250
  const addressesResult = await this.config.bitcoinOperations.deriveAddresses(pkpPublicKey);
31989
32251
  if (addressesResult.success) {
31990
32252
  loan.collateral.vaultAddress = addressesResult.value;
@@ -33420,6 +33682,13 @@ var GraphClient = class {
33420
33682
  var THE_GRAPH_MAX_BATCH_SIZE = 1e3;
33421
33683
 
33422
33684
  // src/graphs/diamond-hands.ts
33685
+ function normalizePkpId2(pkpId) {
33686
+ const raw = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
33687
+ if (raw.length === 64 && raw.startsWith("000000000000000000000000") && raw !== "0".repeat(64)) {
33688
+ return `0x${raw.slice(24)}`;
33689
+ }
33690
+ return pkpId;
33691
+ }
33423
33692
  var DiamondHandsGraph = class {
33424
33693
  client;
33425
33694
  defaultPageSize;
@@ -33442,7 +33711,7 @@ var DiamondHandsGraph = class {
33442
33711
  const ucdDebt = graphPosition.ucdDebt ? Number(graphPosition.ucdDebt) : 0;
33443
33712
  return {
33444
33713
  id: graphPosition.id,
33445
- pkpId: graphPosition.pkpId,
33714
+ pkpId: normalizePkpId2(graphPosition.pkpId),
33446
33715
  borrower: {
33447
33716
  createdAt: graphPosition.borrower?.createdAt ? Number(graphPosition.borrower.createdAt) : 0,
33448
33717
  id: graphPosition.borrower?.id || graphPosition.borrower
@@ -34704,39 +34973,6 @@ try {
34704
34973
  } catch (error) {
34705
34974
  console.warn("Telegram bot API not available:", error instanceof Error ? error.message : String(error));
34706
34975
  }
34707
- async function sendTelegramMessage(chatId, chatToken, message, threadId) {
34708
- try {
34709
- if (typeof window !== "undefined") {
34710
- if (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") {
34711
- console.log("[Browser] Telegram messaging not available - skipping notification");
34712
- }
34713
- return;
34714
- }
34715
- if (!TelegramBot) {
34716
- console.warn("Telegram bot API not available in this environment");
34717
- return;
34718
- }
34719
- const bot = new TelegramBot(chatToken, { polling: false });
34720
- const options = {
34721
- disable_web_page_preview: true
34722
- };
34723
- if (threadId !== void 0) {
34724
- options.message_thread_id = threadId;
34725
- }
34726
- console.log("\u{1F4F1} Sending Telegram message...");
34727
- console.log(` Chat ID: ${chatId}`);
34728
- console.log(` Thread ID: ${threadId || "none"}`);
34729
- console.log(` Message: ${message}`);
34730
- const result = await bot.sendMessage(chatId, message, options);
34731
- console.log("\u2705 Telegram message sent successfully!");
34732
- console.log(` Message ID: ${result.message_id}`);
34733
- } catch (error) {
34734
- console.error("\u274C Failed to send Telegram message:", error);
34735
- if (error instanceof Error) {
34736
- console.error(` Error message: ${error.message}`);
34737
- }
34738
- }
34739
- }
34740
34976
  function formatMintMessage(mintAmount, loanId, txHash) {
34741
34977
  return `${mintAmount} UCD was minted for loan id: ${loanId} Tx: https://sepolia.etherscan.io/tx/${txHash}`;
34742
34978
  }
@@ -35055,6 +35291,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35055
35291
  network: config.litNetwork || DEFAULT_LIT_NETWORK,
35056
35292
  signer: config.mode === "standalone" ? config.litOpsSigner : void 0,
35057
35293
  serviceEndpoint: isServiceModeConfig(config) ? config.serviceEndpoint : void 0,
35294
+ serviceAuthToken: isServiceModeConfig(config) ? config.serviceAuthToken : void 0,
35058
35295
  debug: config.debug,
35059
35296
  litNodeConnectTimeoutMs: config.litNodeConnectTimeoutMs
35060
35297
  // TODO Round 2: Add litActionExecution config when added to config.i.ts interface
@@ -35112,19 +35349,21 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35112
35349
  );
35113
35350
  }
35114
35351
  this.pkpManager = pkpManagerResult.value;
35115
- const graphEndpoint = config.subgraphs?.diamondHandsUrl;
35352
+ const serviceMode = isServiceModeConfig(config);
35353
+ const graphEndpoint = serviceMode ? `${config.serviceEndpoint}/api/lit/graph/query` : config.subgraphs?.diamondHandsUrl;
35116
35354
  if (!graphEndpoint) {
35117
35355
  throw new Error(
35118
35356
  "Diamond Hands subgraph URL is required. Please provide config.subgraphs.diamondHandsUrl"
35119
35357
  );
35120
35358
  }
35359
+ const graphHeaders = serviceMode && config.serviceAuthToken ? { Authorization: `Bearer ${config.serviceAuthToken}` } : config.graphApiKey ? { Authorization: `Bearer ${config.graphApiKey}` } : void 0;
35121
35360
  this.graphClient = new DiamondHandsGraph(
35122
35361
  {
35123
35362
  endpoint: graphEndpoint,
35124
35363
  requestTimeoutMs: config.graphOptions?.requestTimeoutMs,
35125
35364
  maxRetries: config.graphOptions?.maxRetries,
35126
35365
  defaultPageSize: config.graphOptions?.pageSize,
35127
- headers: config.graphApiKey ? { Authorization: `Bearer ${config.graphApiKey}` } : void 0
35366
+ headers: graphHeaders
35128
35367
  },
35129
35368
  this.bitcoinOperations
35130
35369
  );
@@ -35132,6 +35371,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35132
35371
  graphClient: this.graphClient,
35133
35372
  bitcoinOperations: this.bitcoinOperations,
35134
35373
  provider: config.provider,
35374
+ positionManagerCoreAddress: config.contractAddresses?.positionManagerCore,
35135
35375
  cache: this.cacheManager.getCache("loan-data", {
35136
35376
  maxSize: 200,
35137
35377
  ttlMs: 3e4
@@ -35523,6 +35763,30 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35523
35763
  /**
35524
35764
  * Check if SDK is ready for operations
35525
35765
  */
35766
+ async _relayNotification(message) {
35767
+ if (this.config.mode !== "service")
35768
+ return;
35769
+ const endpoint = this.config.serviceEndpoint;
35770
+ if (!endpoint)
35771
+ return;
35772
+ const token = this.config.serviceAuthToken;
35773
+ try {
35774
+ await fetch(`${endpoint}/api/lit/notifications/send`, {
35775
+ method: "POST",
35776
+ headers: {
35777
+ "Content-Type": "application/json",
35778
+ ...token ? { Authorization: `Bearer ${token}` } : {}
35779
+ },
35780
+ body: JSON.stringify({ message })
35781
+ });
35782
+ } catch (err) {
35783
+ if (this.config.debug) {
35784
+ log.warn("Notification relay failed", {
35785
+ error: err instanceof Error ? err.message : String(err)
35786
+ });
35787
+ }
35788
+ }
35789
+ }
35526
35790
  checkInitialized() {
35527
35791
  if (!this.isInitialized) {
35528
35792
  return failure(
@@ -35598,7 +35862,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35598
35862
  return failure(initCheck.error);
35599
35863
  }
35600
35864
  const result = await this.loanCreator.createLoan(request);
35601
- if (result.success && this.config.telegram && result.value.positionId) {
35865
+ if (result.success && result.value.positionId) {
35602
35866
  try {
35603
35867
  const message = formatLoanCreationMessage(
35604
35868
  result.value.positionId,
@@ -35610,12 +35874,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
35610
35874
  "\u{1F4F1} Attempting to send loan creation Telegram message..."
35611
35875
  );
35612
35876
  }
35613
- await sendTelegramMessage(
35614
- this.config.telegram.chatId,
35615
- this.config.telegram.chatToken,
35616
- message,
35617
- this.config.telegram.threadId
35618
- );
35877
+ await this._relayNotification(message);
35619
35878
  if (this.config.debug) {
35620
35879
  console.log("\u2705 Loan creation Telegram message sent successfully");
35621
35880
  }
@@ -36789,7 +37048,7 @@ Error data: ${errorData || "none"}`
36789
37048
  amountMintedUCD: Number(amountMinted) / 10 ** 18
36790
37049
  };
36791
37050
  try {
36792
- if (this.config.telegram && result.transactionHash) {
37051
+ if (result.transactionHash) {
36793
37052
  const mintAmount = result.amountMintedUCD || request.amount;
36794
37053
  const loanId = result.positionId || request.positionId;
36795
37054
  const message = formatMintMessage(
@@ -36797,12 +37056,7 @@ Error data: ${errorData || "none"}`
36797
37056
  loanId,
36798
37057
  result.transactionHash
36799
37058
  );
36800
- await sendTelegramMessage(
36801
- this.config.telegram.chatId,
36802
- this.config.telegram.chatToken,
36803
- message,
36804
- this.config.telegram.threadId
36805
- );
37059
+ await this._relayNotification(message);
36806
37060
  }
36807
37061
  } catch (err) {
36808
37062
  }
@@ -37064,39 +37318,32 @@ Error data: ${errorData || "none"}`
37064
37318
  }
37065
37319
  if (!shouldLiquidate) {
37066
37320
  try {
37067
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37068
- if (this.config.debug) {
37069
- log.info(`\u{1F4F1} Sending liquidation skipped Telegram message...`);
37070
- }
37071
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37072
- const btcPrice2 = litActionResult.btcPrice || "0";
37073
- const btcVaultBalance = litActionResult.btcAmountSats || positionDetails.btcVaultBalance || "0";
37074
- const usdPricePerBTC = Number(btcPrice2) / 1e8;
37075
- const btcAmount = Number(btcVaultBalance) / 1e8;
37076
- const btcValueUSD = btcAmount * usdPricePerBTC;
37077
- const debtUSD = Number(debt) / 1e18;
37078
- const ratio = debtUSD > 0 ? (btcValueUSD / debtUSD * 100).toFixed(2) : "0.00";
37079
- const message = formatLiquidationSkippedMessage(
37080
- request.positionId,
37081
- ratio,
37082
- `${liquidationThreshold / 100}`,
37083
- // Convert to percentage
37084
- positionDetails.vaultAddress || "unknown",
37085
- btcVaultBalance,
37086
- debt,
37087
- btcPrice2
37088
- );
37089
- await sendTelegramMessage(
37090
- this.config.telegram.chatId,
37091
- this.config.telegram.chatToken,
37092
- message,
37093
- this.config.telegram.threadId
37321
+ if (this.config.debug) {
37322
+ log.info(`\u{1F4F1} Sending liquidation skipped Telegram message...`);
37323
+ }
37324
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37325
+ const btcPrice2 = litActionResult.btcPrice || "0";
37326
+ const btcVaultBalance = litActionResult.btcAmountSats || positionDetails.btcVaultBalance || "0";
37327
+ const usdPricePerBTC = Number(btcPrice2) / 1e8;
37328
+ const btcAmount = Number(btcVaultBalance) / 1e8;
37329
+ const btcValueUSD = btcAmount * usdPricePerBTC;
37330
+ const debtUSD = Number(debt) / 1e18;
37331
+ const ratio = debtUSD > 0 ? (btcValueUSD / debtUSD * 100).toFixed(2) : "0.00";
37332
+ const message = formatLiquidationSkippedMessage(
37333
+ request.positionId,
37334
+ ratio,
37335
+ `${liquidationThreshold / 100}`,
37336
+ // Convert to percentage
37337
+ positionDetails.vaultAddress || "unknown",
37338
+ btcVaultBalance,
37339
+ debt,
37340
+ btcPrice2
37341
+ );
37342
+ await this._relayNotification(message);
37343
+ if (this.config.debug) {
37344
+ log.info(
37345
+ `\u2705 Liquidation skipped Telegram message sent successfully`
37094
37346
  );
37095
- if (this.config.debug) {
37096
- log.info(
37097
- `\u2705 Liquidation skipped Telegram message sent successfully`
37098
- );
37099
- }
37100
37347
  }
37101
37348
  } catch (telegramError) {
37102
37349
  if (this.config.debug) {
@@ -37151,32 +37398,25 @@ Error data: ${errorData || "none"}`
37151
37398
  });
37152
37399
  }
37153
37400
  try {
37154
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37155
- if (this.config.debug) {
37156
- log.info(`\u{1F4F1} Sending LIT action rejection Telegram message...`);
37157
- }
37158
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37159
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37160
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37161
- const message = formatLiquidationFailureMessage(
37162
- request.positionId,
37163
- `LIT Action rejected liquidation: ${litActionResult.reason || litActionResult.error || "Unknown error"}`,
37164
- positionDetails.vaultAddress || "unknown",
37165
- btcVaultBalance,
37166
- debt,
37167
- btcPrice2
37168
- );
37169
- await sendTelegramMessage(
37170
- this.config.telegram.chatId,
37171
- this.config.telegram.chatToken,
37172
- message,
37173
- this.config.telegram.threadId
37401
+ if (this.config.debug) {
37402
+ log.info(`\u{1F4F1} Sending LIT action rejection Telegram message...`);
37403
+ }
37404
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37405
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37406
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37407
+ const message = formatLiquidationFailureMessage(
37408
+ request.positionId,
37409
+ `LIT Action rejected liquidation: ${litActionResult.reason || litActionResult.error || "Unknown error"}`,
37410
+ positionDetails.vaultAddress || "unknown",
37411
+ btcVaultBalance,
37412
+ debt,
37413
+ btcPrice2
37414
+ );
37415
+ await this._relayNotification(message);
37416
+ if (this.config.debug) {
37417
+ log.info(
37418
+ `\u2705 LIT action rejection Telegram message sent successfully`
37174
37419
  );
37175
- if (this.config.debug) {
37176
- log.info(
37177
- `\u2705 LIT action rejection Telegram message sent successfully`
37178
- );
37179
- }
37180
37420
  }
37181
37421
  } catch (telegramError) {
37182
37422
  if (this.config.debug) {
@@ -37198,32 +37438,25 @@ Error data: ${errorData || "none"}`
37198
37438
  );
37199
37439
  }
37200
37440
  try {
37201
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37202
- if (this.config.debug) {
37203
- log.info(`\u{1F4F1} Sending forced liquidation Telegram message...`);
37204
- }
37205
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37206
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37207
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37208
- const message = formatLiquidationFailureMessage(
37209
- request.positionId,
37210
- `FORCED LIQUIDATION: LIT Action rejected but forceContractCall=true - proceeding with liquidation`,
37211
- positionDetails.vaultAddress || "unknown",
37212
- btcVaultBalance,
37213
- debt,
37214
- btcPrice2
37215
- );
37216
- await sendTelegramMessage(
37217
- this.config.telegram.chatId,
37218
- this.config.telegram.chatToken,
37219
- message,
37220
- this.config.telegram.threadId
37441
+ if (this.config.debug) {
37442
+ log.info(`\u{1F4F1} Sending forced liquidation Telegram message...`);
37443
+ }
37444
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37445
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37446
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37447
+ const message = formatLiquidationFailureMessage(
37448
+ request.positionId,
37449
+ `FORCED LIQUIDATION: LIT Action rejected but forceContractCall=true - proceeding with liquidation`,
37450
+ positionDetails.vaultAddress || "unknown",
37451
+ btcVaultBalance,
37452
+ debt,
37453
+ btcPrice2
37454
+ );
37455
+ await this._relayNotification(message);
37456
+ if (this.config.debug) {
37457
+ log.info(
37458
+ `\u2705 Forced liquidation Telegram message sent successfully`
37221
37459
  );
37222
- if (this.config.debug) {
37223
- log.info(
37224
- `\u2705 Forced liquidation Telegram message sent successfully`
37225
- );
37226
- }
37227
37460
  }
37228
37461
  } catch (telegramError) {
37229
37462
  if (this.config.debug) {
@@ -37256,34 +37489,27 @@ Error data: ${errorData || "none"}`
37256
37489
  );
37257
37490
  }
37258
37491
  try {
37259
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37260
- if (this.config.debug) {
37261
- log.info(
37262
- `\u{1F4F1} Sending forced liquidation without signature Telegram message...`
37263
- );
37264
- }
37265
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37266
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37267
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37268
- const message = formatLiquidationFailureMessage(
37269
- request.positionId,
37270
- "FORCED LIQUIDATION: LIT Action did not provide signature but forceContractCall=true - proceeding without signature",
37271
- positionDetails.vaultAddress || "unknown",
37272
- btcVaultBalance,
37273
- debt,
37274
- btcPrice2
37492
+ if (this.config.debug) {
37493
+ log.info(
37494
+ `\u{1F4F1} Sending forced liquidation without signature Telegram message...`
37275
37495
  );
37276
- await sendTelegramMessage(
37277
- this.config.telegram.chatId,
37278
- this.config.telegram.chatToken,
37279
- message,
37280
- this.config.telegram.threadId
37496
+ }
37497
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37498
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37499
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37500
+ const message = formatLiquidationFailureMessage(
37501
+ request.positionId,
37502
+ "FORCED LIQUIDATION: LIT Action did not provide signature but forceContractCall=true - proceeding without signature",
37503
+ positionDetails.vaultAddress || "unknown",
37504
+ btcVaultBalance,
37505
+ debt,
37506
+ btcPrice2
37507
+ );
37508
+ await this._relayNotification(message);
37509
+ if (this.config.debug) {
37510
+ log.info(
37511
+ `\u2705 Forced liquidation without signature Telegram message sent successfully`
37281
37512
  );
37282
- if (this.config.debug) {
37283
- log.info(
37284
- `\u2705 Forced liquidation without signature Telegram message sent successfully`
37285
- );
37286
- }
37287
37513
  }
37288
37514
  } catch (telegramError) {
37289
37515
  if (this.config.debug) {
@@ -37297,32 +37523,25 @@ Error data: ${errorData || "none"}`
37297
37523
  }
37298
37524
  } else {
37299
37525
  try {
37300
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37301
- if (this.config.debug) {
37302
- log.info(`\u{1F4F1} Sending missing signature Telegram message...`);
37303
- }
37304
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37305
- const btcPrice2 = litActionResult.btcPrice || "unknown";
37306
- const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37307
- const message = formatLiquidationFailureMessage(
37308
- request.positionId,
37309
- "LIT Action did not provide required signature for liquidation",
37310
- positionDetails.vaultAddress || "unknown",
37311
- btcVaultBalance,
37312
- debt,
37313
- btcPrice2
37314
- );
37315
- await sendTelegramMessage(
37316
- this.config.telegram.chatId,
37317
- this.config.telegram.chatToken,
37318
- message,
37319
- this.config.telegram.threadId
37526
+ if (this.config.debug) {
37527
+ log.info(`\u{1F4F1} Sending missing signature Telegram message...`);
37528
+ }
37529
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37530
+ const btcPrice2 = litActionResult.btcPrice || "unknown";
37531
+ const btcVaultBalance = litActionResult.btcAmountSats || "unknown";
37532
+ const message = formatLiquidationFailureMessage(
37533
+ request.positionId,
37534
+ "LIT Action did not provide required signature for liquidation",
37535
+ positionDetails.vaultAddress || "unknown",
37536
+ btcVaultBalance,
37537
+ debt,
37538
+ btcPrice2
37539
+ );
37540
+ await this._relayNotification(message);
37541
+ if (this.config.debug) {
37542
+ log.info(
37543
+ `\u2705 Missing signature Telegram message sent successfully`
37320
37544
  );
37321
- if (this.config.debug) {
37322
- log.info(
37323
- `\u2705 Missing signature Telegram message sent successfully`
37324
- );
37325
- }
37326
37545
  }
37327
37546
  } catch (telegramError) {
37328
37547
  if (this.config.debug) {
@@ -37561,34 +37780,27 @@ Error data: ${errorData || "none"}`
37561
37780
  });
37562
37781
  }
37563
37782
  try {
37564
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37565
- if (this.config.debug) {
37566
- log.info(`\u{1F4F1} Sending liquidation success Telegram message...`);
37567
- }
37568
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37569
- const btcPrice2 = litActionResult.btcPrice || "0";
37570
- const ratio = debt !== "0" ? (Number(positionDetails.btcVaultBalance || "0") * Number(btcPrice2) / Number(debt) * 100 / 1e8).toFixed(2) : "0.00";
37571
- const message = formatLiquidationSuccessMessage(
37572
- request.positionId,
37573
- ratio,
37574
- `${liquidationThreshold / 100}`,
37575
- // Convert to percentage
37576
- positionDetails.btcVault || "unknown",
37577
- positionDetails.btcVaultBalance || "0",
37578
- debt,
37579
- btcPrice2
37580
- );
37581
- await sendTelegramMessage(
37582
- this.config.telegram.chatId,
37583
- this.config.telegram.chatToken,
37584
- message,
37585
- this.config.telegram.threadId
37783
+ if (this.config.debug) {
37784
+ log.info(`\u{1F4F1} Sending liquidation success Telegram message...`);
37785
+ }
37786
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37787
+ const btcPrice2 = litActionResult.btcPrice || "0";
37788
+ const ratio = debt !== "0" ? (Number(positionDetails.btcVaultBalance || "0") * Number(btcPrice2) / Number(debt) * 100 / 1e8).toFixed(2) : "0.00";
37789
+ const message = formatLiquidationSuccessMessage(
37790
+ request.positionId,
37791
+ ratio,
37792
+ `${liquidationThreshold / 100}`,
37793
+ // Convert to percentage
37794
+ positionDetails.btcVault || "unknown",
37795
+ positionDetails.btcVaultBalance || "0",
37796
+ debt,
37797
+ btcPrice2
37798
+ );
37799
+ await this._relayNotification(message);
37800
+ if (this.config.debug) {
37801
+ log.info(
37802
+ `\u2705 Liquidation success Telegram message sent successfully`
37586
37803
  );
37587
- if (this.config.debug) {
37588
- log.info(
37589
- `\u2705 Liquidation success Telegram message sent successfully`
37590
- );
37591
- }
37592
37804
  }
37593
37805
  } catch (telegramError) {
37594
37806
  if (this.config.debug) {
@@ -37620,31 +37832,24 @@ Error data: ${errorData || "none"}`
37620
37832
  transaction: contractError.transaction
37621
37833
  });
37622
37834
  try {
37623
- if (this.config.telegram?.chatId && this.config.telegram?.chatToken) {
37624
- if (this.config.debug) {
37625
- log.info(`\u{1F4F1} Sending liquidation failure Telegram message...`);
37626
- }
37627
- const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37628
- const btcPrice2 = litActionResult.btcPrice || "0";
37629
- const message = formatLiquidationFailureMessage(
37630
- request.positionId,
37631
- contractError.message || "Unknown contract error",
37632
- positionDetails.btcVault || "unknown",
37633
- positionDetails.btcVaultBalance || "0",
37634
- debt,
37635
- btcPrice2
37636
- );
37637
- await sendTelegramMessage(
37638
- this.config.telegram.chatId,
37639
- this.config.telegram.chatToken,
37640
- message,
37641
- this.config.telegram.threadId
37835
+ if (this.config.debug) {
37836
+ log.info(`\u{1F4F1} Sending liquidation failure Telegram message...`);
37837
+ }
37838
+ const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
37839
+ const btcPrice2 = litActionResult.btcPrice || "0";
37840
+ const message = formatLiquidationFailureMessage(
37841
+ request.positionId,
37842
+ contractError.message || "Unknown contract error",
37843
+ positionDetails.btcVault || "unknown",
37844
+ positionDetails.btcVaultBalance || "0",
37845
+ debt,
37846
+ btcPrice2
37847
+ );
37848
+ await this._relayNotification(message);
37849
+ if (this.config.debug) {
37850
+ log.info(
37851
+ `\u2705 Liquidation failure Telegram message sent successfully`
37642
37852
  );
37643
- if (this.config.debug) {
37644
- log.info(
37645
- `\u2705 Liquidation failure Telegram message sent successfully`
37646
- );
37647
- }
37648
37853
  }
37649
37854
  } catch (telegramError) {
37650
37855
  if (this.config.debug) {
@@ -37794,26 +37999,19 @@ Error data: ${errorData || "none"}`
37794
37999
  )} (${potentialNewExpiry}), max allowed: ${formatDate(
37795
38000
  maxAllowedTimestamp
37796
38001
  )} (${maxAllowedTimestamp})`;
37797
- if (this.config.telegram) {
37798
- try {
37799
- await sendTelegramMessage(
37800
- this.config.telegram.chatId,
37801
- this.config.telegram.chatToken,
37802
- formatLoanRenewalFailureMessage(
37803
- _positionId,
37804
- `Loan could not be renewed: ${errorMessage}`
37805
- ),
37806
- this.config.telegram.threadId
38002
+ try {
38003
+ await this._relayNotification(formatLoanRenewalFailureMessage(
38004
+ _positionId,
38005
+ `Loan could not be renewed: ${errorMessage}`
38006
+ ));
38007
+ } catch (e) {
38008
+ if (this.config.debug) {
38009
+ log.warn(
38010
+ "Failed to send Telegram notification for renewal rule violation",
38011
+ {
38012
+ error: e instanceof Error ? e.message : String(e)
38013
+ }
37807
38014
  );
37808
- } catch (e) {
37809
- if (this.config.debug) {
37810
- log.warn(
37811
- "Failed to send Telegram notification for renewal rule violation",
37812
- {
37813
- error: e instanceof Error ? e.message : String(e)
37814
- }
37815
- );
37816
- }
37817
38015
  }
37818
38016
  }
37819
38017
  throw new Error(errorMessage);
@@ -37865,19 +38063,12 @@ Error data: ${errorData || "none"}`
37865
38063
  error: errorMessage
37866
38064
  });
37867
38065
  }
37868
- if (this.config.telegram) {
37869
- try {
37870
- await sendTelegramMessage(
37871
- this.config.telegram.chatId,
37872
- this.config.telegram.chatToken,
37873
- formatLoanRenewalFailureMessage(
37874
- _positionId,
37875
- `LIT Action failed: ${errorMessage}`
37876
- ),
37877
- this.config.telegram.threadId
37878
- );
37879
- } catch (e) {
37880
- }
38066
+ try {
38067
+ await this._relayNotification(formatLoanRenewalFailureMessage(
38068
+ _positionId,
38069
+ `LIT Action failed: ${errorMessage}`
38070
+ ));
38071
+ } catch (e) {
37881
38072
  }
37882
38073
  throw litError;
37883
38074
  }
@@ -37887,31 +38078,17 @@ Error data: ${errorData || "none"}`
37887
38078
  if (!litActionResult.approved) {
37888
38079
  const reason = litActionResult.reason ?? litActionResult.error ?? "Extension not approved";
37889
38080
  const errorMessage = `Extension not approved: ${reason}`;
37890
- if (this.config.telegram) {
37891
- try {
37892
- await sendTelegramMessage(
37893
- this.config.telegram.chatId,
37894
- this.config.telegram.chatToken,
37895
- formatLoanRenewalFailureMessage(_positionId, errorMessage),
37896
- this.config.telegram.threadId
37897
- );
37898
- } catch (e) {
37899
- }
38081
+ try {
38082
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, errorMessage));
38083
+ } catch (e) {
37900
38084
  }
37901
38085
  throw new Error(errorMessage);
37902
38086
  }
37903
38087
  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) {
37904
38088
  const errorMessage = "LIT Action result missing required fields: signature, btcPrice, availableBTCBalance, quantumTimestamp, proRataRenewalFee";
37905
- if (this.config.telegram) {
37906
- try {
37907
- await sendTelegramMessage(
37908
- this.config.telegram.chatId,
37909
- this.config.telegram.chatToken,
37910
- formatLoanRenewalFailureMessage(_positionId, errorMessage),
37911
- this.config.telegram.threadId
37912
- );
37913
- } catch (e) {
37914
- }
38089
+ try {
38090
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, errorMessage));
38091
+ } catch (e) {
37915
38092
  }
37916
38093
  throw new Error(errorMessage);
37917
38094
  }
@@ -37998,66 +38175,38 @@ Error data: ${errorData || "none"}`
37998
38175
  { hash: txWithProvider.hash, error: errorMessage }
37999
38176
  );
38000
38177
  }
38001
- if (this.config.telegram) {
38002
- try {
38003
- await sendTelegramMessage(
38004
- this.config.telegram.chatId,
38005
- this.config.telegram.chatToken,
38006
- formatLoanRenewalFailureMessage(
38007
- _positionId,
38008
- `Transaction confirmation failed: ${errorMessage}`
38009
- ),
38010
- this.config.telegram.threadId
38011
- );
38012
- } catch (e) {
38013
- }
38178
+ try {
38179
+ await this._relayNotification(formatLoanRenewalFailureMessage(
38180
+ _positionId,
38181
+ `Transaction confirmation failed: ${errorMessage}`
38182
+ ));
38183
+ } catch (e) {
38014
38184
  }
38015
38185
  throw waitError;
38016
38186
  }
38017
38187
  if (!receipt) {
38018
38188
  const error = "Transaction receipt is null - transaction may have failed";
38019
- if (this.config.telegram) {
38020
- try {
38021
- await sendTelegramMessage(
38022
- this.config.telegram.chatId,
38023
- this.config.telegram.chatToken,
38024
- formatLoanRenewalFailureMessage(_positionId, error),
38025
- this.config.telegram.threadId
38026
- );
38027
- } catch (e) {
38028
- }
38189
+ try {
38190
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, error));
38191
+ } catch (e) {
38029
38192
  }
38030
38193
  throw new Error(error);
38031
38194
  }
38032
38195
  if (receipt.status === 0) {
38033
38196
  const error = `Transaction reverted (tx: ${receipt.transactionHash})`;
38034
- if (this.config.telegram) {
38035
- try {
38036
- await sendTelegramMessage(
38037
- this.config.telegram.chatId,
38038
- this.config.telegram.chatToken,
38039
- formatLoanRenewalFailureMessage(_positionId, error),
38040
- this.config.telegram.threadId
38041
- );
38042
- } catch (e) {
38043
- }
38197
+ try {
38198
+ await this._relayNotification(formatLoanRenewalFailureMessage(_positionId, error));
38199
+ } catch (e) {
38044
38200
  }
38045
38201
  throw new Error(error);
38046
38202
  }
38047
- if (this.config.telegram) {
38048
- try {
38049
- await sendTelegramMessage(
38050
- this.config.telegram.chatId,
38051
- this.config.telegram.chatToken,
38052
- formatLoanRenewalMessage(_positionId, receipt.transactionHash),
38053
- this.config.telegram.threadId
38054
- );
38055
- } catch (e) {
38056
- if (this.config.debug) {
38057
- log.warn("Failed to send Telegram notification for extension", {
38058
- error: e instanceof Error ? e.message : String(e)
38059
- });
38060
- }
38203
+ try {
38204
+ await this._relayNotification(formatLoanRenewalMessage(_positionId, receipt.transactionHash));
38205
+ } catch (e) {
38206
+ if (this.config.debug) {
38207
+ log.warn("Failed to send Telegram notification for extension", {
38208
+ error: e instanceof Error ? e.message : String(e)
38209
+ });
38061
38210
  }
38062
38211
  }
38063
38212
  return receipt;
@@ -38171,16 +38320,9 @@ Error data: ${errorData || "none"}`
38171
38320
  const initCheck = this.checkInitialized();
38172
38321
  if (!initCheck.success) {
38173
38322
  const error = `SDK not initialized: ${initCheck.error.message}`;
38174
- if (this.config.telegram) {
38175
- try {
38176
- await sendTelegramMessage(
38177
- this.config.telegram.chatId,
38178
- this.config.telegram.chatToken,
38179
- formatBalanceConfirmationFailureMessage(positionId),
38180
- this.config.telegram.threadId
38181
- );
38182
- } catch (e) {
38183
- }
38323
+ try {
38324
+ await this._relayNotification(formatBalanceConfirmationFailureMessage(positionId));
38325
+ } catch (e) {
38184
38326
  }
38185
38327
  return {
38186
38328
  success: false,
@@ -38320,21 +38462,14 @@ Error data: ${errorData || "none"}`
38320
38462
  gasUsed: receipt.gasUsed.toString()
38321
38463
  });
38322
38464
  }
38323
- if (this.config.telegram) {
38324
- try {
38325
- const message = formatBalanceConfirmationMessage(positionId);
38326
- await sendTelegramMessage(
38327
- this.config.telegram.chatId,
38328
- this.config.telegram.chatToken,
38329
- message,
38330
- this.config.telegram.threadId
38331
- );
38332
- } catch (telegramError) {
38333
- if (this.config.debug) {
38334
- log.warn("\u26A0\uFE0F Failed to send Telegram notification", {
38335
- error: telegramError instanceof Error ? telegramError.message : String(telegramError)
38336
- });
38337
- }
38465
+ try {
38466
+ const message = formatBalanceConfirmationMessage(positionId);
38467
+ await this._relayNotification(message);
38468
+ } catch (telegramError) {
38469
+ if (this.config.debug) {
38470
+ log.warn("\u26A0\uFE0F Failed to send Telegram notification", {
38471
+ error: telegramError instanceof Error ? telegramError.message : String(telegramError)
38472
+ });
38338
38473
  }
38339
38474
  }
38340
38475
  return {
@@ -38357,17 +38492,10 @@ Error data: ${errorData || "none"}`
38357
38492
  positionId
38358
38493
  });
38359
38494
  }
38360
- if (this.config.telegram) {
38361
- try {
38362
- const message = formatBalanceConfirmationFailureMessage(positionId);
38363
- await sendTelegramMessage(
38364
- this.config.telegram.chatId,
38365
- this.config.telegram.chatToken,
38366
- message,
38367
- this.config.telegram.threadId
38368
- );
38369
- } catch (telegramError) {
38370
- }
38495
+ try {
38496
+ const message = formatBalanceConfirmationFailureMessage(positionId);
38497
+ await this._relayNotification(message);
38498
+ } catch (telegramError) {
38371
38499
  }
38372
38500
  return {
38373
38501
  success: false,
@@ -38916,17 +39044,12 @@ Error data: ${errorData || "none"}`
38916
39044
  }
38917
39045
  if (receipt.status === 0) {
38918
39046
  try {
38919
- if (this.config.telegram && tx.hash) {
39047
+ if (tx.hash) {
38920
39048
  const message = formatPartialPaymentFailureMessage(
38921
39049
  request.paymentAmount,
38922
39050
  request.positionId
38923
39051
  );
38924
- await sendTelegramMessage(
38925
- this.config.telegram.chatId,
38926
- this.config.telegram.chatToken,
38927
- message,
38928
- this.config.telegram.threadId
38929
- );
39052
+ await this._relayNotification(message);
38930
39053
  }
38931
39054
  } catch (telegramError) {
38932
39055
  if (this.config.debug) {
@@ -38948,18 +39071,13 @@ Error data: ${errorData || "none"}`
38948
39071
  log.info(`\u2705 Transaction confirmed in block ${receipt.blockNumber}`);
38949
39072
  }
38950
39073
  try {
38951
- if (this.config.telegram && tx.hash) {
39074
+ if (tx.hash) {
38952
39075
  const message = formatPartialPaymentMessage(
38953
39076
  request.paymentAmount,
38954
39077
  request.positionId,
38955
39078
  tx.hash
38956
39079
  );
38957
- await sendTelegramMessage(
38958
- this.config.telegram.chatId,
38959
- this.config.telegram.chatToken,
38960
- message,
38961
- this.config.telegram.threadId
38962
- );
39080
+ await this._relayNotification(message);
38963
39081
  }
38964
39082
  } catch (telegramError) {
38965
39083
  if (this.config.debug) {
@@ -39013,19 +39131,12 @@ Error data: ${errorData || "none"}`
39013
39131
  });
39014
39132
  }
39015
39133
  try {
39016
- if (this.config.telegram) {
39017
- const message = formatPartialPaymentFailureMessage(
39018
- request.paymentAmount,
39019
- request.positionId,
39020
- transactionHash
39021
- );
39022
- await sendTelegramMessage(
39023
- this.config.telegram.chatId,
39024
- this.config.telegram.chatToken,
39025
- message,
39026
- this.config.telegram.threadId
39027
- );
39028
- }
39134
+ const message = formatPartialPaymentFailureMessage(
39135
+ request.paymentAmount,
39136
+ request.positionId,
39137
+ transactionHash
39138
+ );
39139
+ await this._relayNotification(message);
39029
39140
  } catch (telegramError) {
39030
39141
  if (this.config.debug) {
39031
39142
  log.warn("\u26A0\uFE0F Failed to send Telegram failure notification", {
@@ -39341,22 +39452,15 @@ Error data: ${errorData || "none"}`
39341
39452
  });
39342
39453
  }
39343
39454
  try {
39344
- if (this.config.telegram) {
39345
- const position2 = await this.getPosition(positionId);
39346
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39347
- const message = formatBTCWithdrawalFailureMessage(
39348
- btcAmount,
39349
- position2?.vaultAddress || "unknown",
39350
- withdrawalAddress,
39351
- positionId
39352
- );
39353
- await sendTelegramMessage(
39354
- this.config.telegram.chatId,
39355
- this.config.telegram.chatToken,
39356
- message,
39357
- this.config.telegram.threadId
39358
- );
39359
- }
39455
+ const position2 = await this.getPosition(positionId);
39456
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39457
+ const message = formatBTCWithdrawalFailureMessage(
39458
+ btcAmount,
39459
+ position2?.vaultAddress || "unknown",
39460
+ withdrawalAddress,
39461
+ positionId
39462
+ );
39463
+ await this._relayNotification(message);
39360
39464
  } catch (telegramError) {
39361
39465
  console.error(
39362
39466
  "Telegram notification failed:",
@@ -39388,22 +39492,15 @@ Error data: ${errorData || "none"}`
39388
39492
  });
39389
39493
  }
39390
39494
  try {
39391
- if (this.config.telegram) {
39392
- const position = await this.getPosition(positionId);
39393
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39394
- const message = formatBTCWithdrawalFailureMessage(
39395
- btcAmount,
39396
- position?.vaultAddress || "unknown",
39397
- withdrawalAddress,
39398
- positionId
39399
- );
39400
- await sendTelegramMessage(
39401
- this.config.telegram.chatId,
39402
- this.config.telegram.chatToken,
39403
- message,
39404
- this.config.telegram.threadId
39405
- );
39406
- }
39495
+ const position = await this.getPosition(positionId);
39496
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39497
+ const message = formatBTCWithdrawalFailureMessage(
39498
+ btcAmount,
39499
+ position?.vaultAddress || "unknown",
39500
+ withdrawalAddress,
39501
+ positionId
39502
+ );
39503
+ await this._relayNotification(message);
39407
39504
  } catch (telegramError) {
39408
39505
  console.error(
39409
39506
  "Telegram notification failed:",
@@ -39557,22 +39654,15 @@ Error data: ${errorData || "none"}`
39557
39654
  });
39558
39655
  }
39559
39656
  try {
39560
- if (this.config.telegram) {
39561
- const position = await this.getPosition(positionId);
39562
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39563
- const message = formatBTCWithdrawalFailureMessage(
39564
- btcAmount,
39565
- position?.vaultAddress || "unknown",
39566
- withdrawalAddress,
39567
- positionId
39568
- );
39569
- await sendTelegramMessage(
39570
- this.config.telegram.chatId,
39571
- this.config.telegram.chatToken,
39572
- message,
39573
- this.config.telegram.threadId
39574
- );
39575
- }
39657
+ const position = await this.getPosition(positionId);
39658
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39659
+ const message = formatBTCWithdrawalFailureMessage(
39660
+ btcAmount,
39661
+ position?.vaultAddress || "unknown",
39662
+ withdrawalAddress,
39663
+ positionId
39664
+ );
39665
+ await this._relayNotification(message);
39576
39666
  } catch (telegramError) {
39577
39667
  console.error(
39578
39668
  "Telegram notification failed:",
@@ -39612,22 +39702,15 @@ Error data: ${errorData || "none"}`
39612
39702
  });
39613
39703
  }
39614
39704
  try {
39615
- if (this.config.telegram) {
39616
- const position = await this.getPosition(positionId);
39617
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39618
- const message = formatBTCWithdrawalSuccessMessage(
39619
- btcAmount,
39620
- position?.vaultAddress || "unknown",
39621
- validationResponse.destinationAddress,
39622
- positionId
39623
- );
39624
- await sendTelegramMessage(
39625
- this.config.telegram.chatId,
39626
- this.config.telegram.chatToken,
39627
- message,
39628
- this.config.telegram.threadId
39629
- );
39630
- }
39705
+ const position = await this.getPosition(positionId);
39706
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39707
+ const message = formatBTCWithdrawalSuccessMessage(
39708
+ btcAmount,
39709
+ position?.vaultAddress || "unknown",
39710
+ validationResponse.destinationAddress,
39711
+ positionId
39712
+ );
39713
+ await this._relayNotification(message);
39631
39714
  } catch (telegramError) {
39632
39715
  console.error(
39633
39716
  "Telegram notification failed:",
@@ -39653,22 +39736,15 @@ Error data: ${errorData || "none"}`
39653
39736
  });
39654
39737
  }
39655
39738
  try {
39656
- if (this.config.telegram) {
39657
- const position = await this.getPosition(positionId);
39658
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39659
- const message = formatBTCWithdrawalFailureMessage(
39660
- btcAmount,
39661
- position?.vaultAddress || "unknown",
39662
- withdrawalAddress,
39663
- positionId
39664
- );
39665
- await sendTelegramMessage(
39666
- this.config.telegram.chatId,
39667
- this.config.telegram.chatToken,
39668
- message,
39669
- this.config.telegram.threadId
39670
- );
39671
- }
39739
+ const position = await this.getPosition(positionId);
39740
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
39741
+ const message = formatBTCWithdrawalFailureMessage(
39742
+ btcAmount,
39743
+ position?.vaultAddress || "unknown",
39744
+ withdrawalAddress,
39745
+ positionId
39746
+ );
39747
+ await this._relayNotification(message);
39672
39748
  } catch (telegramError) {
39673
39749
  console.error(
39674
39750
  "Telegram notification failed:",
@@ -39732,7 +39808,34 @@ Error data: ${errorData || "none"}`
39732
39808
  const bitcoinNetwork = this.getBitcoinNetwork();
39733
39809
  const mode = chainId === 1337 || chainId === 31337 || bitcoinNetwork === "regtest" ? "dev" : "prod";
39734
39810
  const bitcoin = await import("bitcoinjs-lib");
39735
- const { witnessStackToScriptWitness } = await import("bitcoinjs-lib/src/psbt/psbtutils");
39811
+ const encodeBitcoinVarInt = (value) => {
39812
+ if (value < 253) {
39813
+ return Buffer.from([value]);
39814
+ }
39815
+ if (value <= 65535) {
39816
+ const buf2 = Buffer.allocUnsafe(3);
39817
+ buf2[0] = 253;
39818
+ buf2.writeUInt16LE(value, 1);
39819
+ return buf2;
39820
+ }
39821
+ if (value <= 4294967295) {
39822
+ const buf2 = Buffer.allocUnsafe(5);
39823
+ buf2[0] = 254;
39824
+ buf2.writeUInt32LE(value, 1);
39825
+ return buf2;
39826
+ }
39827
+ const buf = Buffer.allocUnsafe(9);
39828
+ buf[0] = 255;
39829
+ buf.writeBigUInt64LE(BigInt(value), 1);
39830
+ return buf;
39831
+ };
39832
+ const witnessStackToScriptWitness = (witness) => {
39833
+ const serializedChunks = [encodeBitcoinVarInt(witness.length)];
39834
+ for (const item of witness) {
39835
+ serializedChunks.push(encodeBitcoinVarInt(item.length), item);
39836
+ }
39837
+ return Buffer.concat(serializedChunks);
39838
+ };
39736
39839
  const networks2 = bitcoinNetwork === "mainnet" ? bitcoin.networks.bitcoin : bitcoinNetwork === "regtest" ? bitcoin.networks.regtest : bitcoin.networks.testnet;
39737
39840
  if (this.config.debug) {
39738
39841
  log.info("\u{1F4CB} Network configuration", {