@gvnrdao/dh-lit-ops 0.0.201 → 0.0.213

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.
@@ -54,6 +54,7 @@ const pkp_minter_module_1 = require("./pkp-minter.module");
54
54
  const pkp_signer_module_1 = require("./pkp-signer.module");
55
55
  const session_signature_manager_module_1 = require("./session-signature-manager.module");
56
56
  const capacity_master_module_1 = require("./capacity-master.module");
57
+ const pkp_token_id_1 = require("../utils/pkp-token-id");
57
58
  class LitOps {
58
59
  constructor(config) {
59
60
  // CRITICAL VALIDATION: Reject datil-test immediately with terrifying error
@@ -1609,14 +1610,19 @@ class LitOps {
1609
1610
  // Add custom RPC URL for local development (ngrok tunnels)
1610
1611
  if (request.customRpcUrl) {
1611
1612
  litActionParams.customRpcUrl = request.customRpcUrl;
1613
+ // Also set rpcUrl as fallback (some LIT actions expect this)
1614
+ litActionParams.rpcUrl = request.customRpcUrl;
1612
1615
  if (this.config.debug) {
1613
1616
  console.log(" Custom RPC URL:", request.customRpcUrl);
1617
+ console.log(" Setting both customRpcUrl and rpcUrl parameters");
1614
1618
  }
1615
1619
  }
1616
1620
  // Execute LIT Action (single attempt - retry logic is in SDK layer)
1617
1621
  const result = await this.actionExecutor.executeAction({
1618
1622
  cid: litActionInfo.cid,
1619
1623
  pkpPublicKey: litActionInfo.pkp.publicKey,
1624
+ pkpTokenId: (0, pkp_token_id_1.normalizePkpTokenIdForLitResource)(String(litActionInfo.pkp.tokenId)) ?? String(litActionInfo.pkp.tokenId),
1625
+ pkpEthAddress: litActionInfo.pkp.ethAddress,
1620
1626
  params: litActionParams,
1621
1627
  signer: this.config.signer,
1622
1628
  priceProviders: request.priceProviders, // Pass price provider API keys (standalone mode)
@@ -1894,6 +1900,8 @@ class LitOps {
1894
1900
  const result = await this.actionExecutor.executeAction({
1895
1901
  cid: litActionInfo.cid,
1896
1902
  pkpPublicKey: litActionInfo.pkp.publicKey,
1903
+ pkpTokenId: (0, pkp_token_id_1.normalizePkpTokenIdForLitResource)(String(litActionInfo.pkp.tokenId)) ?? String(litActionInfo.pkp.tokenId),
1904
+ pkpEthAddress: litActionInfo.pkp.ethAddress,
1897
1905
  params: litActionParams,
1898
1906
  signer: this.config.signer,
1899
1907
  priceProviders: request.priceProviders, // Pass price provider API keys (standalone mode)
@@ -1976,6 +1984,240 @@ class LitOps {
1976
1984
  }
1977
1985
  return returnValue;
1978
1986
  }
1987
+ /**
1988
+ * Request extend position authorization (dual-mode)
1989
+ *
1990
+ * In SERVICE mode: Delegates to lit-ops-server HTTP endpoint
1991
+ * In STANDALONE mode: Executes extend-position-validator LIT Action locally
1992
+ *
1993
+ * @param request - Authorization request with authMessage and userSignature
1994
+ * @returns Extend authorization response from LIT Action
1995
+ */
1996
+ async requestExtendAuthorization(request) {
1997
+ if (this.config.debug) {
1998
+ console.log("🔍 [requestExtendAuthorization] Mode check:", this.config.mode);
1999
+ }
2000
+ if (this.config.mode === "service") {
2001
+ if (this.config.debug) {
2002
+ console.log("🌐 [requestExtendAuthorization] Using SERVICE mode - delegating to server");
2003
+ }
2004
+ return this.requestExtendAuthorizationViaService(request);
2005
+ }
2006
+ if (this.config.debug) {
2007
+ console.log("🔧 [requestExtendAuthorization] Using STANDALONE mode - executing locally");
2008
+ }
2009
+ return this.requestExtendAuthorizationStandalone(request);
2010
+ }
2011
+ /**
2012
+ * Request extend authorization via lit-ops-server (SERVICE mode)
2013
+ */
2014
+ async requestExtendAuthorizationViaService(request) {
2015
+ if (!this.config.serviceEndpoint) {
2016
+ throw new Error("Service endpoint not configured for service mode");
2017
+ }
2018
+ const url = `${this.config.serviceEndpoint}/api/lit/extend/authorize`;
2019
+ if (this.config.debug) {
2020
+ console.log("🌐 Requesting extend authorization via service:", url);
2021
+ console.log(" Position ID:", request.authMessage.positionId);
2022
+ console.log(" New Term:", request.authMessage.newTerm);
2023
+ }
2024
+ const requestBody = {
2025
+ authMessage: request.authMessage,
2026
+ userSignature: request.userSignature,
2027
+ customRpcUrl: request.customRpcUrl,
2028
+ customBitcoinRpcUrl: request.customBitcoinRpcUrl,
2029
+ priceProviders: request.priceProviders,
2030
+ };
2031
+ try {
2032
+ const controller = new AbortController();
2033
+ const timeoutId = setTimeout(() => controller.abort(), 180000); // 3 minutes
2034
+ const response = await fetch(url, {
2035
+ method: "POST",
2036
+ headers: {
2037
+ "Content-Type": "application/json",
2038
+ },
2039
+ body: JSON.stringify(requestBody),
2040
+ signal: controller.signal,
2041
+ });
2042
+ clearTimeout(timeoutId);
2043
+ if (!response.ok) {
2044
+ const errorText = await response.text();
2045
+ throw new Error(`Service request failed: ${response.status} ${response.statusText} - ${errorText}`);
2046
+ }
2047
+ const serviceResponse = (await response.json());
2048
+ const result = serviceResponse.data || serviceResponse;
2049
+ return {
2050
+ approved: result.approved || false,
2051
+ signature: result.signature,
2052
+ positionId: result.positionId,
2053
+ selectedTerm: result.selectedTerm,
2054
+ btcPrice: result.btcPrice,
2055
+ availableBTCBalance: result.availableBTCBalance,
2056
+ quantumTimestamp: result.quantumTimestamp,
2057
+ extensionFee: result.extensionFee,
2058
+ newTotalDebt: result.newTotalDebt,
2059
+ newCollateralRatioBps: result.newCollateralRatioBps,
2060
+ timestamp: result.timestamp,
2061
+ validatorPkp: result.validatorPkp,
2062
+ reason: result.reason,
2063
+ failedStep: result.failedStep,
2064
+ error: result.error,
2065
+ };
2066
+ }
2067
+ catch (error) {
2068
+ if (this.config.debug) {
2069
+ console.error("❌ Extend authorization service request failed:", error);
2070
+ }
2071
+ throw error;
2072
+ }
2073
+ }
2074
+ /**
2075
+ * Request extend authorization locally (STANDALONE mode)
2076
+ */
2077
+ async requestExtendAuthorizationStandalone(request) {
2078
+ const litActions = this.config.network === "datil"
2079
+ ? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
2080
+ : (() => {
2081
+ throw new Error("Unsupported LIT network");
2082
+ })();
2083
+ const litActionInfo = litActions.extendPositionValidator;
2084
+ if (this.config.debug) {
2085
+ console.log("🔍 [requestExtendAuthorizationStandalone] Using action:", litActionInfo?.name || "NONE");
2086
+ }
2087
+ if (!litActionInfo || !litActionInfo.cid || !litActionInfo.pkp) {
2088
+ throw new Error("Extend position validator LIT Action not found in registry");
2089
+ }
2090
+ // Debug logging for PKP information
2091
+ console.log("🔥🔥🔥 STANDALONE EXTEND AUTH DEBUG - SERVER IS USING UPDATED CODE 🔥🔥🔥");
2092
+ console.log("🔑 STANDALONE EXTEND AUTH DEBUG - PKP token ID details:");
2093
+ console.log(" Raw from registry:", String(litActionInfo.pkp.tokenId));
2094
+ console.log(" Registry CID:", litActionInfo.cid);
2095
+ console.log(" Registry PKP:", JSON.stringify(litActionInfo.pkp, null, 2));
2096
+ const litClient = await this.clientManager.getClient({
2097
+ litNetwork: this.config.network,
2098
+ debug: this.config.debug,
2099
+ });
2100
+ let chain;
2101
+ let bitcoinProviderUrl;
2102
+ if (request.customBitcoinRpcUrl) {
2103
+ bitcoinProviderUrl = request.customBitcoinRpcUrl;
2104
+ switch (request.authMessage.chainId) {
2105
+ case 1:
2106
+ chain = "ethereum";
2107
+ break;
2108
+ case 11155111:
2109
+ chain = "sepolia";
2110
+ break;
2111
+ case 1337:
2112
+ case 31337:
2113
+ chain = "hardhat";
2114
+ break;
2115
+ default:
2116
+ throw new Error(`Unsupported chainId: ${request.authMessage.chainId}`);
2117
+ }
2118
+ }
2119
+ else {
2120
+ switch (request.authMessage.chainId) {
2121
+ case 1:
2122
+ chain = "ethereum";
2123
+ bitcoinProviderUrl =
2124
+ process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
2125
+ break;
2126
+ case 11155111:
2127
+ chain = "sepolia";
2128
+ bitcoinProviderUrl =
2129
+ process.env.BITCOIN_PROVIDER_URL ||
2130
+ "https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api/esplora";
2131
+ break;
2132
+ case 1337:
2133
+ case 31337:
2134
+ chain = "hardhat";
2135
+ bitcoinProviderUrl =
2136
+ process.env.BITCOIN_PROVIDER_URL || "http://127.0.0.1:18443";
2137
+ break;
2138
+ default:
2139
+ throw new Error(`Unsupported chainId: ${request.authMessage.chainId}`);
2140
+ }
2141
+ }
2142
+ if (request.customBitcoinRpcUrl) {
2143
+ bitcoinProviderUrl = request.customBitcoinRpcUrl;
2144
+ }
2145
+ const auth = {
2146
+ positionId: request.authMessage.positionId,
2147
+ timestamp: request.authMessage.timestamp,
2148
+ chainId: request.authMessage.chainId,
2149
+ newTerm: request.authMessage.newTerm,
2150
+ action: request.authMessage.action,
2151
+ signature: request.userSignature,
2152
+ mode: request.authMessage.mode,
2153
+ };
2154
+ const litActionParams = {
2155
+ chain,
2156
+ bitcoinProviderUrl,
2157
+ auth,
2158
+ selectedTerm: request.authMessage.newTerm,
2159
+ ...(request.authMessage.contractAddresses && {
2160
+ contractAddresses: request.authMessage.contractAddresses,
2161
+ }),
2162
+ };
2163
+ if (request.customRpcUrl) {
2164
+ litActionParams.customRpcUrl = request.customRpcUrl;
2165
+ }
2166
+ const normalizedPkpTokenId = (0, pkp_token_id_1.normalizePkpTokenIdForLitResource)(String(litActionInfo.pkp.tokenId));
2167
+ const finalPkpTokenId = normalizedPkpTokenId ?? String(litActionInfo.pkp.tokenId);
2168
+ console.log("🔥🔥🔥 EXTEND AUTH DEBUG - SERVER IS USING UPDATED CODE 🔥🔥🔥");
2169
+ console.log("🔑 EXTEND AUTH DEBUG - PKP token ID details:");
2170
+ console.log(" Raw from registry:", String(litActionInfo.pkp.tokenId));
2171
+ console.log(" Normalized:", normalizedPkpTokenId);
2172
+ console.log(" Final (passed to executor):", finalPkpTokenId);
2173
+ console.log(" Debug enabled:", this.config.debug);
2174
+ console.log(" Registry CID:", litActionInfo.cid);
2175
+ console.log(" Registry PKP:", JSON.stringify(litActionInfo.pkp, null, 2));
2176
+ const result = await this.actionExecutor.executeAction({
2177
+ cid: litActionInfo.cid,
2178
+ pkpPublicKey: litActionInfo.pkp.publicKey,
2179
+ pkpTokenId: finalPkpTokenId,
2180
+ pkpEthAddress: litActionInfo.pkp.ethAddress,
2181
+ params: litActionParams,
2182
+ signer: this.config.signer,
2183
+ priceProviders: request.priceProviders,
2184
+ }, litClient);
2185
+ let responseData = result.response;
2186
+ if (typeof result.response === "string") {
2187
+ try {
2188
+ responseData = JSON.parse(result.response);
2189
+ }
2190
+ catch (e) {
2191
+ if (this.config.debug) {
2192
+ console.error("❌ Failed to parse extend response string:", e);
2193
+ }
2194
+ }
2195
+ }
2196
+ const data = responseData;
2197
+ const signatureRaw = result.signatures;
2198
+ const signatureStr = (signatureRaw?.extendPositionAuth?.signature != null
2199
+ ? typeof signatureRaw.extendPositionAuth.signature === "string"
2200
+ ? signatureRaw.extendPositionAuth.signature
2201
+ : JSON.stringify(signatureRaw.extendPositionAuth.signature)
2202
+ : data?.signature);
2203
+ return {
2204
+ approved: data?.approved ?? false,
2205
+ signature: signatureStr,
2206
+ positionId: data?.positionId,
2207
+ selectedTerm: data?.selectedTerm,
2208
+ btcPrice: data?.btcPrice,
2209
+ availableBTCBalance: data?.availableBTCBalance,
2210
+ quantumTimestamp: data?.quantumTimestamp,
2211
+ extensionFee: data?.extensionFee,
2212
+ newTotalDebt: data?.newTotalDebt,
2213
+ newCollateralRatioBps: data?.newCollateralRatioBps,
2214
+ timestamp: data?.timestamp,
2215
+ validatorPkp: data?.validatorPkp,
2216
+ reason: data?.reason,
2217
+ failedStep: data?.failedStep,
2218
+ error: result.error,
2219
+ };
2220
+ }
1979
2221
  /**
1980
2222
  * Request BTC withdrawal authorization (dual-mode)
1981
2223
  *
@@ -1983,12 +2225,26 @@ class LitOps {
1983
2225
  * @returns Withdrawal authorization response from LIT Action
1984
2226
  */
1985
2227
  async requestWithdrawalAuthorization(request) {
1986
- // In SERVICE mode, delegate to lit-ops-server
2228
+ console.log("🔧 LitOps.requestWithdrawalAuthorization called");
2229
+ console.log(" Config mode:", this.config.mode);
2230
+ console.log(" Config serviceEndpoint:", this.config.serviceEndpoint);
2231
+ console.log(" Position ID:", request.authMessage.positionId);
2232
+ // In SERVICE mode, try server first, fallback to standalone
1987
2233
  if (this.config.mode === "service") {
1988
- if (this.config.debug) {
1989
- console.log("🌐 [requestWithdrawalAuthorization] Using SERVICE mode - delegating to server");
2234
+ console.log("🌐 [requestWithdrawalAuthorization] Using SERVICE mode - trying server first");
2235
+ console.log("🌐 Service endpoint:", this.config.serviceEndpoint);
2236
+ try {
2237
+ console.log("🔗 MAKING HTTP CALL TO:", `${this.config.serviceEndpoint}/api/lit/withdraw-btc/authorize`);
2238
+ return await this.requestWithdrawalAuthorizationViaService(request);
2239
+ }
2240
+ catch (serviceError) {
2241
+ console.log("⚠️ Service mode failed, falling back to standalone mode");
2242
+ console.log("⚠️ Service error:", serviceError.message);
2243
+ if (this.config.debug) {
2244
+ console.log("🔧 [requestWithdrawalAuthorization] FALLBACK: Using STANDALONE mode - executing locally");
2245
+ }
2246
+ return this.requestWithdrawalAuthorizationStandalone(request);
1990
2247
  }
1991
- return this.requestWithdrawalAuthorizationViaService(request);
1992
2248
  }
1993
2249
  // STANDALONE mode: Execute LIT action locally
1994
2250
  if (this.config.debug) {
@@ -2024,11 +2280,14 @@ class LitOps {
2024
2280
  bitcoinProviderUrl: request.bitcoinProviderUrl, // Pass to service
2025
2281
  customRpcUrl: request.customRpcUrl,
2026
2282
  customBitcoinRpcUrl: request.customBitcoinRpcUrl,
2283
+ ...(request.authMessage.contractAddresses && { contractAddresses: request.authMessage.contractAddresses }),
2284
+ ...(request.priceProviders && { priceProviders: request.priceProviders }),
2027
2285
  };
2028
2286
  if (this.config.debug) {
2029
2287
  console.log("🔍 [WITHDRAWAL REQUEST] Complete parameters being sent to lit-ops-server:");
2030
2288
  console.log(JSON.stringify(requestBody, null, 2));
2031
2289
  }
2290
+ console.log("🔗 MAKING HTTP CALL TO:", url);
2032
2291
  const response = await fetch(url, {
2033
2292
  method: "POST",
2034
2293
  headers: {
@@ -2040,33 +2299,153 @@ class LitOps {
2040
2299
  const errorText = await response.text();
2041
2300
  throw new Error(`Service error (${response.status}): ${errorText}`);
2042
2301
  }
2043
- const envelope = await response.json();
2302
+ let envelope;
2303
+ try {
2304
+ envelope = await response.json();
2305
+ }
2306
+ catch (parseError) {
2307
+ const errorMsg = parseError instanceof Error ? parseError.message : String(parseError);
2308
+ if (errorMsg.includes("BigNumber") || errorMsg.includes("invalid")) {
2309
+ console.error("❌ Error parsing JSON response (BigNumber issue):", errorMsg);
2310
+ return {
2311
+ approved: false,
2312
+ error: `LIT Action validation error: ${errorMsg}`,
2313
+ reason: "Failed to parse service response",
2314
+ };
2315
+ }
2316
+ throw parseError;
2317
+ }
2044
2318
  if (this.config.debug) {
2045
- console.log("📥 Service response:", envelope);
2319
+ // Safely log response - avoid accessing properties that might trigger BigNumber errors
2320
+ try {
2321
+ console.log("📥 Service response:", JSON.stringify(envelope, null, 2));
2322
+ }
2323
+ catch (logError) {
2324
+ console.log("📥 Service response: [unable to stringify - may contain BigNumber objects]");
2325
+ }
2046
2326
  }
2047
2327
  // Extract data from envelope (server wraps in { success, data } structure)
2048
- const result = envelope.data || envelope;
2049
- // Return the result from service
2050
- return {
2051
- approved: result.approved ?? false,
2052
- signature: result.signature,
2053
- actionHash: result.actionHash,
2054
- authorizedSpendsHash: result.authorizedSpendsHash,
2055
- ucdDebtHash: result.ucdDebtHash,
2056
- contractBundleHash: result.contractBundleHash,
2057
- totalDeduction: result.totalDeduction,
2058
- remainingCollateral: result.remainingCollateral,
2059
- newCollateralRatioBps: result.newCollateralRatioBps,
2060
- destinationAddress: result.destinationAddress,
2061
- btcPrice: result.btcPrice,
2062
- timestamp: result.timestamp,
2063
- utxoTxid: result.utxoTxid,
2064
- utxoVout: result.utxoVout,
2065
- utxoSatoshis: result.utxoSatoshis,
2066
- reason: result.reason,
2067
- failedStep: result.failedStep,
2068
- error: result.error,
2328
+ // Use safe property access to avoid BigNumber errors
2329
+ let result;
2330
+ try {
2331
+ result = envelope.data || envelope;
2332
+ }
2333
+ catch (accessError) {
2334
+ const errorMsg = accessError instanceof Error ? accessError.message : String(accessError);
2335
+ if (errorMsg.includes("BigNumber") || errorMsg.includes("invalid")) {
2336
+ console.error("❌ Error accessing envelope.data (BigNumber issue):", errorMsg);
2337
+ return {
2338
+ approved: false,
2339
+ error: `LIT Action validation error: ${errorMsg}`,
2340
+ reason: "Failed to access response data",
2341
+ };
2342
+ }
2343
+ throw accessError;
2344
+ }
2345
+ // Normalize empty objects to prevent BigNumber errors in SDK
2346
+ // Helper function to safely normalize values - wraps property access in try-catch
2347
+ const safeGetValue = (obj, key) => {
2348
+ try {
2349
+ return obj?.[key];
2350
+ }
2351
+ catch (e) {
2352
+ const errorMsg = e instanceof Error ? e.message : String(e);
2353
+ if (errorMsg.includes("BigNumber") || errorMsg.includes("invalid")) {
2354
+ if (this.config.debug) {
2355
+ console.warn(`⚠️ Error accessing ${key} (BigNumber issue), using undefined`);
2356
+ }
2357
+ return undefined;
2358
+ }
2359
+ throw e;
2360
+ }
2069
2361
  };
2362
+ const normalizeValue = (value, defaultValue) => {
2363
+ if (value === null || value === undefined) {
2364
+ return defaultValue;
2365
+ }
2366
+ // Check for empty object FIRST - this is the most common issue
2367
+ if (typeof value === "object" && value !== null && Object.keys(value).length === 0) {
2368
+ return defaultValue;
2369
+ }
2370
+ if (typeof value === "string") {
2371
+ return value;
2372
+ }
2373
+ if (typeof value === "number") {
2374
+ return value.toString();
2375
+ }
2376
+ if (typeof value === "bigint") {
2377
+ return value.toString();
2378
+ }
2379
+ // Try to extract value from object (ethers BigNumber objects)
2380
+ if (typeof value === "object" && value !== null) {
2381
+ if (value._hex && typeof value._hex === "string" && value._hex.length > 0) {
2382
+ try {
2383
+ return ethers_1.ethers.BigNumber.from(value._hex).toString();
2384
+ }
2385
+ catch {
2386
+ return defaultValue;
2387
+ }
2388
+ }
2389
+ if (value.hex && typeof value.hex === "string" && value.hex.length > 0) {
2390
+ try {
2391
+ return ethers_1.ethers.BigNumber.from(value.hex).toString();
2392
+ }
2393
+ catch {
2394
+ return defaultValue;
2395
+ }
2396
+ }
2397
+ if (value.value !== undefined) {
2398
+ return normalizeValue(value.value, defaultValue);
2399
+ }
2400
+ if (value.toString && typeof value.toString === "function") {
2401
+ try {
2402
+ const str = value.toString();
2403
+ if (typeof str === "string" && str !== "[object Object]") {
2404
+ return str;
2405
+ }
2406
+ }
2407
+ catch { }
2408
+ }
2409
+ return defaultValue; // Unhandled object
2410
+ }
2411
+ return String(value);
2412
+ };
2413
+ // DEBUG: Log raw result before processing
2414
+ console.log("🔍 LITOPS RAW RESULT ANALYSIS:");
2415
+ console.log(" result type:", typeof result);
2416
+ console.log(" result is object:", typeof result === 'object');
2417
+ console.log(" result keys:", result && typeof result === 'object' ? Object.keys(result) : "N/A");
2418
+ console.log(" raw btcPrice:", safeGetValue(result, "btcPrice"), "type:", typeof safeGetValue(result, "btcPrice"));
2419
+ console.log(" raw btcPrice is empty object:", (() => {
2420
+ const btcPrice = safeGetValue(result, "btcPrice");
2421
+ return btcPrice && typeof btcPrice === 'object' && Object.keys(btcPrice).length === 0;
2422
+ })());
2423
+ // Return the result from service with normalized numeric values
2424
+ // Use safeGetValue to avoid BigNumber errors when accessing properties
2425
+ const processedResult = {
2426
+ approved: safeGetValue(result, "approved") ?? false,
2427
+ signature: safeGetValue(result, "signature"),
2428
+ actionHash: safeGetValue(result, "actionHash"),
2429
+ authorizedSpendsHash: safeGetValue(result, "authorizedSpendsHash"),
2430
+ ucdDebtHash: safeGetValue(result, "ucdDebtHash"),
2431
+ contractBundleHash: safeGetValue(result, "contractBundleHash"),
2432
+ totalDeduction: normalizeValue(safeGetValue(result, "totalDeduction"), "0"),
2433
+ remainingCollateral: normalizeValue(safeGetValue(result, "remainingCollateral"), "0"),
2434
+ newCollateralRatioBps: safeGetValue(result, "newCollateralRatioBps"),
2435
+ destinationAddress: safeGetValue(result, "destinationAddress"),
2436
+ btcPrice: normalizeValue(safeGetValue(result, "btcPrice"), "5000000000000"), // Default: $50,000 with 8 decimals
2437
+ timestamp: normalizeValue(safeGetValue(result, "timestamp"), Math.floor(Date.now() / 1000).toString()),
2438
+ utxoTxid: safeGetValue(result, "utxoTxid"),
2439
+ utxoVout: safeGetValue(result, "utxoVout"),
2440
+ utxoSatoshis: safeGetValue(result, "utxoSatoshis") ? normalizeValue(safeGetValue(result, "utxoSatoshis"), "0") : undefined,
2441
+ reason: safeGetValue(result, "reason"),
2442
+ failedStep: safeGetValue(result, "failedStep"),
2443
+ error: safeGetValue(result, "error"),
2444
+ };
2445
+ console.log("🔍 LITOPS PROCESSED RESULT:");
2446
+ console.log(" processedResult.btcPrice:", processedResult.btcPrice, "type:", typeof processedResult.btcPrice);
2447
+ console.log(" processedResult.btcPrice is empty object:", processedResult.btcPrice && typeof processedResult.btcPrice === 'object' && Object.keys(processedResult.btcPrice).length === 0);
2448
+ return processedResult;
2070
2449
  }
2071
2450
  catch (error) {
2072
2451
  console.error("❌ Service request failed:", error);
@@ -2219,6 +2598,69 @@ class LitOps {
2219
2598
  }
2220
2599
  }
2221
2600
  }
2601
+ // Normalize empty objects to prevent BigNumber errors in SDK
2602
+ // Helper function to safely normalize values
2603
+ const normalizeValue = (value, defaultValue) => {
2604
+ if (value === null || value === undefined) {
2605
+ return defaultValue;
2606
+ }
2607
+ // Check for empty object FIRST - this is the most common issue
2608
+ if (typeof value === "object" && value !== null && Object.keys(value).length === 0) {
2609
+ return defaultValue;
2610
+ }
2611
+ if (typeof value === "string") {
2612
+ return value;
2613
+ }
2614
+ if (typeof value === "number") {
2615
+ return value.toString();
2616
+ }
2617
+ if (typeof value === "bigint") {
2618
+ return value.toString();
2619
+ }
2620
+ // Try to extract value from object (ethers BigNumber objects)
2621
+ if (typeof value === "object" && value !== null) {
2622
+ if (value._hex && typeof value._hex === "string" && value._hex.length > 0) {
2623
+ try {
2624
+ return ethers_1.ethers.BigNumber.from(value._hex).toString();
2625
+ }
2626
+ catch {
2627
+ return defaultValue;
2628
+ }
2629
+ }
2630
+ if (value.hex && typeof value.hex === "string" && value.hex.length > 0) {
2631
+ try {
2632
+ return ethers_1.ethers.BigNumber.from(value.hex).toString();
2633
+ }
2634
+ catch {
2635
+ return defaultValue;
2636
+ }
2637
+ }
2638
+ if (value.value !== undefined) {
2639
+ return normalizeValue(value.value, defaultValue);
2640
+ }
2641
+ if (value.toString && typeof value.toString === "function") {
2642
+ try {
2643
+ const str = value.toString();
2644
+ if (typeof str === "string" && str !== "[object Object]") {
2645
+ return str;
2646
+ }
2647
+ }
2648
+ catch { }
2649
+ }
2650
+ return defaultValue; // Unhandled object
2651
+ }
2652
+ return String(value);
2653
+ };
2654
+ // DEBUG: Log responseData before processing
2655
+ console.log("🔍 STANDALONE RESPONSE DATA ANALYSIS:");
2656
+ console.log(" responseData type:", typeof responseData);
2657
+ console.log(" responseData is object:", typeof responseData === 'object');
2658
+ console.log(" responseData keys:", responseData && typeof responseData === 'object' ? Object.keys(responseData) : "N/A");
2659
+ console.log(" raw responseData.btcPrice:", responseData?.btcPrice, "type:", typeof responseData?.btcPrice);
2660
+ console.log(" raw responseData.btcPrice is empty object:", (() => {
2661
+ const btcPrice = responseData?.btcPrice;
2662
+ return btcPrice && typeof btcPrice === 'object' && Object.keys(btcPrice).length === 0;
2663
+ })());
2222
2664
  // Return standardized response including UTXO data from Bitcoin network query
2223
2665
  const returnValue = {
2224
2666
  approved: responseData?.approved ?? false,
@@ -2229,19 +2671,22 @@ class LitOps {
2229
2671
  authorizedSpendsHash: responseData?.authorizedSpendsHash,
2230
2672
  ucdDebtHash: responseData?.ucdDebtHash,
2231
2673
  contractBundleHash: responseData?.contractBundleHash, // Binds to specific contract deployment
2232
- totalDeduction: responseData?.totalDeduction,
2233
- remainingCollateral: responseData?.remainingCollateral,
2674
+ totalDeduction: normalizeValue(responseData?.totalDeduction, "0"),
2675
+ remainingCollateral: normalizeValue(responseData?.remainingCollateral, "0"),
2234
2676
  newCollateralRatioBps: responseData?.newCollateralRatioBps,
2235
2677
  destinationAddress: responseData?.destinationAddress,
2236
- btcPrice: responseData?.btcPrice,
2237
- timestamp: responseData?.timestamp,
2678
+ btcPrice: normalizeValue(responseData?.btcPrice, "5000000000000"), // Default: $50,000 with 8 decimals
2679
+ timestamp: normalizeValue(responseData?.timestamp, Math.floor(Date.now() / 1000).toString()),
2238
2680
  utxoTxid: responseData?.utxoTxid, // Real Bitcoin UTXO txid from network query
2239
2681
  utxoVout: responseData?.utxoVout, // Real Bitcoin UTXO vout from network query
2240
- utxoSatoshis: responseData?.utxoSatoshis, // UTXO value for validation
2682
+ utxoSatoshis: responseData?.utxoSatoshis ? normalizeValue(responseData?.utxoSatoshis, "0") : undefined, // UTXO value for validation
2241
2683
  reason: responseData?.reason,
2242
2684
  failedStep: responseData?.failedStep,
2243
2685
  error: result.error,
2244
2686
  };
2687
+ console.log("🔍 STANDALONE PROCESSED RETURN VALUE:");
2688
+ console.log(" returnValue.btcPrice:", returnValue.btcPrice, "type:", typeof returnValue.btcPrice);
2689
+ console.log(" returnValue.btcPrice is empty object:", returnValue.btcPrice && typeof returnValue.btcPrice === 'object' && Object.keys(returnValue.btcPrice).length === 0);
2245
2690
  if (this.config.debug) {
2246
2691
  console.log("🎁 STANDALONE RETURN VALUE:", JSON.stringify(returnValue, null, 2));
2247
2692
  }