@gvnrdao/dh-lit-ops 0.0.61 ā 0.0.107
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.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interfaces/chunks/config.d.ts +6 -0
- package/dist/interfaces/chunks/config.d.ts.map +1 -1
- package/dist/modules/action-executor.module.d.ts.map +1 -1
- package/dist/modules/action-executor.module.js +103 -20
- package/dist/modules/action-executor.module.js.map +1 -1
- package/dist/modules/auth-manager.module.d.ts.map +1 -1
- package/dist/modules/auth-manager.module.js +149 -32
- package/dist/modules/auth-manager.module.js.map +1 -1
- package/dist/modules/lit-ops.module.d.ts +270 -2
- package/dist/modules/lit-ops.module.d.ts.map +1 -1
- package/dist/modules/lit-ops.module.js +1349 -38
- package/dist/modules/lit-ops.module.js.map +1 -1
- package/dist/modules/pkp-macros.module.d.ts +4 -0
- package/dist/modules/pkp-macros.module.d.ts.map +1 -1
- package/dist/modules/pkp-macros.module.js +28 -8
- package/dist/modules/pkp-macros.module.js.map +1 -1
- package/dist/modules/pkp-minter.module.d.ts +1 -0
- package/dist/modules/pkp-minter.module.d.ts.map +1 -1
- package/dist/modules/pkp-minter.module.js +77 -45
- package/dist/modules/pkp-minter.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 +67 -31
- package/dist/modules/session-signature-manager.module.js.map +1 -1
- package/package.json +2 -2
|
@@ -415,6 +415,29 @@ class LitOps {
|
|
|
415
415
|
};
|
|
416
416
|
return this.actionExecutor.executeAction(request, litClient);
|
|
417
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* TEST-ONLY: Execute arbitrary local LIT Action code for debugging PKP authorization.
|
|
420
|
+
*
|
|
421
|
+
* This helper is intended for Jest / integration tests to run a minimal action
|
|
422
|
+
* (e.g. sign-only) with either wildcard or CID-scoped session signatures.
|
|
423
|
+
*/
|
|
424
|
+
async runLocalLitActionCodeForTest(options) {
|
|
425
|
+
const { code, pkpPublicKey, params, pkpTokenId, cid } = options;
|
|
426
|
+
const litClient = await this.clientManager.getClient({
|
|
427
|
+
litNetwork: this.config.network,
|
|
428
|
+
debug: this.config.debug,
|
|
429
|
+
});
|
|
430
|
+
const request = {
|
|
431
|
+
code,
|
|
432
|
+
cid, // Optional CID: when provided, session sigs are scoped to this action
|
|
433
|
+
pkpPublicKey,
|
|
434
|
+
params,
|
|
435
|
+
signer: this.config.signer,
|
|
436
|
+
pkpTokenId,
|
|
437
|
+
};
|
|
438
|
+
const result = await this.actionExecutor.executeAction(request, litClient);
|
|
439
|
+
return result.response;
|
|
440
|
+
}
|
|
418
441
|
/**
|
|
419
442
|
* Execute a LIT Action from IPFS
|
|
420
443
|
*/
|
|
@@ -630,7 +653,7 @@ class LitOps {
|
|
|
630
653
|
* @param signer - The wallet to use for session signatures
|
|
631
654
|
* @returns PKP validation result with signature verification
|
|
632
655
|
*/
|
|
633
|
-
async validatePKPSecurity(targetPkpTokenId, expectedCid, signerPkp, signer) {
|
|
656
|
+
async validatePKPSecurity(targetPkpTokenId, expectedCid, signerPkp, signer, options) {
|
|
634
657
|
console.log(`š LIT-OPS TRACE: validatePKPSecurity ENTRY`);
|
|
635
658
|
console.log(` - targetPkpTokenId: "${targetPkpTokenId}"`);
|
|
636
659
|
console.log(` - targetPkpTokenId type: ${typeof targetPkpTokenId}`);
|
|
@@ -649,18 +672,25 @@ class LitOps {
|
|
|
649
672
|
// Get the PKP validator CID
|
|
650
673
|
const pkpValidatorCid = (this.config.network === "datil"
|
|
651
674
|
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
652
|
-
:
|
|
675
|
+
: (() => {
|
|
676
|
+
throw new Error("Unsupported LIT network");
|
|
677
|
+
})()).pkpValidator.cid;
|
|
678
|
+
// Convert validator CID to hex format for signature message
|
|
679
|
+
// The contract expects the validator's CID in the signature, not the PKP's CID
|
|
680
|
+
// Use registry CID (same as cr-lit branch) - this is the source of truth
|
|
681
|
+
const validatorCidHex = (0, dh_lit_actions_1.cidToHex)(pkpValidatorCid);
|
|
653
682
|
if (this.config.debug) {
|
|
654
|
-
console.log(` PKP Validator CID: ${pkpValidatorCid}`);
|
|
683
|
+
console.log(` PKP Validator CID (IPFS): ${pkpValidatorCid}`);
|
|
684
|
+
console.log(` Validator CID (hex): ${validatorCidHex}`);
|
|
685
|
+
console.log(` PKP's expected CID (hex): ${expectedCid}`);
|
|
655
686
|
}
|
|
656
687
|
// Execute PKP Validator LIT Action
|
|
657
688
|
// NOTE: Even though the validator PKP is burned/immutable (read-only),
|
|
658
689
|
// we still pass its tokenId so the session signature is scoped to the
|
|
659
690
|
// validator resource. The Lit nodes will simply treat the resource as
|
|
660
691
|
// non-signing, but scoping keeps the session principle of least privilege.
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
console.log(` - expectedCid: "${expectedCid}"`);
|
|
692
|
+
// Normalize signer PKP token ID to hex format for session scoping
|
|
693
|
+
// NOTE: signerPkp IS the validator PKP (passed from call site)
|
|
664
694
|
let sessionScopedSignerTokenId = signerPkp.tokenId;
|
|
665
695
|
try {
|
|
666
696
|
const normalizedHex = BigInt(signerPkp.tokenId)
|
|
@@ -671,22 +701,28 @@ class LitOps {
|
|
|
671
701
|
catch (tokenErr) {
|
|
672
702
|
console.warn("ā ļø Failed to normalize signer PKP tokenId to hex, using raw value", tokenErr);
|
|
673
703
|
}
|
|
674
|
-
// Convert validator CID to hex format for signature message
|
|
675
|
-
// The contract expects the validator's CID in the signature, not the PKP's CID
|
|
676
|
-
const validatorCidHex = (0, dh_lit_actions_1.cidToHex)(pkpValidatorCid);
|
|
677
704
|
if (this.config.debug) {
|
|
678
|
-
console.log(`
|
|
679
|
-
console.log(`
|
|
680
|
-
console.log(` PKP
|
|
705
|
+
console.log(` Signer PKP (validator) Public Key: ${signerPkp.publicKey.substring(0, 20)}...`);
|
|
706
|
+
console.log(` Signer PKP (validator) Token ID: ${signerPkp.tokenId}`);
|
|
707
|
+
console.log(` Signer PKP (validator) ETH Address: ${signerPkp.ethAddress}`);
|
|
681
708
|
}
|
|
682
|
-
|
|
709
|
+
console.log(`\nš LIT-OPS TRACE: About to call executeActionFromCID with jsParams:`);
|
|
710
|
+
console.log(` - targetPkpTokenId: "${targetPkpTokenId}"`);
|
|
711
|
+
console.log(` - expectedCid: "${expectedCid}"`);
|
|
712
|
+
console.log(` - certificationCid: "${validatorCidHex}"`);
|
|
713
|
+
console.log(` - signerPkp.publicKey: "${signerPkp.publicKey.substring(0, 20)}..."`);
|
|
714
|
+
// Use signerPkp directly (which IS the validator PKP from call site, matching cr-lit)
|
|
715
|
+
// The LIT Action will use globalThis.publicKey which is set from pkpPublicKey parameter
|
|
716
|
+
const litResult = await this.executeActionFromCID(pkpValidatorCid, signerPkp.publicKey, // ā
Use signerPkp.publicKey (validator PKP, matching cr-lit)
|
|
717
|
+
{
|
|
683
718
|
targetPkpTokenId,
|
|
684
719
|
expectedCid, // PKP's LIT Action CID (for validation check)
|
|
685
|
-
certificationCid: validatorCidHex, // Validator's CID (for signature message)
|
|
720
|
+
certificationCid: validatorCidHex, // Validator's CID (for signature message) - from registry
|
|
686
721
|
message: `PKP validation: ${Date.now()}`,
|
|
687
722
|
// Ensure the LIT Action knows which network (datil vs datil-test)
|
|
688
723
|
network: this.config.network,
|
|
689
|
-
}, signer, sessionScopedSignerTokenId, signerPkp.
|
|
724
|
+
}, signer, sessionScopedSignerTokenId, // ā
Use normalized signerPkp.tokenId for session scoping (matching cr-lit)
|
|
725
|
+
signerPkp.ethAddress // ā
Use signerPkp.ethAddress for capacity delegation (matching cr-lit)
|
|
690
726
|
);
|
|
691
727
|
if (this.config.debug) {
|
|
692
728
|
console.log(` LIT Action Success: ${litResult.success}`);
|
|
@@ -745,7 +781,7 @@ class LitOps {
|
|
|
745
781
|
console.log(" š Verifying signature authenticity...");
|
|
746
782
|
}
|
|
747
783
|
try {
|
|
748
|
-
// Compute PKP address from public key (
|
|
784
|
+
// Compute validator PKP address from public key (CRITICAL: Use signerPkp.publicKey, matching cr-lit)
|
|
749
785
|
const cleanPublicKey = signerPkp.publicKey.startsWith("0x")
|
|
750
786
|
? signerPkp.publicKey
|
|
751
787
|
: `0x${signerPkp.publicKey}`;
|
|
@@ -893,10 +929,24 @@ class LitOps {
|
|
|
893
929
|
litActionCids: litActionCids,
|
|
894
930
|
}),
|
|
895
931
|
}, timeoutMs);
|
|
932
|
+
// Read response body first (whether success or error)
|
|
933
|
+
const responseText = await response.text();
|
|
934
|
+
let result;
|
|
935
|
+
try {
|
|
936
|
+
result = JSON.parse(responseText);
|
|
937
|
+
}
|
|
938
|
+
catch {
|
|
939
|
+
// If response is not JSON, treat as plain text error
|
|
940
|
+
if (!response.ok) {
|
|
941
|
+
throw new Error(`Service request failed: ${response.status} ${response.statusText} - ${responseText}`);
|
|
942
|
+
}
|
|
943
|
+
throw new Error(`Invalid JSON response from service: ${responseText}`);
|
|
944
|
+
}
|
|
896
945
|
if (!response.ok) {
|
|
897
|
-
|
|
946
|
+
// Extract error message from JSON response
|
|
947
|
+
const errorDetails = result.error || result.message || response.statusText;
|
|
948
|
+
throw new Error(`Service request failed: ${response.status} ${errorDetails}`);
|
|
898
949
|
}
|
|
899
|
-
const result = (await response.json());
|
|
900
950
|
const duration = Date.now() - startTime;
|
|
901
951
|
// The service may wrap the LitOps result as { success, data }
|
|
902
952
|
// Unwrap if needed to maintain a stable SDK return shape
|
|
@@ -1088,8 +1138,16 @@ class LitOps {
|
|
|
1088
1138
|
console.log(` - pkpTokenId startsWith '0x': ${pkpData.tokenId.startsWith("0x")}`);
|
|
1089
1139
|
console.log(` - litActionCidHex (expectedCid): "${litActionCidHex}"`);
|
|
1090
1140
|
console.log(` - validatorPkp: "${validatorPkp}"`);
|
|
1141
|
+
// Get validator version and contract info from config
|
|
1142
|
+
const validatorVersion = this.config.validatorVersion;
|
|
1143
|
+
const ethRpcUrl = this.config.ethRpcUrl;
|
|
1144
|
+
const pkpValidationRegistry = this.config.pkpValidationRegistry;
|
|
1091
1145
|
validationResult = await this.validatePKPSecurity(pkpData.tokenId, litActionCidHex, // Pass hex format CID
|
|
1092
|
-
validatorPkp, signer
|
|
1146
|
+
validatorPkp, signer, {
|
|
1147
|
+
validatorVersion,
|
|
1148
|
+
ethRpcUrl,
|
|
1149
|
+
pkpValidationRegistry,
|
|
1150
|
+
});
|
|
1093
1151
|
// If validation succeeds, break out of retry loop
|
|
1094
1152
|
if (validationResult.success) {
|
|
1095
1153
|
if (this.config.debug && attempt > 1) {
|
|
@@ -1245,7 +1303,9 @@ class LitOps {
|
|
|
1245
1303
|
console.log("šÆ Creating new Diamond Hands Loan PKP");
|
|
1246
1304
|
console.log(" Using authorization CID:", (networkOverride ?? this.config.network) === "datil"
|
|
1247
1305
|
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL.authorizationDummy.cid
|
|
1248
|
-
:
|
|
1306
|
+
: (() => {
|
|
1307
|
+
throw new Error("Unsupported LIT network");
|
|
1308
|
+
})());
|
|
1249
1309
|
console.log(` Mode: ${this.config.mode}`);
|
|
1250
1310
|
if (networkOverride) {
|
|
1251
1311
|
console.log(" Network override:", networkOverride);
|
|
@@ -1258,12 +1318,16 @@ class LitOps {
|
|
|
1258
1318
|
throw new Error("Signer is required for standalone mode");
|
|
1259
1319
|
}
|
|
1260
1320
|
const selectedNetwork = networkOverride ?? this.config.network;
|
|
1261
|
-
const
|
|
1321
|
+
const registry = selectedNetwork === "datil"
|
|
1262
1322
|
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
1263
|
-
:
|
|
1323
|
+
: (() => {
|
|
1324
|
+
throw new Error("Unsupported LIT network");
|
|
1325
|
+
})();
|
|
1326
|
+
// Vault PKP must authorize btcTransactionSigner for Bitcoin transaction signing
|
|
1327
|
+
const btcTxSignerCid = registry.btcTransactionSigner.cid;
|
|
1264
1328
|
console.log(`š LIT-OPS TRACE: getNewDiamondHandsLoanPkp - selectedNetwork = "${selectedNetwork}"`);
|
|
1265
|
-
console.log(`š LIT-OPS TRACE: getNewDiamondHandsLoanPkp -
|
|
1266
|
-
return this.createAndValidatePkpToLitAction(
|
|
1329
|
+
console.log(`š LIT-OPS TRACE: getNewDiamondHandsLoanPkp - btcTransactionSigner.cid = "${btcTxSignerCid}"`);
|
|
1330
|
+
return this.createAndValidatePkpToLitAction(btcTxSignerCid, effectiveSigner);
|
|
1267
1331
|
}
|
|
1268
1332
|
/**
|
|
1269
1333
|
* Request mint authorization from UCD Mint Validator LIT Action
|
|
@@ -1303,6 +1367,125 @@ class LitOps {
|
|
|
1303
1367
|
}
|
|
1304
1368
|
return this.requestMintAuthorizationStandalone(request);
|
|
1305
1369
|
}
|
|
1370
|
+
/**
|
|
1371
|
+
* DEV ONLY: Run BTC Always Signer LIT Action
|
|
1372
|
+
* Intermediate testing tool for Bitcoin transaction structure validation
|
|
1373
|
+
* Signs Bitcoin transactions WITHOUT authorization checks
|
|
1374
|
+
*
|
|
1375
|
+
* @param request - Bitcoin transaction parameters
|
|
1376
|
+
* @returns Signature result with transaction structure
|
|
1377
|
+
*/
|
|
1378
|
+
async runBtcAlwaysSigner(request) {
|
|
1379
|
+
if (this.config.debug) {
|
|
1380
|
+
console.log("š§ [runBtcAlwaysSigner] DEV MODE ONLY");
|
|
1381
|
+
console.log(" Mode:", this.config.mode);
|
|
1382
|
+
}
|
|
1383
|
+
// Service mode: Call server endpoint
|
|
1384
|
+
if (this.config.mode === "service") {
|
|
1385
|
+
return this.runBtcAlwaysSignerViaService(request);
|
|
1386
|
+
}
|
|
1387
|
+
// Standalone mode: Execute locally
|
|
1388
|
+
return this.runBtcAlwaysSignerStandalone(request);
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* Run BTC Always Signer via service (SERVICE mode)
|
|
1392
|
+
*/
|
|
1393
|
+
async runBtcAlwaysSignerViaService(request) {
|
|
1394
|
+
if (!this.config.serviceEndpoint) {
|
|
1395
|
+
throw new Error("Service endpoint not configured for service mode");
|
|
1396
|
+
}
|
|
1397
|
+
const url = `${this.config.serviceEndpoint}/api/lit/dev/btc-always-signer`;
|
|
1398
|
+
if (this.config.debug) {
|
|
1399
|
+
console.log("š Running BTC always-signer via service:", url);
|
|
1400
|
+
console.log(" Destination:", request.destination);
|
|
1401
|
+
console.log(" Amount:", request.amount);
|
|
1402
|
+
}
|
|
1403
|
+
try {
|
|
1404
|
+
const response = await fetch(url, {
|
|
1405
|
+
method: "POST",
|
|
1406
|
+
headers: {
|
|
1407
|
+
"Content-Type": "application/json",
|
|
1408
|
+
},
|
|
1409
|
+
body: JSON.stringify(request),
|
|
1410
|
+
});
|
|
1411
|
+
if (!response.ok) {
|
|
1412
|
+
const errorText = await response.text();
|
|
1413
|
+
throw new Error(`Service error (${response.status}): ${errorText}`);
|
|
1414
|
+
}
|
|
1415
|
+
const result = (await response.json());
|
|
1416
|
+
if (this.config.debug) {
|
|
1417
|
+
console.log("ā
BTC always-signer completed via service");
|
|
1418
|
+
}
|
|
1419
|
+
return result.data || result;
|
|
1420
|
+
}
|
|
1421
|
+
catch (error) {
|
|
1422
|
+
if (this.config.debug) {
|
|
1423
|
+
console.error("ā Service BTC always-signer failed:", error);
|
|
1424
|
+
}
|
|
1425
|
+
return {
|
|
1426
|
+
success: false,
|
|
1427
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
/**
|
|
1432
|
+
* Run BTC Always Signer locally (STANDALONE mode)
|
|
1433
|
+
*/
|
|
1434
|
+
async runBtcAlwaysSignerStandalone(request) {
|
|
1435
|
+
// Get always-signer LIT Action CID
|
|
1436
|
+
const alwaysSignerCid = "QmRcQTDiZJq5arXngdxCX1LPnTW1fvx78tBD9vZmMXg8Ly";
|
|
1437
|
+
if (this.config.debug) {
|
|
1438
|
+
console.log("š” Calling BTC Always Signer LIT Action:");
|
|
1439
|
+
console.log(" CID:", alwaysSignerCid);
|
|
1440
|
+
console.log(" Destination:", request.destination);
|
|
1441
|
+
console.log(" Amount:", request.amount);
|
|
1442
|
+
}
|
|
1443
|
+
try {
|
|
1444
|
+
// Execute LIT Action
|
|
1445
|
+
// NOTE: The always-signer LIT Action expects params in (globalThis as any).params
|
|
1446
|
+
// so we nest the parameters under a 'params' key
|
|
1447
|
+
const result = await this.executeActionFromCID(alwaysSignerCid, request.pkpPublicKey, {
|
|
1448
|
+
params: {
|
|
1449
|
+
amount: request.amount,
|
|
1450
|
+
fee: request.fee,
|
|
1451
|
+
destination: request.destination,
|
|
1452
|
+
utxo: request.utxo,
|
|
1453
|
+
network: request.network,
|
|
1454
|
+
pkpPublicKey: request.pkpPublicKey,
|
|
1455
|
+
},
|
|
1456
|
+
}, this.config.signer, // Use signer from LitOps config
|
|
1457
|
+
undefined, // No PKP token ID needed
|
|
1458
|
+
undefined // No PKP ETH address needed
|
|
1459
|
+
);
|
|
1460
|
+
if (this.config.debug) {
|
|
1461
|
+
console.log("ā
BTC Always Signer executed");
|
|
1462
|
+
console.log(" Success:", result.success);
|
|
1463
|
+
}
|
|
1464
|
+
// Parse response
|
|
1465
|
+
const response = typeof result.response === "string"
|
|
1466
|
+
? JSON.parse(result.response)
|
|
1467
|
+
: result.response;
|
|
1468
|
+
// Extract actual signature from LIT SDK response
|
|
1469
|
+
// LIT SDK puts signatures in result.signatures.btcTxSig
|
|
1470
|
+
if (result.signatures?.btcTxSig) {
|
|
1471
|
+
response.signature = {
|
|
1472
|
+
r: result.signatures.btcTxSig.r,
|
|
1473
|
+
s: result.signatures.btcTxSig.s,
|
|
1474
|
+
recid: result.signatures.btcTxSig.recid,
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
return response;
|
|
1478
|
+
}
|
|
1479
|
+
catch (error) {
|
|
1480
|
+
if (this.config.debug) {
|
|
1481
|
+
console.error("ā BTC Always Signer failed:", error);
|
|
1482
|
+
}
|
|
1483
|
+
return {
|
|
1484
|
+
success: false,
|
|
1485
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1306
1489
|
/**
|
|
1307
1490
|
* Request mint authorization via lit-ops-server (SERVICE mode)
|
|
1308
1491
|
*/
|
|
@@ -1379,15 +1562,26 @@ class LitOps {
|
|
|
1379
1562
|
// Get LIT Action info from registry
|
|
1380
1563
|
const litActions = this.config.network === "datil"
|
|
1381
1564
|
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
1382
|
-
:
|
|
1565
|
+
: (() => {
|
|
1566
|
+
throw new Error("Unsupported LIT network");
|
|
1567
|
+
})();
|
|
1383
1568
|
const litActionInfo = litActions.ucdMintValidator;
|
|
1384
1569
|
if (!litActionInfo || !litActionInfo.cid || !litActionInfo.pkp) {
|
|
1385
1570
|
throw new Error("UCD mint validator LIT Action not found in registry");
|
|
1386
1571
|
}
|
|
1572
|
+
// CRITICAL: Use validator PKP details from registry (not loan PKP)
|
|
1573
|
+
// The validator PKP is the one that signs mint authorization messages
|
|
1574
|
+
const validatorPkpTokenId = litActionInfo.pkp.tokenId;
|
|
1575
|
+
const validatorCid = litActionInfo.cid;
|
|
1576
|
+
const validatorPkpPublicKey = litActionInfo.pkp.publicKey;
|
|
1577
|
+
const validatorPkpEthAddress = litActionInfo.pkp.ethAddress;
|
|
1387
1578
|
if (this.config.debug) {
|
|
1388
1579
|
console.log("š” Calling UCD Mint Validator LIT Action:");
|
|
1389
1580
|
console.log(" Network:", this.config.network);
|
|
1390
|
-
console.log(" CID:",
|
|
1581
|
+
console.log(" Validator CID:", validatorCid);
|
|
1582
|
+
console.log(" Validator PKP Token ID:", validatorPkpTokenId);
|
|
1583
|
+
console.log(" Validator PKP Public Key:", validatorPkpPublicKey);
|
|
1584
|
+
console.log(" Validator PKP ETH Address:", validatorPkpEthAddress);
|
|
1391
1585
|
console.log(" Position:", request.authMessage.positionId);
|
|
1392
1586
|
console.log(" Amount:", request.authMessage.amount);
|
|
1393
1587
|
console.log(" Timestamp:", request.authMessage.timestamp);
|
|
@@ -1410,7 +1604,7 @@ class LitOps {
|
|
|
1410
1604
|
chain = "sepolia";
|
|
1411
1605
|
bitcoinProviderUrl =
|
|
1412
1606
|
process.env.BITCOIN_PROVIDER_URL ||
|
|
1413
|
-
"https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api";
|
|
1607
|
+
"https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api/esplora";
|
|
1414
1608
|
break;
|
|
1415
1609
|
case 1337: // Hardhat local testnet (actual deployment chainId)
|
|
1416
1610
|
case 31337: // Hardhat local testnet (standard default)
|
|
@@ -1442,11 +1636,16 @@ class LitOps {
|
|
|
1442
1636
|
action: request.authMessage.action,
|
|
1443
1637
|
signature: request.userSignature,
|
|
1444
1638
|
mode: request.authMessage.mode,
|
|
1445
|
-
...(request.authMessage.contracts && {
|
|
1446
|
-
contracts: request.authMessage.contracts,
|
|
1447
|
-
}),
|
|
1448
1639
|
},
|
|
1449
1640
|
amount: request.authMessage.amount,
|
|
1641
|
+
// Contract addresses must be at top level to become globalThis.contractAddresses in LIT Action
|
|
1642
|
+
...(request.authMessage.contractAddresses && {
|
|
1643
|
+
contractAddresses: request.authMessage.contractAddresses,
|
|
1644
|
+
}),
|
|
1645
|
+
// Price providers with API keys for faster price fetching
|
|
1646
|
+
...(request.priceProviders && {
|
|
1647
|
+
priceProviders: request.priceProviders,
|
|
1648
|
+
}),
|
|
1450
1649
|
};
|
|
1451
1650
|
// Add custom RPC URL for local development (ngrok tunnels)
|
|
1452
1651
|
if (request.customRpcUrl) {
|
|
@@ -1455,14 +1654,115 @@ class LitOps {
|
|
|
1455
1654
|
console.log(" Custom RPC URL:", request.customRpcUrl);
|
|
1456
1655
|
}
|
|
1457
1656
|
}
|
|
1458
|
-
//
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1657
|
+
// Verify PKP authorization before executing LIT Action
|
|
1658
|
+
// Use validator PKP details (not loan PKP)
|
|
1659
|
+
if (validatorCid && validatorPkpTokenId) {
|
|
1660
|
+
console.log("[LitOps] ======= PKP Authorization Check =======");
|
|
1661
|
+
console.log("[LitOps] Validator PKP Token ID:", validatorPkpTokenId);
|
|
1662
|
+
console.log("[LitOps] Validator Lit Action CID:", validatorCid);
|
|
1663
|
+
try {
|
|
1664
|
+
const pkpAuthorizer = new pkp_authorizer_module_1.PKPAuthorizer({
|
|
1665
|
+
debug: this.config.debug,
|
|
1666
|
+
signer: this.config.signer,
|
|
1667
|
+
network: this.config.network, // Pass LIT network (e.g., 'datil') for PKP authorization check
|
|
1668
|
+
});
|
|
1669
|
+
const isPermitted = await pkpAuthorizer.isActionPermitted(validatorPkpTokenId, validatorCid);
|
|
1670
|
+
console.log("[LitOps] PKP Authorization Status:", isPermitted ? "ā
AUTHORIZED" : "ā NOT AUTHORIZED");
|
|
1671
|
+
if (!isPermitted) {
|
|
1672
|
+
console.warn("[LitOps] ā ļø PKP is not authorized for this Lit Action CID");
|
|
1673
|
+
console.warn("[LitOps] This may cause signing to fail or timeout");
|
|
1674
|
+
console.warn("[LitOps] Session signatures may use wildcard authorization instead");
|
|
1675
|
+
}
|
|
1676
|
+
// Get comprehensive permission check for debugging
|
|
1677
|
+
const permissionCheck = await pkpAuthorizer.checkPermissions(validatorPkpTokenId, validatorCid);
|
|
1678
|
+
console.log("[LitOps] Permitted Actions Count:", permissionCheck.permittedActions.length);
|
|
1679
|
+
console.log("[LitOps] CID in Permitted List:", permissionCheck.isPermitted);
|
|
1680
|
+
if (permissionCheck.permittedActions.length > 0) {
|
|
1681
|
+
console.log("[LitOps] Sample Permitted Actions:", permissionCheck.permittedActions.slice(0, 3));
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
catch (authError) {
|
|
1685
|
+
console.warn("[LitOps] ā ļø Failed to check PKP authorization:", authError instanceof Error ? authError.message : String(authError));
|
|
1686
|
+
console.warn("[LitOps] Continuing with execution - may use wildcard authorization");
|
|
1687
|
+
}
|
|
1688
|
+
console.log("[LitOps] ================================");
|
|
1689
|
+
}
|
|
1690
|
+
else {
|
|
1691
|
+
console.log("[LitOps] ā ļø Skipping PKP authorization check (CID or tokenId missing)");
|
|
1692
|
+
if (!validatorCid) {
|
|
1693
|
+
console.log("[LitOps] Validator CID:", validatorCid);
|
|
1694
|
+
}
|
|
1695
|
+
if (!validatorPkpTokenId) {
|
|
1696
|
+
console.log("[LitOps] Validator PKP Token ID:", validatorPkpTokenId);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
// CRITICAL: Use validator PKP token ID (not loan PKP)
|
|
1700
|
+
// Session signatures must authorize the validator PKP to sign, not the loan PKP
|
|
1701
|
+
// PKP token ID should already be in decimal format from the registry
|
|
1702
|
+
// Don't normalize it - session-signature-manager will handle the conversion to hex
|
|
1703
|
+
// The registry stores token IDs as decimal strings, and session-signature-manager
|
|
1704
|
+
// expects decimal input which it then converts to hex for LitPKPResource
|
|
1705
|
+
const normalizedPkpTokenId = validatorPkpTokenId;
|
|
1706
|
+
// Check if we should use local code execution
|
|
1707
|
+
// CRITICAL: If we have a registry CID, always use IPFS mode
|
|
1708
|
+
// Never use local code when we have a deployed registry CID
|
|
1709
|
+
const useLocalCode = this.config.litActionExecution === 'local' && !validatorCid;
|
|
1710
|
+
if (this.config.debug) {
|
|
1711
|
+
console.log("š [DEBUG] litActionExecution config:", this.config.litActionExecution);
|
|
1712
|
+
console.log("š [DEBUG] Validator CID available:", validatorCid);
|
|
1713
|
+
console.log("š [DEBUG] useLocalCode:", useLocalCode, "(ignored if registry CID exists)");
|
|
1714
|
+
}
|
|
1715
|
+
let result;
|
|
1716
|
+
if (useLocalCode) {
|
|
1717
|
+
// Only use local code if NO registry CID is available (shouldn't happen in production)
|
|
1718
|
+
// Read code from local dist file
|
|
1719
|
+
const fs = require('fs');
|
|
1720
|
+
const path = require('path');
|
|
1721
|
+
// Try multiple possible paths
|
|
1722
|
+
const possiblePaths = [
|
|
1723
|
+
path.join(__dirname, '../../lit-actions/dist/ucd-mint-validator.action.js'),
|
|
1724
|
+
path.join(process.cwd(), 'lit-actions/dist/ucd-mint-validator.action.js'),
|
|
1725
|
+
path.join(process.cwd(), '../lit-actions/dist/ucd-mint-validator.action.js'),
|
|
1726
|
+
];
|
|
1727
|
+
let codePath;
|
|
1728
|
+
for (const p of possiblePaths) {
|
|
1729
|
+
if (fs.existsSync(p)) {
|
|
1730
|
+
codePath = p;
|
|
1731
|
+
break;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
if (!codePath) {
|
|
1735
|
+
throw new Error(`Local LIT action code not found. Tried: ${possiblePaths.join(', ')}. Please build lit-actions first.`);
|
|
1736
|
+
}
|
|
1737
|
+
const code = fs.readFileSync(codePath, 'utf8');
|
|
1738
|
+
if (this.config.debug) {
|
|
1739
|
+
console.log("š¦ Using LOCAL LIT Action code (not IPFS)");
|
|
1740
|
+
console.log(" Code path:", codePath);
|
|
1741
|
+
console.log(" Code size:", code.length, "bytes");
|
|
1742
|
+
}
|
|
1743
|
+
result = await this.executeActionFromCode(code, validatorPkpPublicKey, // Use validator PKP public key
|
|
1744
|
+
litActionParams, this.config.signer, normalizedPkpTokenId, // Validator PKP token ID
|
|
1745
|
+
validatorCid // Validator CID for authorization validation
|
|
1746
|
+
);
|
|
1747
|
+
}
|
|
1748
|
+
else {
|
|
1749
|
+
// Always use IPFS mode when we have a registry CID
|
|
1750
|
+
// This ensures the Lit SDK uses the correct CID from the registry for authorization
|
|
1751
|
+
// Execute LIT Action (single attempt - retry logic is in SDK layer)
|
|
1752
|
+
// CRITICAL: Pass validator PKP token ID for session signature PKP scoping (fixes signEcdsa timeout)
|
|
1753
|
+
// Use normalized decimal format for consistent conversion in session-signature-manager
|
|
1754
|
+
result = await this.actionExecutor.executeAction({
|
|
1755
|
+
cid: validatorCid, // Use validator CID from registry
|
|
1756
|
+
pkpPublicKey: validatorPkpPublicKey, // Use validator PKP public key
|
|
1757
|
+
params: litActionParams,
|
|
1758
|
+
signer: this.config.signer,
|
|
1759
|
+
pkpTokenId: normalizedPkpTokenId, // Validator PKP token ID (decimal string)
|
|
1760
|
+
pkpEthAddress: validatorPkpEthAddress, // Validator PKP ETH address for capacity credit delegation
|
|
1761
|
+
}, litClient);
|
|
1762
|
+
}
|
|
1465
1763
|
if (this.config.debug) {
|
|
1764
|
+
console.log("š [DEBUG] litActionParams passed to LIT Action:", JSON.stringify(litActionParams, null, 2));
|
|
1765
|
+
console.log("š [DEBUG] contractAddresses in litActionParams:", litActionParams.contractAddresses);
|
|
1466
1766
|
console.log("š„ LIT Action response:", {
|
|
1467
1767
|
success: result.success,
|
|
1468
1768
|
hasSignature: !!result.signatures,
|
|
@@ -1502,6 +1802,8 @@ class LitOps {
|
|
|
1502
1802
|
newCollateral: responseData?.newCollateral,
|
|
1503
1803
|
btcPrice: responseData?.btcPrice,
|
|
1504
1804
|
authorizedSpendsHash: responseData?.authorizedSpendsHash,
|
|
1805
|
+
ucdDebtHash: responseData?.ucdDebtHash,
|
|
1806
|
+
contractBundleHash: responseData?.contractBundleHash,
|
|
1505
1807
|
timestamp: responseData?.timestamp,
|
|
1506
1808
|
reason: responseData?.reason,
|
|
1507
1809
|
failedStep: responseData?.failedStep,
|
|
@@ -1514,6 +1816,1013 @@ class LitOps {
|
|
|
1514
1816
|
}
|
|
1515
1817
|
return returnValue;
|
|
1516
1818
|
}
|
|
1819
|
+
/**
|
|
1820
|
+
* Request extend position authorization from Extend Position Validator LIT Action
|
|
1821
|
+
*
|
|
1822
|
+
* In SERVICE mode: Delegates to lit-ops-server
|
|
1823
|
+
* In STANDALONE mode: Executes LIT action locally
|
|
1824
|
+
*
|
|
1825
|
+
* @param request - Authorization request with authMessage and userSignature
|
|
1826
|
+
* @returns Extend authorization response from LIT Action
|
|
1827
|
+
*/
|
|
1828
|
+
async requestExtendAuthorization(request) {
|
|
1829
|
+
// In SERVICE mode, delegate to lit-ops-server
|
|
1830
|
+
if (this.config.mode === "service") {
|
|
1831
|
+
return this.requestExtendAuthorizationViaService(request);
|
|
1832
|
+
}
|
|
1833
|
+
return this.requestExtendAuthorizationStandalone(request);
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Request extend authorization via lit-ops-server (SERVICE mode)
|
|
1837
|
+
*/
|
|
1838
|
+
async requestExtendAuthorizationViaService(request) {
|
|
1839
|
+
if (!this.config.serviceEndpoint) {
|
|
1840
|
+
throw new Error("Service endpoint not configured for service mode");
|
|
1841
|
+
}
|
|
1842
|
+
const url = `${this.config.serviceEndpoint}/api/lit/extend/authorize`;
|
|
1843
|
+
if (this.config.debug) {
|
|
1844
|
+
console.log("š Requesting extend authorization via service:", url);
|
|
1845
|
+
console.log(" Position ID:", request.authMessage.positionId);
|
|
1846
|
+
console.log(" New Term:", request.authMessage.newTerm);
|
|
1847
|
+
}
|
|
1848
|
+
try {
|
|
1849
|
+
const response = await fetch(url, {
|
|
1850
|
+
method: "POST",
|
|
1851
|
+
headers: {
|
|
1852
|
+
"Content-Type": "application/json",
|
|
1853
|
+
},
|
|
1854
|
+
body: JSON.stringify({
|
|
1855
|
+
authMessage: request.authMessage,
|
|
1856
|
+
userSignature: request.userSignature,
|
|
1857
|
+
customRpcUrl: request.customRpcUrl,
|
|
1858
|
+
customBitcoinRpcUrl: request.customBitcoinRpcUrl,
|
|
1859
|
+
}),
|
|
1860
|
+
});
|
|
1861
|
+
if (!response.ok) {
|
|
1862
|
+
const errorText = await response.text();
|
|
1863
|
+
throw new Error(`Service error (${response.status}): ${errorText}`);
|
|
1864
|
+
}
|
|
1865
|
+
const envelope = await response.json();
|
|
1866
|
+
if (envelope.success && envelope.data) {
|
|
1867
|
+
return envelope.data;
|
|
1868
|
+
}
|
|
1869
|
+
else if (!envelope.success && envelope.error) {
|
|
1870
|
+
return {
|
|
1871
|
+
approved: false,
|
|
1872
|
+
error: envelope.error,
|
|
1873
|
+
reason: "Service returned error",
|
|
1874
|
+
};
|
|
1875
|
+
}
|
|
1876
|
+
return envelope;
|
|
1877
|
+
}
|
|
1878
|
+
catch (error) {
|
|
1879
|
+
if (this.config.debug) {
|
|
1880
|
+
console.error("ā Service extend authorization failed:", error);
|
|
1881
|
+
}
|
|
1882
|
+
return {
|
|
1883
|
+
approved: false,
|
|
1884
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1885
|
+
reason: "Service request failed",
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
/**
|
|
1890
|
+
* Request extend authorization locally (STANDALONE mode)
|
|
1891
|
+
*/
|
|
1892
|
+
async requestExtendAuthorizationStandalone(request) {
|
|
1893
|
+
// Get LIT Action info from registry
|
|
1894
|
+
const litActions = this.config.network === "datil"
|
|
1895
|
+
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
1896
|
+
: (() => {
|
|
1897
|
+
throw new Error("Unsupported LIT network");
|
|
1898
|
+
})();
|
|
1899
|
+
// Note: extendPositionValidator needs to be added to registry
|
|
1900
|
+
// For now, we'll throw an error if not found
|
|
1901
|
+
const litActionInfo = litActions.extendPositionValidator;
|
|
1902
|
+
if (!litActionInfo || !litActionInfo.cid || !litActionInfo.pkp) {
|
|
1903
|
+
throw new Error("Extend position validator LIT Action not found in registry");
|
|
1904
|
+
}
|
|
1905
|
+
if (this.config.debug) {
|
|
1906
|
+
console.log("š” Calling Extend Position Validator LIT Action:");
|
|
1907
|
+
console.log(" Network:", this.config.network);
|
|
1908
|
+
console.log(" CID:", litActionInfo.cid);
|
|
1909
|
+
console.log(" Position:", request.authMessage.positionId);
|
|
1910
|
+
console.log(" New Term:", request.authMessage.newTerm);
|
|
1911
|
+
}
|
|
1912
|
+
// Verify PKP authorization before executing LIT Action
|
|
1913
|
+
if (litActionInfo.cid && litActionInfo.pkp.tokenId) {
|
|
1914
|
+
console.log("[LitOps] ======= PKP Authorization Check =======");
|
|
1915
|
+
console.log("[LitOps] PKP Token ID:", litActionInfo.pkp.tokenId);
|
|
1916
|
+
console.log("[LitOps] Lit Action CID:", litActionInfo.cid);
|
|
1917
|
+
try {
|
|
1918
|
+
const pkpAuthorizer = new pkp_authorizer_module_1.PKPAuthorizer({
|
|
1919
|
+
debug: this.config.debug,
|
|
1920
|
+
signer: this.config.signer,
|
|
1921
|
+
network: this.config.network, // Pass LIT network (e.g., 'datil') for PKP authorization check
|
|
1922
|
+
});
|
|
1923
|
+
const isPermitted = await pkpAuthorizer.isActionPermitted(litActionInfo.pkp.tokenId, litActionInfo.cid);
|
|
1924
|
+
console.log("[LitOps] PKP Authorization Status:", isPermitted ? "ā
AUTHORIZED" : "ā NOT AUTHORIZED");
|
|
1925
|
+
if (!isPermitted) {
|
|
1926
|
+
console.warn("[LitOps] ā ļø PKP is not authorized for this Lit Action CID");
|
|
1927
|
+
console.warn("[LitOps] This may cause signing to fail or timeout");
|
|
1928
|
+
console.warn("[LitOps] Session signatures may use wildcard authorization instead");
|
|
1929
|
+
}
|
|
1930
|
+
// Get comprehensive permission check for debugging
|
|
1931
|
+
const permissionCheck = await pkpAuthorizer.checkPermissions(litActionInfo.pkp.tokenId, litActionInfo.cid);
|
|
1932
|
+
console.log("[LitOps] Permitted Actions Count:", permissionCheck.permittedActions.length);
|
|
1933
|
+
console.log("[LitOps] CID in Permitted List:", permissionCheck.isPermitted);
|
|
1934
|
+
if (permissionCheck.permittedActions.length > 0) {
|
|
1935
|
+
console.log("[LitOps] Sample Permitted Actions:", permissionCheck.permittedActions.slice(0, 3));
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
catch (authError) {
|
|
1939
|
+
console.warn("[LitOps] ā ļø Failed to check PKP authorization:", authError instanceof Error ? authError.message : String(authError));
|
|
1940
|
+
console.warn("[LitOps] Continuing with execution - may use wildcard authorization");
|
|
1941
|
+
}
|
|
1942
|
+
console.log("[LitOps] ================================");
|
|
1943
|
+
}
|
|
1944
|
+
else {
|
|
1945
|
+
console.log("[LitOps] ā ļø Skipping PKP authorization check (CID or tokenId missing)");
|
|
1946
|
+
if (!litActionInfo.cid) {
|
|
1947
|
+
console.log("[LitOps] CID:", litActionInfo.cid);
|
|
1948
|
+
}
|
|
1949
|
+
if (!litActionInfo.pkp.tokenId) {
|
|
1950
|
+
console.log("[LitOps] PKP Token ID:", litActionInfo.pkp.tokenId);
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
// Get LIT client for execution
|
|
1954
|
+
const litClient = await this.clientManager.getClient({
|
|
1955
|
+
litNetwork: this.config.network,
|
|
1956
|
+
debug: this.config.debug,
|
|
1957
|
+
});
|
|
1958
|
+
// Determine chain and Bitcoin provider from chainId
|
|
1959
|
+
let chain;
|
|
1960
|
+
let bitcoinProviderUrl;
|
|
1961
|
+
switch (request.authMessage.chainId) {
|
|
1962
|
+
case 1: // Ethereum mainnet
|
|
1963
|
+
chain = "ethereum";
|
|
1964
|
+
bitcoinProviderUrl =
|
|
1965
|
+
process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
|
|
1966
|
+
break;
|
|
1967
|
+
case 11155111: // Sepolia testnet
|
|
1968
|
+
chain = "sepolia";
|
|
1969
|
+
bitcoinProviderUrl =
|
|
1970
|
+
process.env.BITCOIN_PROVIDER_URL ||
|
|
1971
|
+
"https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api/esplora";
|
|
1972
|
+
break;
|
|
1973
|
+
case 1337: // Hardhat local testnet (actual deployment chainId)
|
|
1974
|
+
case 31337: // Hardhat local testnet (standard default)
|
|
1975
|
+
chain = "hardhat";
|
|
1976
|
+
bitcoinProviderUrl =
|
|
1977
|
+
process.env.BITCOIN_PROVIDER_URL || "http://127.0.0.1:18443";
|
|
1978
|
+
break;
|
|
1979
|
+
default:
|
|
1980
|
+
throw new Error(`Unsupported chainId: ${request.authMessage.chainId}`);
|
|
1981
|
+
}
|
|
1982
|
+
if (request.customBitcoinRpcUrl) {
|
|
1983
|
+
bitcoinProviderUrl = request.customBitcoinRpcUrl;
|
|
1984
|
+
if (this.config.debug) {
|
|
1985
|
+
console.log(" Custom Bitcoin RPC URL:", request.customBitcoinRpcUrl);
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
const litActionParams = {
|
|
1989
|
+
chain,
|
|
1990
|
+
bitcoinProviderUrl,
|
|
1991
|
+
auth: {
|
|
1992
|
+
positionId: request.authMessage.positionId,
|
|
1993
|
+
timestamp: request.authMessage.timestamp,
|
|
1994
|
+
chainId: request.authMessage.chainId,
|
|
1995
|
+
newTerm: request.authMessage.newTerm,
|
|
1996
|
+
action: request.authMessage.action,
|
|
1997
|
+
signature: request.userSignature,
|
|
1998
|
+
mode: request.authMessage.mode,
|
|
1999
|
+
},
|
|
2000
|
+
selectedTerm: request.authMessage.newTerm,
|
|
2001
|
+
// Contract addresses must be at top level to become globalThis.contractAddresses in LIT Action
|
|
2002
|
+
...(request.authMessage.contractAddresses && {
|
|
2003
|
+
contractAddresses: request.authMessage.contractAddresses,
|
|
2004
|
+
}),
|
|
2005
|
+
// Price providers with API keys for faster price fetching
|
|
2006
|
+
...(request.priceProviders && {
|
|
2007
|
+
priceProviders: request.priceProviders,
|
|
2008
|
+
}),
|
|
2009
|
+
};
|
|
2010
|
+
// Debug: Log priceProviders to verify they're being passed
|
|
2011
|
+
if (this.config.debug) {
|
|
2012
|
+
console.log(" Price Providers:", request.priceProviders);
|
|
2013
|
+
console.log(" Price Providers in litActionParams:", litActionParams.priceProviders);
|
|
2014
|
+
}
|
|
2015
|
+
if (request.customRpcUrl) {
|
|
2016
|
+
litActionParams.customRpcUrl = request.customRpcUrl;
|
|
2017
|
+
}
|
|
2018
|
+
// PKP token ID should already be in decimal format from the registry
|
|
2019
|
+
// Don't normalize it - session-signature-manager will handle the conversion to hex
|
|
2020
|
+
// The registry stores token IDs as decimal strings, and session-signature-manager
|
|
2021
|
+
// expects decimal input which it then converts to hex for LitPKPResource
|
|
2022
|
+
const normalizedPkpTokenId = litActionInfo.pkp.tokenId;
|
|
2023
|
+
// Check if we should use local code execution
|
|
2024
|
+
// CRITICAL: If we have a registry CID, always use IPFS mode
|
|
2025
|
+
// Never use local code when we have a deployed registry CID
|
|
2026
|
+
const useLocalCode = this.config.litActionExecution === 'local' && !litActionInfo.cid;
|
|
2027
|
+
if (this.config.debug) {
|
|
2028
|
+
console.log("š [DEBUG] litActionExecution config:", this.config.litActionExecution);
|
|
2029
|
+
console.log("š [DEBUG] Registry CID available:", litActionInfo.cid);
|
|
2030
|
+
console.log("š [DEBUG] useLocalCode:", useLocalCode, "(ignored if registry CID exists)");
|
|
2031
|
+
}
|
|
2032
|
+
let result;
|
|
2033
|
+
if (useLocalCode) {
|
|
2034
|
+
// Only use local code if NO registry CID is available (shouldn't happen in production)
|
|
2035
|
+
// Read code from local dist file
|
|
2036
|
+
const fs = require('fs');
|
|
2037
|
+
const path = require('path');
|
|
2038
|
+
// Try multiple possible paths
|
|
2039
|
+
const possiblePaths = [
|
|
2040
|
+
path.join(__dirname, '../../lit-actions/dist/extend-position-validator.action.js'),
|
|
2041
|
+
path.join(process.cwd(), 'lit-actions/dist/extend-position-validator.action.js'),
|
|
2042
|
+
path.join(process.cwd(), '../lit-actions/dist/extend-position-validator.action.js'),
|
|
2043
|
+
];
|
|
2044
|
+
let codePath;
|
|
2045
|
+
for (const p of possiblePaths) {
|
|
2046
|
+
if (fs.existsSync(p)) {
|
|
2047
|
+
codePath = p;
|
|
2048
|
+
break;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
if (!codePath) {
|
|
2052
|
+
throw new Error(`Local LIT action code not found. Tried: ${possiblePaths.join(', ')}. Please build lit-actions first.`);
|
|
2053
|
+
}
|
|
2054
|
+
const code = fs.readFileSync(codePath, 'utf8');
|
|
2055
|
+
if (this.config.debug) {
|
|
2056
|
+
console.log("š¦ Using LOCAL LIT Action code (not IPFS)");
|
|
2057
|
+
console.log(" Code path:", codePath);
|
|
2058
|
+
console.log(" Code size:", code.length, "bytes");
|
|
2059
|
+
}
|
|
2060
|
+
result = await this.executeActionFromCode(code, litActionInfo.pkp.publicKey, litActionParams, this.config.signer, normalizedPkpTokenId, // Normalized to decimal string for consistent handling
|
|
2061
|
+
litActionInfo.cid // Still provide CID for authorization validation
|
|
2062
|
+
);
|
|
2063
|
+
}
|
|
2064
|
+
else {
|
|
2065
|
+
// Always use IPFS mode when we have a registry CID
|
|
2066
|
+
// This ensures the Lit SDK uses the correct CID from the registry for authorization
|
|
2067
|
+
// Execute LIT Action (single attempt - retry logic is in SDK layer)
|
|
2068
|
+
// CRITICAL: Pass pkpTokenId for session signature PKP scoping (fixes signEcdsa timeout)
|
|
2069
|
+
// Use normalized decimal format for consistent conversion in session-signature-manager
|
|
2070
|
+
result = await this.actionExecutor.executeAction({
|
|
2071
|
+
cid: litActionInfo.cid, // Use registry CID
|
|
2072
|
+
pkpPublicKey: litActionInfo.pkp.publicKey,
|
|
2073
|
+
params: litActionParams,
|
|
2074
|
+
signer: this.config.signer,
|
|
2075
|
+
pkpTokenId: normalizedPkpTokenId, // Normalized to decimal string for consistent handling
|
|
2076
|
+
pkpEthAddress: litActionInfo.pkp.ethAddress, // Required for capacity credit delegation
|
|
2077
|
+
}, litClient);
|
|
2078
|
+
}
|
|
2079
|
+
let responseData = result.response;
|
|
2080
|
+
if (typeof result.response === "string") {
|
|
2081
|
+
try {
|
|
2082
|
+
responseData = JSON.parse(result.response);
|
|
2083
|
+
}
|
|
2084
|
+
catch (e) {
|
|
2085
|
+
// Ignore parse errors
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
// Handle signature: prefer LIT SDK format (result.signatures), fall back to responseData.signature
|
|
2089
|
+
let signature;
|
|
2090
|
+
if (result.signatures) {
|
|
2091
|
+
signature = JSON.stringify(result.signatures);
|
|
2092
|
+
}
|
|
2093
|
+
else if (responseData?.signature) {
|
|
2094
|
+
signature = responseData.signature;
|
|
2095
|
+
}
|
|
2096
|
+
return {
|
|
2097
|
+
approved: responseData?.approved ?? false,
|
|
2098
|
+
signature,
|
|
2099
|
+
btcPrice: responseData?.btcPrice,
|
|
2100
|
+
availableBTCBalance: responseData?.availableBTCBalance,
|
|
2101
|
+
extensionFee: responseData?.extensionFee,
|
|
2102
|
+
newTotalDebt: responseData?.newTotalDebt,
|
|
2103
|
+
newCollateralRatioBps: responseData?.newCollateralRatioBps,
|
|
2104
|
+
quantumTimestamp: responseData?.quantumTimestamp,
|
|
2105
|
+
timestamp: responseData?.timestamp,
|
|
2106
|
+
reason: responseData?.reason,
|
|
2107
|
+
failedStep: responseData?.failedStep,
|
|
2108
|
+
error: result.error,
|
|
2109
|
+
};
|
|
2110
|
+
}
|
|
2111
|
+
/**
|
|
2112
|
+
* Request BTC withdrawal authorization (dual-mode)
|
|
2113
|
+
*
|
|
2114
|
+
* @param request - Authorization request with authMessage and userSignature
|
|
2115
|
+
* @returns Withdrawal authorization response from LIT Action
|
|
2116
|
+
*/
|
|
2117
|
+
async requestWithdrawalAuthorization(request) {
|
|
2118
|
+
// In SERVICE mode, delegate to lit-ops-server
|
|
2119
|
+
if (this.config.mode === "service") {
|
|
2120
|
+
if (this.config.debug) {
|
|
2121
|
+
console.log("š [requestWithdrawalAuthorization] Using SERVICE mode - delegating to server");
|
|
2122
|
+
}
|
|
2123
|
+
return this.requestWithdrawalAuthorizationViaService(request);
|
|
2124
|
+
}
|
|
2125
|
+
// STANDALONE mode: Execute LIT action locally
|
|
2126
|
+
if (this.config.debug) {
|
|
2127
|
+
console.log("š§ [requestWithdrawalAuthorization] Using STANDALONE mode - executing locally");
|
|
2128
|
+
}
|
|
2129
|
+
return this.requestWithdrawalAuthorizationStandalone(request);
|
|
2130
|
+
}
|
|
2131
|
+
/**
|
|
2132
|
+
* Request withdrawal authorization via lit-ops-server (SERVICE mode)
|
|
2133
|
+
*/
|
|
2134
|
+
async requestWithdrawalAuthorizationViaService(request) {
|
|
2135
|
+
if (!this.config.serviceEndpoint) {
|
|
2136
|
+
throw new Error("Service endpoint not configured for service mode");
|
|
2137
|
+
}
|
|
2138
|
+
const url = `${this.config.serviceEndpoint}/api/lit/withdrawal/authorize`;
|
|
2139
|
+
if (this.config.debug) {
|
|
2140
|
+
console.log("š Requesting withdrawal authorization via service:", url);
|
|
2141
|
+
console.log(" Position ID:", request.authMessage.positionId);
|
|
2142
|
+
console.log(" Amount:", request.authMessage.amount);
|
|
2143
|
+
console.log(" Address:", request.authMessage.withdrawalAddress);
|
|
2144
|
+
}
|
|
2145
|
+
try {
|
|
2146
|
+
const response = await fetch(url, {
|
|
2147
|
+
method: "POST",
|
|
2148
|
+
headers: {
|
|
2149
|
+
"Content-Type": "application/json",
|
|
2150
|
+
},
|
|
2151
|
+
body: JSON.stringify({
|
|
2152
|
+
authMessage: request.authMessage,
|
|
2153
|
+
userSignature: request.userSignature,
|
|
2154
|
+
customRpcUrl: request.customRpcUrl,
|
|
2155
|
+
customBitcoinRpcUrl: request.customBitcoinRpcUrl,
|
|
2156
|
+
}),
|
|
2157
|
+
});
|
|
2158
|
+
if (!response.ok) {
|
|
2159
|
+
const errorText = await response.text();
|
|
2160
|
+
throw new Error(`Service error (${response.status}): ${errorText}`);
|
|
2161
|
+
}
|
|
2162
|
+
const envelope = await response.json();
|
|
2163
|
+
if (this.config.debug) {
|
|
2164
|
+
console.log("š„ Service response:", envelope);
|
|
2165
|
+
}
|
|
2166
|
+
// Return the result from service
|
|
2167
|
+
return {
|
|
2168
|
+
approved: envelope.approved ?? false,
|
|
2169
|
+
signature: envelope.signature,
|
|
2170
|
+
totalDeduction: envelope.totalDeduction,
|
|
2171
|
+
remainingCollateral: envelope.remainingCollateral,
|
|
2172
|
+
newCollateralRatioBps: envelope.newCollateralRatioBps,
|
|
2173
|
+
destinationAddress: envelope.destinationAddress,
|
|
2174
|
+
btcPrice: envelope.btcPrice,
|
|
2175
|
+
timestamp: envelope.timestamp,
|
|
2176
|
+
reason: envelope.reason,
|
|
2177
|
+
failedStep: envelope.failedStep,
|
|
2178
|
+
error: envelope.error,
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
catch (error) {
|
|
2182
|
+
console.error("ā Service request failed:", error);
|
|
2183
|
+
return {
|
|
2184
|
+
approved: false,
|
|
2185
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2186
|
+
reason: "Service request failed",
|
|
2187
|
+
};
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
/**
|
|
2191
|
+
* Request withdrawal authorization locally (STANDALONE mode)
|
|
2192
|
+
*/
|
|
2193
|
+
async requestWithdrawalAuthorizationStandalone(request) {
|
|
2194
|
+
// Get LIT Action info from registry
|
|
2195
|
+
const litActions = this.config.network === "datil"
|
|
2196
|
+
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
2197
|
+
: (() => {
|
|
2198
|
+
throw new Error("Unsupported LIT network");
|
|
2199
|
+
})();
|
|
2200
|
+
const litActionInfo = litActions.btcWithdrawal;
|
|
2201
|
+
if (!litActionInfo || !litActionInfo.cid || !litActionInfo.pkp) {
|
|
2202
|
+
throw new Error("BTC withdrawal LIT Action not found in registry");
|
|
2203
|
+
}
|
|
2204
|
+
if (this.config.debug) {
|
|
2205
|
+
console.log("š” Calling BTC Withdrawal LIT Action:");
|
|
2206
|
+
console.log(" Network:", this.config.network);
|
|
2207
|
+
console.log(" CID:", litActionInfo.cid);
|
|
2208
|
+
console.log(" Position:", request.authMessage.positionId);
|
|
2209
|
+
console.log(" Amount:", request.authMessage.amount);
|
|
2210
|
+
console.log(" Address:", request.authMessage.withdrawalAddress);
|
|
2211
|
+
console.log(" Timestamp:", request.authMessage.timestamp);
|
|
2212
|
+
}
|
|
2213
|
+
// Get LIT client for execution
|
|
2214
|
+
const litClient = await this.clientManager.getClient({
|
|
2215
|
+
litNetwork: this.config.network,
|
|
2216
|
+
debug: this.config.debug,
|
|
2217
|
+
});
|
|
2218
|
+
// Determine chain and Bitcoin provider from chainId
|
|
2219
|
+
let chain;
|
|
2220
|
+
let bitcoinProviderUrl;
|
|
2221
|
+
switch (request.authMessage.chainId) {
|
|
2222
|
+
case 1: // Ethereum mainnet
|
|
2223
|
+
chain = "ethereum";
|
|
2224
|
+
bitcoinProviderUrl =
|
|
2225
|
+
process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
|
|
2226
|
+
break;
|
|
2227
|
+
case 11155111: // Sepolia testnet
|
|
2228
|
+
chain = "sepolia";
|
|
2229
|
+
bitcoinProviderUrl =
|
|
2230
|
+
process.env.BITCOIN_PROVIDER_URL ||
|
|
2231
|
+
"https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api/esplora";
|
|
2232
|
+
break;
|
|
2233
|
+
case 1337: // Hardhat local testnet (actual deployment chainId)
|
|
2234
|
+
case 31337: // Hardhat local testnet (standard default)
|
|
2235
|
+
chain = "hardhat";
|
|
2236
|
+
bitcoinProviderUrl =
|
|
2237
|
+
process.env.BITCOIN_PROVIDER_URL || "http://127.0.0.1:18443";
|
|
2238
|
+
break;
|
|
2239
|
+
default:
|
|
2240
|
+
throw new Error(`Unsupported chainId: ${request.authMessage.chainId}`);
|
|
2241
|
+
}
|
|
2242
|
+
// Override with custom Bitcoin RPC URL if provided
|
|
2243
|
+
if (request.customBitcoinRpcUrl) {
|
|
2244
|
+
bitcoinProviderUrl = request.customBitcoinRpcUrl;
|
|
2245
|
+
if (this.config.debug) {
|
|
2246
|
+
console.log(" Custom Bitcoin RPC URL:", request.customBitcoinRpcUrl);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
// Execute LIT Action
|
|
2250
|
+
const litActionParams = {
|
|
2251
|
+
chain,
|
|
2252
|
+
bitcoinProviderUrl,
|
|
2253
|
+
auth: {
|
|
2254
|
+
positionId: request.authMessage.positionId,
|
|
2255
|
+
timestamp: request.authMessage.timestamp,
|
|
2256
|
+
chainId: request.authMessage.chainId,
|
|
2257
|
+
destinationAddress: request.authMessage.withdrawalAddress,
|
|
2258
|
+
amount: request.authMessage.amount,
|
|
2259
|
+
action: request.authMessage.action,
|
|
2260
|
+
signature: request.userSignature,
|
|
2261
|
+
mode: request.authMessage.mode,
|
|
2262
|
+
},
|
|
2263
|
+
// Always pass contractAddresses (undefined in prod mode)
|
|
2264
|
+
contractAddresses: request.authMessage.contractAddresses,
|
|
2265
|
+
};
|
|
2266
|
+
// Add custom RPC URL for local development
|
|
2267
|
+
if (request.customRpcUrl) {
|
|
2268
|
+
litActionParams.customRpcUrl = request.customRpcUrl;
|
|
2269
|
+
if (this.config.debug) {
|
|
2270
|
+
console.log(" Custom RPC URL:", request.customRpcUrl);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
// PKP token ID should already be in decimal format from the registry
|
|
2274
|
+
// Don't normalize it - session-signature-manager will handle the conversion to hex
|
|
2275
|
+
// The registry stores token IDs as decimal strings, and session-signature-manager
|
|
2276
|
+
// expects decimal input which it then converts to hex for LitPKPResource
|
|
2277
|
+
const normalizedPkpTokenId = litActionInfo.pkp.tokenId;
|
|
2278
|
+
// Execute LIT Action
|
|
2279
|
+
// CRITICAL: Pass pkpTokenId for session signature PKP scoping (fixes signEcdsa timeout)
|
|
2280
|
+
// Use normalized decimal format for consistent conversion in session-signature-manager
|
|
2281
|
+
const result = await this.actionExecutor.executeAction({
|
|
2282
|
+
cid: litActionInfo.cid,
|
|
2283
|
+
pkpPublicKey: litActionInfo.pkp.publicKey,
|
|
2284
|
+
params: litActionParams,
|
|
2285
|
+
signer: this.config.signer,
|
|
2286
|
+
pkpTokenId: normalizedPkpTokenId, // Normalized to decimal string for consistent handling
|
|
2287
|
+
pkpEthAddress: litActionInfo.pkp.ethAddress, // Required for capacity credit delegation
|
|
2288
|
+
}, litClient);
|
|
2289
|
+
if (this.config.debug) {
|
|
2290
|
+
console.log("š„ LIT Action response:", {
|
|
2291
|
+
success: result.success,
|
|
2292
|
+
hasSignature: !!result.signatures,
|
|
2293
|
+
error: result.error,
|
|
2294
|
+
});
|
|
2295
|
+
console.log("š„ LIT Action result.response (raw):", result.response);
|
|
2296
|
+
}
|
|
2297
|
+
// Parse response if it's a string
|
|
2298
|
+
let responseData = result.response;
|
|
2299
|
+
if (typeof result.response === "string") {
|
|
2300
|
+
try {
|
|
2301
|
+
responseData = JSON.parse(result.response);
|
|
2302
|
+
if (this.config.debug) {
|
|
2303
|
+
console.log("š„ Parsed response data:", responseData);
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
catch (e) {
|
|
2307
|
+
if (this.config.debug) {
|
|
2308
|
+
console.error("ā Failed to parse response string:", e);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
// Return standardized response including UTXO data from Bitcoin network query
|
|
2313
|
+
const returnValue = {
|
|
2314
|
+
approved: responseData?.approved ?? false,
|
|
2315
|
+
signature: result.signatures
|
|
2316
|
+
? JSON.stringify(result.signatures)
|
|
2317
|
+
: undefined,
|
|
2318
|
+
actionHash: responseData?.actionHash,
|
|
2319
|
+
authorizedSpendsHash: responseData?.authorizedSpendsHash,
|
|
2320
|
+
ucdDebtHash: responseData?.ucdDebtHash,
|
|
2321
|
+
totalDeduction: responseData?.totalDeduction,
|
|
2322
|
+
remainingCollateral: responseData?.remainingCollateral,
|
|
2323
|
+
newCollateralRatioBps: responseData?.newCollateralRatioBps,
|
|
2324
|
+
destinationAddress: responseData?.destinationAddress,
|
|
2325
|
+
btcPrice: responseData?.btcPrice,
|
|
2326
|
+
timestamp: responseData?.timestamp,
|
|
2327
|
+
utxoTxid: responseData?.utxoTxid, // Real Bitcoin UTXO txid from network query
|
|
2328
|
+
utxoVout: responseData?.utxoVout, // Real Bitcoin UTXO vout from network query
|
|
2329
|
+
utxoSatoshis: responseData?.utxoSatoshis, // UTXO value for validation
|
|
2330
|
+
reason: responseData?.reason,
|
|
2331
|
+
failedStep: responseData?.failedStep,
|
|
2332
|
+
error: result.error,
|
|
2333
|
+
};
|
|
2334
|
+
if (this.config.debug) {
|
|
2335
|
+
console.log("š STANDALONE RETURN VALUE:", JSON.stringify(returnValue, null, 2));
|
|
2336
|
+
}
|
|
2337
|
+
return returnValue;
|
|
2338
|
+
}
|
|
2339
|
+
/**
|
|
2340
|
+
* Request payment authorization from Process Payment Validator LIT Action
|
|
2341
|
+
*
|
|
2342
|
+
* In SERVICE mode: Delegates to lit-ops-server
|
|
2343
|
+
* In STANDALONE mode: Executes LIT action locally
|
|
2344
|
+
*
|
|
2345
|
+
* @param request - Payment authorization request
|
|
2346
|
+
* @returns Payment authorization response from LIT Action
|
|
2347
|
+
*/
|
|
2348
|
+
async requestPaymentAuthorization(request) {
|
|
2349
|
+
// In SERVICE mode, delegate to lit-ops-server
|
|
2350
|
+
if (this.config.mode === "service") {
|
|
2351
|
+
return this.requestPaymentAuthorizationViaService(request);
|
|
2352
|
+
}
|
|
2353
|
+
return this.requestPaymentAuthorizationStandalone(request);
|
|
2354
|
+
}
|
|
2355
|
+
/**
|
|
2356
|
+
* Request payment authorization via lit-ops-server (SERVICE mode)
|
|
2357
|
+
*/
|
|
2358
|
+
async requestPaymentAuthorizationViaService(request) {
|
|
2359
|
+
if (!this.config.serviceEndpoint) {
|
|
2360
|
+
throw new Error("Service endpoint not configured for service mode");
|
|
2361
|
+
}
|
|
2362
|
+
const url = `${this.config.serviceEndpoint}/api/lit/payment/authorize`;
|
|
2363
|
+
if (this.config.debug) {
|
|
2364
|
+
console.log("š Requesting payment authorization via service:", url);
|
|
2365
|
+
console.log(" Position ID:", request.positionId);
|
|
2366
|
+
console.log(" Payment Amount:", request.paymentAmount);
|
|
2367
|
+
console.log(" Price Providers:", request.priceProviders);
|
|
2368
|
+
}
|
|
2369
|
+
const requestBody = {
|
|
2370
|
+
positionId: request.positionId,
|
|
2371
|
+
paymentAmount: request.paymentAmount,
|
|
2372
|
+
chainId: request.chainId,
|
|
2373
|
+
mode: request.mode,
|
|
2374
|
+
contractAddresses: request.contractAddresses,
|
|
2375
|
+
customRpcUrl: request.customRpcUrl,
|
|
2376
|
+
customBitcoinRpcUrl: request.customBitcoinRpcUrl,
|
|
2377
|
+
priceProviders: request.priceProviders,
|
|
2378
|
+
};
|
|
2379
|
+
try {
|
|
2380
|
+
const response = await fetch(url, {
|
|
2381
|
+
method: "POST",
|
|
2382
|
+
headers: {
|
|
2383
|
+
"Content-Type": "application/json",
|
|
2384
|
+
},
|
|
2385
|
+
body: JSON.stringify(requestBody),
|
|
2386
|
+
});
|
|
2387
|
+
if (!response.ok) {
|
|
2388
|
+
const errorText = await response.text();
|
|
2389
|
+
throw new Error(`Service error (${response.status}): ${errorText}`);
|
|
2390
|
+
}
|
|
2391
|
+
const envelope = await response.json();
|
|
2392
|
+
if (envelope.success && envelope.data) {
|
|
2393
|
+
return envelope.data;
|
|
2394
|
+
}
|
|
2395
|
+
else if (!envelope.success && envelope.error) {
|
|
2396
|
+
return {
|
|
2397
|
+
approved: false,
|
|
2398
|
+
error: envelope.error,
|
|
2399
|
+
reason: "Service returned error",
|
|
2400
|
+
};
|
|
2401
|
+
}
|
|
2402
|
+
return envelope;
|
|
2403
|
+
}
|
|
2404
|
+
catch (error) {
|
|
2405
|
+
if (this.config.debug) {
|
|
2406
|
+
console.error("ā Service payment authorization failed:", error);
|
|
2407
|
+
}
|
|
2408
|
+
return {
|
|
2409
|
+
approved: false,
|
|
2410
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2411
|
+
reason: "Service request failed",
|
|
2412
|
+
};
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
/**
|
|
2416
|
+
* Sign Bitcoin transaction for BTC withdrawal execution (Phase 2)
|
|
2417
|
+
*
|
|
2418
|
+
* Dual-mode method: Delegates to service endpoint or executes locally
|
|
2419
|
+
*/
|
|
2420
|
+
async signBTCTransaction(request) {
|
|
2421
|
+
// In SERVICE mode, delegate to lit-ops-server
|
|
2422
|
+
if (this.config.mode === "service") {
|
|
2423
|
+
if (this.config.debug) {
|
|
2424
|
+
console.log("š [signBTCTransaction] Using SERVICE mode - delegating to server");
|
|
2425
|
+
}
|
|
2426
|
+
return this.signBTCTransactionViaService(request);
|
|
2427
|
+
}
|
|
2428
|
+
// STANDALONE mode: Execute LIT action locally
|
|
2429
|
+
if (this.config.debug) {
|
|
2430
|
+
console.log("š§ [signBTCTransaction] Using STANDALONE mode - executing locally");
|
|
2431
|
+
}
|
|
2432
|
+
return this.signBTCTransactionStandalone(request);
|
|
2433
|
+
}
|
|
2434
|
+
/**
|
|
2435
|
+
* Sign Bitcoin transaction via lit-ops-server (SERVICE mode)
|
|
2436
|
+
*/
|
|
2437
|
+
async signBTCTransactionViaService(request) {
|
|
2438
|
+
if (!this.config.serviceEndpoint) {
|
|
2439
|
+
throw new Error("Service endpoint not configured for service mode");
|
|
2440
|
+
}
|
|
2441
|
+
const url = `${this.config.serviceEndpoint}/api/lit/btc/sign-transaction`;
|
|
2442
|
+
if (this.config.debug) {
|
|
2443
|
+
console.log("š Signing BTC transaction via service:", url);
|
|
2444
|
+
console.log(" Position ID:", request.auth.positionId);
|
|
2445
|
+
console.log(" UTXO:", `${request.auth.utxo.txid}:${request.auth.utxo.vout}`);
|
|
2446
|
+
console.log(" Network Fee:", request.auth.networkFee);
|
|
2447
|
+
}
|
|
2448
|
+
try {
|
|
2449
|
+
const response = await fetch(url, {
|
|
2450
|
+
method: "POST",
|
|
2451
|
+
headers: {
|
|
2452
|
+
"Content-Type": "application/json",
|
|
2453
|
+
},
|
|
2454
|
+
body: JSON.stringify(request),
|
|
2455
|
+
});
|
|
2456
|
+
if (!response.ok) {
|
|
2457
|
+
const errorText = await response.text();
|
|
2458
|
+
throw new Error(`Service error (${response.status}): ${errorText}`);
|
|
2459
|
+
}
|
|
2460
|
+
const envelope = await response.json();
|
|
2461
|
+
if (this.config.debug) {
|
|
2462
|
+
console.log("š„ Service response:", envelope);
|
|
2463
|
+
}
|
|
2464
|
+
return {
|
|
2465
|
+
success: envelope.success ?? false,
|
|
2466
|
+
unsignedTxHex: envelope.unsignedTxHex,
|
|
2467
|
+
sigHash: envelope.sigHash,
|
|
2468
|
+
signature: envelope.signature,
|
|
2469
|
+
pkpPublicKey: envelope.pkpPublicKey,
|
|
2470
|
+
pkpBtcAddress: envelope.pkpBtcAddress,
|
|
2471
|
+
destination: envelope.destination,
|
|
2472
|
+
userReceivesAmount: envelope.userReceivesAmount,
|
|
2473
|
+
networkFee: envelope.networkFee,
|
|
2474
|
+
changeAmount: envelope.changeAmount,
|
|
2475
|
+
utxo: envelope.utxo,
|
|
2476
|
+
authorization: envelope.authorization,
|
|
2477
|
+
timestamp: envelope.timestamp,
|
|
2478
|
+
action: envelope.action,
|
|
2479
|
+
error: envelope.error,
|
|
2480
|
+
failedStep: envelope.failedStep,
|
|
2481
|
+
};
|
|
2482
|
+
}
|
|
2483
|
+
catch (error) {
|
|
2484
|
+
console.error("ā Service request failed:", error);
|
|
2485
|
+
return {
|
|
2486
|
+
success: false,
|
|
2487
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
/**
|
|
2492
|
+
* Request payment authorization locally (STANDALONE mode)
|
|
2493
|
+
*/
|
|
2494
|
+
async requestPaymentAuthorizationStandalone(request) {
|
|
2495
|
+
// Get LIT Action info from registry
|
|
2496
|
+
const litActions = this.config.network === "datil"
|
|
2497
|
+
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
2498
|
+
: (() => {
|
|
2499
|
+
throw new Error("Unsupported LIT network");
|
|
2500
|
+
})();
|
|
2501
|
+
const litActionInfo = litActions.processPaymentValidator;
|
|
2502
|
+
if (!litActionInfo || !litActionInfo.cid || !litActionInfo.pkp) {
|
|
2503
|
+
throw new Error("Process payment validator LIT Action not found in registry");
|
|
2504
|
+
}
|
|
2505
|
+
if (this.config.debug) {
|
|
2506
|
+
console.log("š” Calling Process Payment Validator LIT Action:");
|
|
2507
|
+
console.log(" Network:", this.config.network);
|
|
2508
|
+
console.log(" CID:", litActionInfo.cid);
|
|
2509
|
+
console.log(" Position:", request.positionId);
|
|
2510
|
+
console.log(" Payment Amount:", request.paymentAmount);
|
|
2511
|
+
}
|
|
2512
|
+
// Verify PKP authorization before executing LIT Action
|
|
2513
|
+
if (litActionInfo.cid && litActionInfo.pkp.tokenId) {
|
|
2514
|
+
console.log("[LitOps] ======= PKP Authorization Check =======");
|
|
2515
|
+
console.log("[LitOps] PKP Token ID:", litActionInfo.pkp.tokenId);
|
|
2516
|
+
console.log("[LitOps] Lit Action CID:", litActionInfo.cid);
|
|
2517
|
+
try {
|
|
2518
|
+
const pkpAuthorizer = new pkp_authorizer_module_1.PKPAuthorizer({
|
|
2519
|
+
debug: this.config.debug,
|
|
2520
|
+
signer: this.config.signer,
|
|
2521
|
+
network: this.config.network, // Pass LIT network (e.g., 'datil') for PKP authorization check
|
|
2522
|
+
});
|
|
2523
|
+
const isPermitted = await pkpAuthorizer.isActionPermitted(litActionInfo.pkp.tokenId, litActionInfo.cid);
|
|
2524
|
+
console.log("[LitOps] PKP Authorization Status:", isPermitted ? "ā
AUTHORIZED" : "ā NOT AUTHORIZED");
|
|
2525
|
+
if (!isPermitted) {
|
|
2526
|
+
console.warn("[LitOps] ā ļø PKP is not authorized for this Lit Action CID");
|
|
2527
|
+
console.warn("[LitOps] This may cause signing to fail or timeout");
|
|
2528
|
+
console.warn("[LitOps] Session signatures may use wildcard authorization instead");
|
|
2529
|
+
}
|
|
2530
|
+
// Get comprehensive permission check for debugging
|
|
2531
|
+
const permissionCheck = await pkpAuthorizer.checkPermissions(litActionInfo.pkp.tokenId, litActionInfo.cid);
|
|
2532
|
+
console.log("[LitOps] Permitted Actions Count:", permissionCheck.permittedActions.length);
|
|
2533
|
+
console.log("[LitOps] CID in Permitted List:", permissionCheck.isPermitted);
|
|
2534
|
+
if (permissionCheck.permittedActions.length > 0) {
|
|
2535
|
+
console.log("[LitOps] Sample Permitted Actions:", permissionCheck.permittedActions.slice(0, 3));
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
catch (authError) {
|
|
2539
|
+
console.warn("[LitOps] ā ļø Failed to check PKP authorization:", authError instanceof Error ? authError.message : String(authError));
|
|
2540
|
+
console.warn("[LitOps] Continuing with execution - may use wildcard authorization");
|
|
2541
|
+
}
|
|
2542
|
+
console.log("[LitOps] ================================");
|
|
2543
|
+
}
|
|
2544
|
+
else {
|
|
2545
|
+
console.log("[LitOps] ā ļø Skipping PKP authorization check (CID or tokenId missing)");
|
|
2546
|
+
if (!litActionInfo.cid) {
|
|
2547
|
+
console.log("[LitOps] CID:", litActionInfo.cid);
|
|
2548
|
+
}
|
|
2549
|
+
if (!litActionInfo.pkp.tokenId) {
|
|
2550
|
+
console.log("[LitOps] PKP Token ID:", litActionInfo.pkp.tokenId);
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
// PKP token ID should already be in decimal format from the registry
|
|
2554
|
+
// Don't normalize it - session-signature-manager will handle the conversion to hex
|
|
2555
|
+
// The registry stores token IDs as decimal strings, and session-signature-manager
|
|
2556
|
+
// expects decimal input which it then converts to hex for LitPKPResource
|
|
2557
|
+
const normalizedPkpTokenId = litActionInfo.pkp.tokenId;
|
|
2558
|
+
// Get LIT client for execution
|
|
2559
|
+
const litClient = await this.clientManager.getClient({
|
|
2560
|
+
litNetwork: this.config.network,
|
|
2561
|
+
debug: this.config.debug,
|
|
2562
|
+
});
|
|
2563
|
+
// Determine chain and Bitcoin provider from chainId
|
|
2564
|
+
let chain;
|
|
2565
|
+
let bitcoinProviderUrl;
|
|
2566
|
+
switch (request.chainId) {
|
|
2567
|
+
case 1:
|
|
2568
|
+
chain = "ethereum";
|
|
2569
|
+
bitcoinProviderUrl =
|
|
2570
|
+
process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
|
|
2571
|
+
break;
|
|
2572
|
+
case 11155111:
|
|
2573
|
+
chain = "sepolia";
|
|
2574
|
+
bitcoinProviderUrl =
|
|
2575
|
+
process.env.BITCOIN_PROVIDER_URL ||
|
|
2576
|
+
"https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api/esplora";
|
|
2577
|
+
break;
|
|
2578
|
+
case 1337:
|
|
2579
|
+
case 31337:
|
|
2580
|
+
chain = "hardhat";
|
|
2581
|
+
bitcoinProviderUrl =
|
|
2582
|
+
process.env.BITCOIN_PROVIDER_URL || "http://127.0.0.1:18443";
|
|
2583
|
+
break;
|
|
2584
|
+
default:
|
|
2585
|
+
throw new Error(`Unsupported chainId: ${request.chainId}`);
|
|
2586
|
+
}
|
|
2587
|
+
if (request.customBitcoinRpcUrl) {
|
|
2588
|
+
bitcoinProviderUrl = request.customBitcoinRpcUrl;
|
|
2589
|
+
}
|
|
2590
|
+
// Support both legacy `contracts` (standalone) and newer `contractAddresses`
|
|
2591
|
+
const contractAddresses = request.contractAddresses ?? request.contracts;
|
|
2592
|
+
const litActionParams = {
|
|
2593
|
+
chain,
|
|
2594
|
+
bitcoinProviderUrl,
|
|
2595
|
+
positionId: request.positionId,
|
|
2596
|
+
paymentAmount: request.paymentAmount,
|
|
2597
|
+
...(contractAddresses && {
|
|
2598
|
+
contractAddresses,
|
|
2599
|
+
}),
|
|
2600
|
+
...(request.priceProviders && {
|
|
2601
|
+
priceProviders: request.priceProviders,
|
|
2602
|
+
}),
|
|
2603
|
+
};
|
|
2604
|
+
if (request.customRpcUrl) {
|
|
2605
|
+
litActionParams.customRpcUrl = request.customRpcUrl;
|
|
2606
|
+
}
|
|
2607
|
+
// Check if we should use local code execution
|
|
2608
|
+
// CRITICAL: If we have a registry CID, always use IPFS mode
|
|
2609
|
+
// Never use local code when we have a deployed registry CID
|
|
2610
|
+
const useLocalCode = this.config.litActionExecution === 'local' && !litActionInfo.cid;
|
|
2611
|
+
if (this.config.debug) {
|
|
2612
|
+
console.log("š [DEBUG] litActionExecution config:", this.config.litActionExecution);
|
|
2613
|
+
console.log("š [DEBUG] Registry CID available:", litActionInfo.cid);
|
|
2614
|
+
console.log("š [DEBUG] useLocalCode:", useLocalCode, "(ignored if registry CID exists)");
|
|
2615
|
+
}
|
|
2616
|
+
let result;
|
|
2617
|
+
if (useLocalCode) {
|
|
2618
|
+
// Only use local code if NO registry CID is available (shouldn't happen in production)
|
|
2619
|
+
// Read code from local dist file
|
|
2620
|
+
const fs = require('fs');
|
|
2621
|
+
const path = require('path');
|
|
2622
|
+
// Try multiple possible paths
|
|
2623
|
+
const possiblePaths = [
|
|
2624
|
+
path.join(__dirname, '../../lit-actions/dist/process-payment-validator.action.js'),
|
|
2625
|
+
path.join(process.cwd(), 'lit-actions/dist/process-payment-validator.action.js'),
|
|
2626
|
+
path.join(process.cwd(), '../lit-actions/dist/process-payment-validator.action.js'),
|
|
2627
|
+
];
|
|
2628
|
+
let codePath;
|
|
2629
|
+
for (const p of possiblePaths) {
|
|
2630
|
+
if (fs.existsSync(p)) {
|
|
2631
|
+
codePath = p;
|
|
2632
|
+
break;
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
if (!codePath) {
|
|
2636
|
+
throw new Error(`Local LIT action code not found. Tried: ${possiblePaths.join(', ')}. Please build lit-actions first.`);
|
|
2637
|
+
}
|
|
2638
|
+
const code = fs.readFileSync(codePath, 'utf8');
|
|
2639
|
+
if (this.config.debug) {
|
|
2640
|
+
console.log("š¦ Using LOCAL LIT Action code (not IPFS)");
|
|
2641
|
+
console.log(" Code path:", codePath);
|
|
2642
|
+
console.log(" Code size:", code.length, "bytes");
|
|
2643
|
+
}
|
|
2644
|
+
result = await this.executeActionFromCode(code, litActionInfo.pkp.publicKey, litActionParams, this.config.signer, normalizedPkpTokenId, // Normalized to decimal string for consistent handling
|
|
2645
|
+
litActionInfo.cid // Still provide CID for authorization validation
|
|
2646
|
+
);
|
|
2647
|
+
}
|
|
2648
|
+
else {
|
|
2649
|
+
// Always use IPFS mode when we have a registry CID
|
|
2650
|
+
// This ensures the Lit SDK uses the correct CID from the registry for authorization
|
|
2651
|
+
// Execute LIT Action (single attempt - retry logic is in SDK layer)
|
|
2652
|
+
// CRITICAL: Pass pkpTokenId for session signature PKP scoping (fixes signEcdsa timeout)
|
|
2653
|
+
// Use normalized decimal format for consistent conversion in session-signature-manager
|
|
2654
|
+
result = await this.actionExecutor.executeAction({
|
|
2655
|
+
cid: litActionInfo.cid, // Use registry CID
|
|
2656
|
+
pkpPublicKey: litActionInfo.pkp.publicKey,
|
|
2657
|
+
params: litActionParams,
|
|
2658
|
+
signer: this.config.signer,
|
|
2659
|
+
pkpTokenId: normalizedPkpTokenId, // Normalized to decimal string for consistent handling
|
|
2660
|
+
pkpEthAddress: litActionInfo.pkp.ethAddress, // Required for capacity credit delegation
|
|
2661
|
+
}, litClient);
|
|
2662
|
+
}
|
|
2663
|
+
let responseData = result.response;
|
|
2664
|
+
if (typeof result.response === "string") {
|
|
2665
|
+
try {
|
|
2666
|
+
responseData = JSON.parse(result.response);
|
|
2667
|
+
}
|
|
2668
|
+
catch (e) {
|
|
2669
|
+
// Ignore parse errors
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
// Handle signature: prefer LIT SDK format (result.signatures), fall back to responseData.signature
|
|
2673
|
+
let signature;
|
|
2674
|
+
if (result.signatures) {
|
|
2675
|
+
signature = JSON.stringify(result.signatures);
|
|
2676
|
+
}
|
|
2677
|
+
else if (responseData?.signature) {
|
|
2678
|
+
signature = responseData.signature;
|
|
2679
|
+
}
|
|
2680
|
+
return {
|
|
2681
|
+
approved: responseData?.approved ?? false,
|
|
2682
|
+
signature,
|
|
2683
|
+
btcPrice: responseData?.btcPrice,
|
|
2684
|
+
paymentAmount: responseData?.paymentAmount,
|
|
2685
|
+
timestamp: responseData?.timestamp,
|
|
2686
|
+
reason: responseData?.reason,
|
|
2687
|
+
failedStep: responseData?.failedStep,
|
|
2688
|
+
error: result.error,
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
/**
|
|
2692
|
+
* Sign Bitcoin transaction locally (STANDALONE mode)
|
|
2693
|
+
*/
|
|
2694
|
+
async signBTCTransactionStandalone(request) {
|
|
2695
|
+
// Get LIT Action info from registry
|
|
2696
|
+
const litActions = this.config.network === "datil"
|
|
2697
|
+
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
2698
|
+
: (() => {
|
|
2699
|
+
throw new Error("Unsupported LIT network");
|
|
2700
|
+
})();
|
|
2701
|
+
const litActionInfo = litActions.btcTransactionSigner;
|
|
2702
|
+
if (!litActionInfo || !litActionInfo.cid) {
|
|
2703
|
+
throw new Error("BTC transaction signer LIT Action not found in registry");
|
|
2704
|
+
}
|
|
2705
|
+
if (this.config.debug) {
|
|
2706
|
+
console.log("š” Calling BTC Transaction Signer LIT Action:");
|
|
2707
|
+
console.log(" Network:", this.config.network);
|
|
2708
|
+
console.log(" CID:", litActionInfo.cid);
|
|
2709
|
+
console.log(" Position:", request.auth.positionId);
|
|
2710
|
+
console.log(" UTXO:", `${request.auth.utxo.txid}:${request.auth.utxo.vout}`);
|
|
2711
|
+
console.log(" Network Fee:", request.auth.networkFee);
|
|
2712
|
+
}
|
|
2713
|
+
// Get LIT client for execution
|
|
2714
|
+
const litClient = await this.clientManager.getClient({
|
|
2715
|
+
litNetwork: this.config.network,
|
|
2716
|
+
debug: this.config.debug,
|
|
2717
|
+
});
|
|
2718
|
+
// Build LIT Action parameters
|
|
2719
|
+
// Determine Bitcoin provider URL based on network
|
|
2720
|
+
let bitcoinProviderUrl;
|
|
2721
|
+
const chainId = request.auth.chainId;
|
|
2722
|
+
switch (chainId) {
|
|
2723
|
+
case 1: // Ethereum mainnet
|
|
2724
|
+
bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
|
|
2725
|
+
break;
|
|
2726
|
+
case 11155111: // Sepolia testnet
|
|
2727
|
+
bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api";
|
|
2728
|
+
break;
|
|
2729
|
+
case 1337: // Hardhat local testnet (actual deployment chainId)
|
|
2730
|
+
case 31337: // Hardhat local testnet (standard default)
|
|
2731
|
+
bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "http://127.0.0.1:18443";
|
|
2732
|
+
break;
|
|
2733
|
+
default:
|
|
2734
|
+
throw new Error(`Unsupported chainId: ${chainId}`);
|
|
2735
|
+
}
|
|
2736
|
+
// Override with custom Bitcoin RPC URL if provided (for local development with ngrok)
|
|
2737
|
+
if (request.customBitcoinRpcUrl) {
|
|
2738
|
+
bitcoinProviderUrl = request.customBitcoinRpcUrl;
|
|
2739
|
+
if (this.config.debug) {
|
|
2740
|
+
console.log(" Custom Bitcoin RPC URL (override):", request.customBitcoinRpcUrl);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
const litActionParams = {
|
|
2744
|
+
chain: request.chain,
|
|
2745
|
+
bitcoinNetwork: request.bitcoinNetwork,
|
|
2746
|
+
bitcoinProviderUrl, // For Bitcoin UTXO queries
|
|
2747
|
+
auth: request.auth,
|
|
2748
|
+
publicKey: request.publicKey,
|
|
2749
|
+
contracts: request.contracts,
|
|
2750
|
+
};
|
|
2751
|
+
// Add custom EVM RPC URL for local development (Hardhat)
|
|
2752
|
+
if (request.customRpcUrl) {
|
|
2753
|
+
litActionParams.customRpcUrl = request.customRpcUrl;
|
|
2754
|
+
if (this.config.debug) {
|
|
2755
|
+
console.log(" Custom EVM RPC URL:", request.customRpcUrl);
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
if (this.config.debug) {
|
|
2759
|
+
console.log(" Bitcoin Provider URL:", bitcoinProviderUrl);
|
|
2760
|
+
}
|
|
2761
|
+
// Execute LIT Action
|
|
2762
|
+
const result = await this.actionExecutor.executeAction({
|
|
2763
|
+
cid: litActionInfo.cid,
|
|
2764
|
+
pkpPublicKey: request.publicKey,
|
|
2765
|
+
params: litActionParams,
|
|
2766
|
+
signer: this.config.signer,
|
|
2767
|
+
}, litClient);
|
|
2768
|
+
if (this.config.debug) {
|
|
2769
|
+
console.log("š„ LIT Action response:", {
|
|
2770
|
+
success: result.success,
|
|
2771
|
+
hasSignature: !!result.signatures,
|
|
2772
|
+
error: result.error,
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
// Parse response if it's a string
|
|
2776
|
+
let responseData = result.response;
|
|
2777
|
+
if (typeof result.response === "string") {
|
|
2778
|
+
try {
|
|
2779
|
+
responseData = JSON.parse(result.response);
|
|
2780
|
+
if (this.config.debug) {
|
|
2781
|
+
console.log("š„ Parsed response data:", responseData);
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
catch (e) {
|
|
2785
|
+
if (this.config.debug) {
|
|
2786
|
+
console.error("ā Failed to parse response string:", e);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
// Extract combined signature from LIT SDK result
|
|
2791
|
+
// LIT SDK returns signatures in result.signatures.btcTxSig after combination
|
|
2792
|
+
let combinedSignature;
|
|
2793
|
+
if (result.signatures && typeof result.signatures === 'object') {
|
|
2794
|
+
const btcTxSig = result.signatures.btcTxSig;
|
|
2795
|
+
if (btcTxSig && btcTxSig.signature) {
|
|
2796
|
+
// LIT SDK combined signature
|
|
2797
|
+
combinedSignature = btcTxSig.signature;
|
|
2798
|
+
if (this.config.debug && combinedSignature) {
|
|
2799
|
+
console.log("ā
Extracted combined signature from LIT SDK:", {
|
|
2800
|
+
signatureLength: combinedSignature.length,
|
|
2801
|
+
signatureStart: combinedSignature.substring(0, 20) + "..."
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
// Return standardized response
|
|
2807
|
+
return {
|
|
2808
|
+
success: responseData?.success ?? false,
|
|
2809
|
+
unsignedTxHex: responseData?.unsignedTxHex,
|
|
2810
|
+
sigHash: responseData?.sigHash,
|
|
2811
|
+
signature: combinedSignature || responseData?.signature,
|
|
2812
|
+
pkpPublicKey: responseData?.pkpPublicKey,
|
|
2813
|
+
pkpBtcAddress: responseData?.pkpBtcAddress,
|
|
2814
|
+
destination: responseData?.destination,
|
|
2815
|
+
userReceivesAmount: responseData?.userReceivesAmount,
|
|
2816
|
+
networkFee: responseData?.networkFee,
|
|
2817
|
+
changeAmount: responseData?.changeAmount,
|
|
2818
|
+
utxo: responseData?.utxo,
|
|
2819
|
+
authorization: responseData?.authorization,
|
|
2820
|
+
timestamp: responseData?.timestamp,
|
|
2821
|
+
action: responseData?.action,
|
|
2822
|
+
error: result.error || responseData?.error,
|
|
2823
|
+
failedStep: responseData?.failedStep,
|
|
2824
|
+
};
|
|
2825
|
+
}
|
|
1517
2826
|
/**
|
|
1518
2827
|
* Get trustless BTC price from Price Oracle LIT Action
|
|
1519
2828
|
*
|
|
@@ -1530,7 +2839,9 @@ class LitOps {
|
|
|
1530
2839
|
// Get LIT Action info from registry
|
|
1531
2840
|
const litActions = (this.config.network === "datil"
|
|
1532
2841
|
? dh_lit_actions_1.DH_LIT_ACTIONS_DATIL
|
|
1533
|
-
:
|
|
2842
|
+
: (() => {
|
|
2843
|
+
throw new Error("Unsupported LIT network");
|
|
2844
|
+
})());
|
|
1534
2845
|
console.log("litActions in getActions", litActions);
|
|
1535
2846
|
const litActionInfo = litActions.priceOracle;
|
|
1536
2847
|
if (!litActionInfo || !litActionInfo.cid) {
|