@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.
- package/dist/modules/auth-manager.module.d.ts.map +1 -1
- package/dist/modules/auth-manager.module.js +41 -42
- package/dist/modules/auth-manager.module.js.map +1 -1
- package/dist/modules/lit-ops.module.d.ts +57 -0
- package/dist/modules/lit-ops.module.d.ts.map +1 -1
- package/dist/modules/lit-ops.module.js +477 -32
- package/dist/modules/lit-ops.module.js.map +1 -1
- package/dist/modules/session-signature-manager.module.d.ts.map +1 -1
- package/dist/modules/session-signature-manager.module.js +12 -30
- package/dist/modules/session-signature-manager.module.js.map +1 -1
- package/dist/utils/pkp-token-id.d.ts +11 -0
- package/dist/utils/pkp-token-id.d.ts.map +1 -0
- package/dist/utils/pkp-token-id.js +44 -0
- package/dist/utils/pkp-token-id.js.map +1 -0
- package/package.json +2 -2
|
@@ -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
|
-
|
|
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
|
-
|
|
1989
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
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
|
}
|