@gvnrdao/dh-lit-ops 0.0.108 ā 0.0.182
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/interfaces/chunks/config.d.ts +0 -6
- package/dist/interfaces/chunks/config.d.ts.map +1 -1
- package/dist/interfaces/chunks/lit-action-execution.d.ts +11 -0
- package/dist/interfaces/chunks/lit-action-execution.d.ts.map +1 -1
- package/dist/modules/action-executor.module.d.ts.map +1 -1
- package/dist/modules/action-executor.module.js +23 -103
- 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 +34 -148
- package/dist/modules/auth-manager.module.js.map +1 -1
- package/dist/modules/client-manager.module.d.ts.map +1 -1
- package/dist/modules/client-manager.module.js.map +1 -1
- package/dist/modules/lit-ops.module.d.ts +8 -118
- package/dist/modules/lit-ops.module.d.ts.map +1 -1
- package/dist/modules/lit-ops.module.js +98 -823
- package/dist/modules/lit-ops.module.js.map +1 -1
- package/dist/modules/pkp-minter.module.d.ts +0 -1
- package/dist/modules/pkp-minter.module.d.ts.map +1 -1
- package/dist/modules/pkp-minter.module.js +98 -106
- 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 +31 -67
- package/dist/modules/session-signature-manager.module.js.map +1 -1
- package/package.json +3 -4
|
@@ -415,29 +415,6 @@ 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
|
-
}
|
|
441
418
|
/**
|
|
442
419
|
* Execute a LIT Action from IPFS
|
|
443
420
|
*/
|
|
@@ -653,7 +630,7 @@ class LitOps {
|
|
|
653
630
|
* @param signer - The wallet to use for session signatures
|
|
654
631
|
* @returns PKP validation result with signature verification
|
|
655
632
|
*/
|
|
656
|
-
async validatePKPSecurity(targetPkpTokenId, expectedCid, signerPkp, signer
|
|
633
|
+
async validatePKPSecurity(targetPkpTokenId, expectedCid, signerPkp, signer) {
|
|
657
634
|
console.log(`š LIT-OPS TRACE: validatePKPSecurity ENTRY`);
|
|
658
635
|
console.log(` - targetPkpTokenId: "${targetPkpTokenId}"`);
|
|
659
636
|
console.log(` - targetPkpTokenId type: ${typeof targetPkpTokenId}`);
|
|
@@ -675,54 +652,25 @@ class LitOps {
|
|
|
675
652
|
: (() => {
|
|
676
653
|
throw new Error("Unsupported LIT network");
|
|
677
654
|
})()).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);
|
|
682
655
|
if (this.config.debug) {
|
|
683
|
-
console.log(` PKP Validator CID
|
|
684
|
-
console.log(` Validator CID (hex): ${validatorCidHex}`);
|
|
685
|
-
console.log(` PKP's expected CID (hex): ${expectedCid}`);
|
|
656
|
+
console.log(` PKP Validator CID: ${pkpValidatorCid}`);
|
|
686
657
|
}
|
|
687
658
|
// Execute PKP Validator LIT Action
|
|
688
|
-
// NOTE:
|
|
689
|
-
//
|
|
690
|
-
//
|
|
691
|
-
//
|
|
692
|
-
// Normalize signer PKP token ID to hex format for session scoping
|
|
693
|
-
// NOTE: signerPkp IS the validator PKP (passed from call site)
|
|
694
|
-
let sessionScopedSignerTokenId = signerPkp.tokenId;
|
|
695
|
-
try {
|
|
696
|
-
const normalizedHex = BigInt(signerPkp.tokenId)
|
|
697
|
-
.toString(16)
|
|
698
|
-
.padStart(64, "0");
|
|
699
|
-
sessionScopedSignerTokenId = `0x${normalizedHex}`;
|
|
700
|
-
}
|
|
701
|
-
catch (tokenErr) {
|
|
702
|
-
console.warn("ā ļø Failed to normalize signer PKP tokenId to hex, using raw value", tokenErr);
|
|
703
|
-
}
|
|
704
|
-
if (this.config.debug) {
|
|
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}`);
|
|
708
|
-
}
|
|
659
|
+
// NOTE: We do NOT pass the validator PKP token ID here because the validator
|
|
660
|
+
// performs READ-ONLY operations (no signing). Passing undefined for pkpTokenId
|
|
661
|
+
// will skip adding LitPKPResource to the session signature, which is correct
|
|
662
|
+
// for burned/immutable validator PKPs that can't sign via session signatures.
|
|
709
663
|
console.log(`\nš LIT-OPS TRACE: About to call executeActionFromCID with jsParams:`);
|
|
710
664
|
console.log(` - targetPkpTokenId: "${targetPkpTokenId}"`);
|
|
711
665
|
console.log(` - expectedCid: "${expectedCid}"`);
|
|
712
|
-
|
|
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
|
-
{
|
|
666
|
+
const litResult = await this.executeActionFromCID(pkpValidatorCid, signerPkp.publicKey, {
|
|
718
667
|
targetPkpTokenId,
|
|
719
|
-
expectedCid, //
|
|
720
|
-
certificationCid: validatorCidHex, // Validator's CID (for signature message) - from registry
|
|
668
|
+
expectedCid, // Expected to be in hex format
|
|
721
669
|
message: `PKP validation: ${Date.now()}`,
|
|
722
670
|
// Ensure the LIT Action knows which network (datil vs datil-test)
|
|
723
671
|
network: this.config.network,
|
|
724
|
-
}, signer
|
|
725
|
-
|
|
672
|
+
}, signer
|
|
673
|
+
// Intentionally NOT passing signerPkp.tokenId - validator is read-only
|
|
726
674
|
);
|
|
727
675
|
if (this.config.debug) {
|
|
728
676
|
console.log(` LIT Action Success: ${litResult.success}`);
|
|
@@ -781,7 +729,7 @@ class LitOps {
|
|
|
781
729
|
console.log(" š Verifying signature authenticity...");
|
|
782
730
|
}
|
|
783
731
|
try {
|
|
784
|
-
// Compute
|
|
732
|
+
// Compute PKP address from public key (publicKey already includes 0x prefix)
|
|
785
733
|
const cleanPublicKey = signerPkp.publicKey.startsWith("0x")
|
|
786
734
|
? signerPkp.publicKey
|
|
787
735
|
: `0x${signerPkp.publicKey}`;
|
|
@@ -929,24 +877,10 @@ class LitOps {
|
|
|
929
877
|
litActionCids: litActionCids,
|
|
930
878
|
}),
|
|
931
879
|
}, 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
|
-
}
|
|
945
880
|
if (!response.ok) {
|
|
946
|
-
|
|
947
|
-
const errorDetails = result.error || result.message || response.statusText;
|
|
948
|
-
throw new Error(`Service request failed: ${response.status} ${errorDetails}`);
|
|
881
|
+
throw new Error(`Service request failed: ${response.status} ${response.statusText}`);
|
|
949
882
|
}
|
|
883
|
+
const result = (await response.json());
|
|
950
884
|
const duration = Date.now() - startTime;
|
|
951
885
|
// The service may wrap the LitOps result as { success, data }
|
|
952
886
|
// Unwrap if needed to maintain a stable SDK return shape
|
|
@@ -1138,16 +1072,8 @@ class LitOps {
|
|
|
1138
1072
|
console.log(` - pkpTokenId startsWith '0x': ${pkpData.tokenId.startsWith("0x")}`);
|
|
1139
1073
|
console.log(` - litActionCidHex (expectedCid): "${litActionCidHex}"`);
|
|
1140
1074
|
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;
|
|
1145
1075
|
validationResult = await this.validatePKPSecurity(pkpData.tokenId, litActionCidHex, // Pass hex format CID
|
|
1146
|
-
validatorPkp, signer
|
|
1147
|
-
validatorVersion,
|
|
1148
|
-
ethRpcUrl,
|
|
1149
|
-
pkpValidationRegistry,
|
|
1150
|
-
});
|
|
1076
|
+
validatorPkp, signer);
|
|
1151
1077
|
// If validation succeeds, break out of retry loop
|
|
1152
1078
|
if (validationResult.success) {
|
|
1153
1079
|
if (this.config.debug && attempt > 1) {
|
|
@@ -1569,19 +1495,10 @@ class LitOps {
|
|
|
1569
1495
|
if (!litActionInfo || !litActionInfo.cid || !litActionInfo.pkp) {
|
|
1570
1496
|
throw new Error("UCD mint validator LIT Action not found in registry");
|
|
1571
1497
|
}
|
|
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;
|
|
1578
1498
|
if (this.config.debug) {
|
|
1579
1499
|
console.log("š” Calling UCD Mint Validator LIT Action:");
|
|
1580
1500
|
console.log(" Network:", this.config.network);
|
|
1581
|
-
console.log("
|
|
1582
|
-
console.log(" Validator PKP Token ID:", validatorPkpTokenId);
|
|
1583
|
-
console.log(" Validator PKP Public Key:", validatorPkpPublicKey);
|
|
1584
|
-
console.log(" Validator PKP ETH Address:", validatorPkpEthAddress);
|
|
1501
|
+
console.log(" CID:", litActionInfo.cid);
|
|
1585
1502
|
console.log(" Position:", request.authMessage.positionId);
|
|
1586
1503
|
console.log(" Amount:", request.authMessage.amount);
|
|
1587
1504
|
console.log(" Timestamp:", request.authMessage.timestamp);
|
|
@@ -1604,7 +1521,7 @@ class LitOps {
|
|
|
1604
1521
|
chain = "sepolia";
|
|
1605
1522
|
bitcoinProviderUrl =
|
|
1606
1523
|
process.env.BITCOIN_PROVIDER_URL ||
|
|
1607
|
-
"https://diamond-hands-btc-faucet-
|
|
1524
|
+
"https://diamond-hands-btc-faucet-jw-b86e9451a147.herokuapp.com/api";
|
|
1608
1525
|
break;
|
|
1609
1526
|
case 1337: // Hardhat local testnet (actual deployment chainId)
|
|
1610
1527
|
case 31337: // Hardhat local testnet (standard default)
|
|
@@ -1638,14 +1555,10 @@ class LitOps {
|
|
|
1638
1555
|
mode: request.authMessage.mode,
|
|
1639
1556
|
},
|
|
1640
1557
|
amount: request.authMessage.amount,
|
|
1641
|
-
//
|
|
1558
|
+
// Contracts must be at top level to become globalThis.contractAddresses in LIT Action
|
|
1642
1559
|
...(request.authMessage.contractAddresses && {
|
|
1643
1560
|
contractAddresses: request.authMessage.contractAddresses,
|
|
1644
1561
|
}),
|
|
1645
|
-
// Price providers with API keys for faster price fetching
|
|
1646
|
-
...(request.priceProviders && {
|
|
1647
|
-
priceProviders: request.priceProviders,
|
|
1648
|
-
}),
|
|
1649
1562
|
};
|
|
1650
1563
|
// Add custom RPC URL for local development (ngrok tunnels)
|
|
1651
1564
|
if (request.customRpcUrl) {
|
|
@@ -1654,115 +1567,15 @@ class LitOps {
|
|
|
1654
1567
|
console.log(" Custom RPC URL:", request.customRpcUrl);
|
|
1655
1568
|
}
|
|
1656
1569
|
}
|
|
1657
|
-
//
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
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
|
-
}
|
|
1570
|
+
// Execute LIT Action (single attempt - retry logic is in SDK layer)
|
|
1571
|
+
const result = await this.actionExecutor.executeAction({
|
|
1572
|
+
cid: litActionInfo.cid,
|
|
1573
|
+
pkpPublicKey: litActionInfo.pkp.publicKey,
|
|
1574
|
+
params: litActionParams,
|
|
1575
|
+
signer: this.config.signer,
|
|
1576
|
+
priceProviders: request.priceProviders, // Pass price provider API keys (standalone mode)
|
|
1577
|
+
}, litClient);
|
|
1763
1578
|
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);
|
|
1766
1579
|
console.log("š„ LIT Action response:", {
|
|
1767
1580
|
success: result.success,
|
|
1768
1581
|
hasSignature: !!result.signatures,
|
|
@@ -1802,8 +1615,6 @@ class LitOps {
|
|
|
1802
1615
|
newCollateral: responseData?.newCollateral,
|
|
1803
1616
|
btcPrice: responseData?.btcPrice,
|
|
1804
1617
|
authorizedSpendsHash: responseData?.authorizedSpendsHash,
|
|
1805
|
-
ucdDebtHash: responseData?.ucdDebtHash,
|
|
1806
|
-
contractBundleHash: responseData?.contractBundleHash,
|
|
1807
1618
|
timestamp: responseData?.timestamp,
|
|
1808
1619
|
reason: responseData?.reason,
|
|
1809
1620
|
failedStep: responseData?.failedStep,
|
|
@@ -1816,298 +1627,6 @@ class LitOps {
|
|
|
1816
1627
|
}
|
|
1817
1628
|
return returnValue;
|
|
1818
1629
|
}
|
|
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
1630
|
/**
|
|
2112
1631
|
* Request BTC withdrawal authorization (dual-mode)
|
|
2113
1632
|
*
|
|
@@ -2135,7 +1654,7 @@ class LitOps {
|
|
|
2135
1654
|
if (!this.config.serviceEndpoint) {
|
|
2136
1655
|
throw new Error("Service endpoint not configured for service mode");
|
|
2137
1656
|
}
|
|
2138
|
-
const url = `${this.config.serviceEndpoint}/api/lit/
|
|
1657
|
+
const url = `${this.config.serviceEndpoint}/api/lit/withdraw-btc/authorize`;
|
|
2139
1658
|
if (this.config.debug) {
|
|
2140
1659
|
console.log("š Requesting withdrawal authorization via service:", url);
|
|
2141
1660
|
console.log(" Position ID:", request.authMessage.positionId);
|
|
@@ -2143,13 +1662,20 @@ class LitOps {
|
|
|
2143
1662
|
console.log(" Address:", request.authMessage.withdrawalAddress);
|
|
2144
1663
|
}
|
|
2145
1664
|
try {
|
|
1665
|
+
// Transform authMessage: SDK uses withdrawalAddress, server expects destinationAddress
|
|
1666
|
+
const transformedAuthMessage = {
|
|
1667
|
+
...request.authMessage,
|
|
1668
|
+
destinationAddress: request.authMessage.withdrawalAddress,
|
|
1669
|
+
};
|
|
1670
|
+
// Remove withdrawalAddress from the transformed message
|
|
1671
|
+
delete transformedAuthMessage.withdrawalAddress;
|
|
2146
1672
|
const response = await fetch(url, {
|
|
2147
1673
|
method: "POST",
|
|
2148
1674
|
headers: {
|
|
2149
1675
|
"Content-Type": "application/json",
|
|
2150
1676
|
},
|
|
2151
1677
|
body: JSON.stringify({
|
|
2152
|
-
authMessage:
|
|
1678
|
+
authMessage: transformedAuthMessage,
|
|
2153
1679
|
userSignature: request.userSignature,
|
|
2154
1680
|
customRpcUrl: request.customRpcUrl,
|
|
2155
1681
|
customBitcoinRpcUrl: request.customBitcoinRpcUrl,
|
|
@@ -2163,19 +1689,27 @@ class LitOps {
|
|
|
2163
1689
|
if (this.config.debug) {
|
|
2164
1690
|
console.log("š„ Service response:", envelope);
|
|
2165
1691
|
}
|
|
1692
|
+
// Extract data from envelope (server wraps in { success, data } structure)
|
|
1693
|
+
const result = envelope.data || envelope;
|
|
2166
1694
|
// Return the result from service
|
|
2167
1695
|
return {
|
|
2168
|
-
approved:
|
|
2169
|
-
signature:
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
1696
|
+
approved: result.approved ?? false,
|
|
1697
|
+
signature: result.signature,
|
|
1698
|
+
actionHash: result.actionHash,
|
|
1699
|
+
authorizedSpendsHash: result.authorizedSpendsHash,
|
|
1700
|
+
ucdDebtHash: result.ucdDebtHash,
|
|
1701
|
+
totalDeduction: result.totalDeduction,
|
|
1702
|
+
remainingCollateral: result.remainingCollateral,
|
|
1703
|
+
newCollateralRatioBps: result.newCollateralRatioBps,
|
|
1704
|
+
destinationAddress: result.destinationAddress,
|
|
1705
|
+
btcPrice: result.btcPrice,
|
|
1706
|
+
timestamp: result.timestamp,
|
|
1707
|
+
utxoTxid: result.utxoTxid,
|
|
1708
|
+
utxoVout: result.utxoVout,
|
|
1709
|
+
utxoSatoshis: result.utxoSatoshis,
|
|
1710
|
+
reason: result.reason,
|
|
1711
|
+
failedStep: result.failedStep,
|
|
1712
|
+
error: result.error,
|
|
2179
1713
|
};
|
|
2180
1714
|
}
|
|
2181
1715
|
catch (error) {
|
|
@@ -2228,7 +1762,7 @@ class LitOps {
|
|
|
2228
1762
|
chain = "sepolia";
|
|
2229
1763
|
bitcoinProviderUrl =
|
|
2230
1764
|
process.env.BITCOIN_PROVIDER_URL ||
|
|
2231
|
-
"https://diamond-hands-btc-faucet-
|
|
1765
|
+
"https://diamond-hands-btc-faucet-jw-b86e9451a147.herokuapp.com/api";
|
|
2232
1766
|
break;
|
|
2233
1767
|
case 1337: // Hardhat local testnet (actual deployment chainId)
|
|
2234
1768
|
case 31337: // Hardhat local testnet (standard default)
|
|
@@ -2270,21 +1804,12 @@ class LitOps {
|
|
|
2270
1804
|
console.log(" Custom RPC URL:", request.customRpcUrl);
|
|
2271
1805
|
}
|
|
2272
1806
|
}
|
|
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
1807
|
// 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
1808
|
const result = await this.actionExecutor.executeAction({
|
|
2282
1809
|
cid: litActionInfo.cid,
|
|
2283
1810
|
pkpPublicKey: litActionInfo.pkp.publicKey,
|
|
2284
1811
|
params: litActionParams,
|
|
2285
1812
|
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
1813
|
}, litClient);
|
|
2289
1814
|
if (this.config.debug) {
|
|
2290
1815
|
console.log("š„ LIT Action response:", {
|
|
@@ -2336,82 +1861,6 @@ class LitOps {
|
|
|
2336
1861
|
}
|
|
2337
1862
|
return returnValue;
|
|
2338
1863
|
}
|
|
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
1864
|
/**
|
|
2416
1865
|
* Sign Bitcoin transaction for BTC withdrawal execution (Phase 2)
|
|
2417
1866
|
*
|
|
@@ -2461,23 +1910,25 @@ class LitOps {
|
|
|
2461
1910
|
if (this.config.debug) {
|
|
2462
1911
|
console.log("š„ Service response:", envelope);
|
|
2463
1912
|
}
|
|
1913
|
+
// Extract data from envelope (server wraps in { success, data } structure)
|
|
1914
|
+
const result = envelope.data || envelope;
|
|
2464
1915
|
return {
|
|
2465
|
-
success:
|
|
2466
|
-
unsignedTxHex:
|
|
2467
|
-
sigHash:
|
|
2468
|
-
signature:
|
|
2469
|
-
pkpPublicKey:
|
|
2470
|
-
pkpBtcAddress:
|
|
2471
|
-
destination:
|
|
2472
|
-
userReceivesAmount:
|
|
2473
|
-
networkFee:
|
|
2474
|
-
changeAmount:
|
|
2475
|
-
utxo:
|
|
2476
|
-
authorization:
|
|
2477
|
-
timestamp:
|
|
2478
|
-
action:
|
|
2479
|
-
error:
|
|
2480
|
-
failedStep:
|
|
1916
|
+
success: result.success ?? false,
|
|
1917
|
+
unsignedTxHex: result.unsignedTxHex,
|
|
1918
|
+
sigHash: result.sigHash,
|
|
1919
|
+
signature: result.signature,
|
|
1920
|
+
pkpPublicKey: result.pkpPublicKey,
|
|
1921
|
+
pkpBtcAddress: result.pkpBtcAddress,
|
|
1922
|
+
destination: result.destination,
|
|
1923
|
+
userReceivesAmount: result.userReceivesAmount,
|
|
1924
|
+
networkFee: result.networkFee,
|
|
1925
|
+
changeAmount: result.changeAmount,
|
|
1926
|
+
utxo: result.utxo,
|
|
1927
|
+
authorization: result.authorization,
|
|
1928
|
+
timestamp: result.timestamp,
|
|
1929
|
+
action: result.action,
|
|
1930
|
+
error: result.error,
|
|
1931
|
+
failedStep: result.failedStep,
|
|
2481
1932
|
};
|
|
2482
1933
|
}
|
|
2483
1934
|
catch (error) {
|
|
@@ -2488,206 +1939,6 @@ class LitOps {
|
|
|
2488
1939
|
};
|
|
2489
1940
|
}
|
|
2490
1941
|
}
|
|
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
1942
|
/**
|
|
2692
1943
|
* Sign Bitcoin transaction locally (STANDALONE mode)
|
|
2693
1944
|
*/
|
|
@@ -2724,7 +1975,7 @@ class LitOps {
|
|
|
2724
1975
|
bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
|
|
2725
1976
|
break;
|
|
2726
1977
|
case 11155111: // Sepolia testnet
|
|
2727
|
-
bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "https://diamond-hands-btc-faucet-
|
|
1978
|
+
bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "https://diamond-hands-btc-faucet-jw-b86e9451a147.herokuapp.com/api";
|
|
2728
1979
|
break;
|
|
2729
1980
|
case 1337: // Hardhat local testnet (actual deployment chainId)
|
|
2730
1981
|
case 31337: // Hardhat local testnet (standard default)
|
|
@@ -2746,7 +1997,7 @@ class LitOps {
|
|
|
2746
1997
|
bitcoinProviderUrl, // For Bitcoin UTXO queries
|
|
2747
1998
|
auth: request.auth,
|
|
2748
1999
|
publicKey: request.publicKey,
|
|
2749
|
-
|
|
2000
|
+
contractAddresses: request.contractAddresses,
|
|
2750
2001
|
};
|
|
2751
2002
|
// Add custom EVM RPC URL for local development (Hardhat)
|
|
2752
2003
|
if (request.customRpcUrl) {
|
|
@@ -2771,6 +2022,30 @@ class LitOps {
|
|
|
2771
2022
|
hasSignature: !!result.signatures,
|
|
2772
2023
|
error: result.error,
|
|
2773
2024
|
});
|
|
2025
|
+
// Log per-node debug information if available
|
|
2026
|
+
if (result.debug) {
|
|
2027
|
+
console.log("\nš PER-NODE DEBUG INFORMATION:");
|
|
2028
|
+
console.log("=====================================");
|
|
2029
|
+
const debugInfo = result.debug;
|
|
2030
|
+
if (debugInfo.allNodeResponses) {
|
|
2031
|
+
console.log("\nš All Node Responses:");
|
|
2032
|
+
console.log(JSON.stringify(debugInfo.allNodeResponses, null, 2));
|
|
2033
|
+
}
|
|
2034
|
+
if (debugInfo.allNodeLogs) {
|
|
2035
|
+
console.log("\nš All Node Logs:");
|
|
2036
|
+
debugInfo.allNodeLogs.forEach((nodeLog, index) => {
|
|
2037
|
+
console.log(`\n--- Node ${index + 1} ---`);
|
|
2038
|
+
console.log(JSON.stringify(nodeLog, null, 2));
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
if (debugInfo.rawNodeHTTPResponses) {
|
|
2042
|
+
console.log("\nš Raw Node HTTP Responses:");
|
|
2043
|
+
console.log(JSON.stringify(debugInfo.rawNodeHTTPResponses, null, 2));
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
else {
|
|
2047
|
+
console.log("ā ļø No per-node debug information available in result");
|
|
2048
|
+
}
|
|
2774
2049
|
}
|
|
2775
2050
|
// Parse response if it's a string
|
|
2776
2051
|
let responseData = result.response;
|