@gvnrdao/dh-lit-ops 0.0.108 → 0.0.183

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.
@@ -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, options) {
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 (IPFS): ${pkpValidatorCid}`);
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: Even though the validator PKP is burned/immutable (read-only),
689
- // we still pass its tokenId so the session signature is scoped to the
690
- // validator resource. The Lit nodes will simply treat the resource as
691
- // non-signing, but scoping keeps the session principle of least privilege.
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
- 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
- {
666
+ const litResult = await this.executeActionFromCID(pkpValidatorCid, signerPkp.publicKey, {
718
667
  targetPkpTokenId,
719
- expectedCid, // PKP's LIT Action CID (for validation check)
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, sessionScopedSignerTokenId, // āœ… Use normalized signerPkp.tokenId for session scoping (matching cr-lit)
725
- signerPkp.ethAddress // āœ… Use signerPkp.ethAddress for capacity delegation (matching cr-lit)
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 validator PKP address from public key (CRITICAL: Use signerPkp.publicKey, matching cr-lit)
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
- // 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}`);
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(" 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);
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-6b39a1072059.herokuapp.com/api/esplora";
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
- // Contract addresses must be at top level to become globalThis.contractAddresses in LIT Action
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
- // 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
- }
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/withdrawal/authorize`;
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: request.authMessage,
1678
+ authMessage: transformedAuthMessage,
2153
1679
  userSignature: request.userSignature,
2154
1680
  customRpcUrl: request.customRpcUrl,
2155
1681
  customBitcoinRpcUrl: request.customBitcoinRpcUrl,
@@ -2163,19 +1689,28 @@ 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: 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,
1696
+ approved: result.approved ?? false,
1697
+ signature: result.signature,
1698
+ actionHash: result.actionHash,
1699
+ authorizedSpendsHash: result.authorizedSpendsHash,
1700
+ ucdDebtHash: result.ucdDebtHash,
1701
+ contractBundleHash: result.contractBundleHash,
1702
+ totalDeduction: result.totalDeduction,
1703
+ remainingCollateral: result.remainingCollateral,
1704
+ newCollateralRatioBps: result.newCollateralRatioBps,
1705
+ destinationAddress: result.destinationAddress,
1706
+ btcPrice: result.btcPrice,
1707
+ timestamp: result.timestamp,
1708
+ utxoTxid: result.utxoTxid,
1709
+ utxoVout: result.utxoVout,
1710
+ utxoSatoshis: result.utxoSatoshis,
1711
+ reason: result.reason,
1712
+ failedStep: result.failedStep,
1713
+ error: result.error,
2179
1714
  };
2180
1715
  }
2181
1716
  catch (error) {
@@ -2228,7 +1763,7 @@ class LitOps {
2228
1763
  chain = "sepolia";
2229
1764
  bitcoinProviderUrl =
2230
1765
  process.env.BITCOIN_PROVIDER_URL ||
2231
- "https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api/esplora";
1766
+ "https://diamond-hands-btc-faucet-jw-b86e9451a147.herokuapp.com/api";
2232
1767
  break;
2233
1768
  case 1337: // Hardhat local testnet (actual deployment chainId)
2234
1769
  case 31337: // Hardhat local testnet (standard default)
@@ -2262,6 +1797,7 @@ class LitOps {
2262
1797
  },
2263
1798
  // Always pass contractAddresses (undefined in prod mode)
2264
1799
  contractAddresses: request.authMessage.contractAddresses,
1800
+ priceProviders: request.priceProviders, // Pass price provider API keys (standalone mode)
2265
1801
  };
2266
1802
  // Add custom RPC URL for local development
2267
1803
  if (request.customRpcUrl) {
@@ -2270,21 +1806,12 @@ class LitOps {
2270
1806
  console.log(" Custom RPC URL:", request.customRpcUrl);
2271
1807
  }
2272
1808
  }
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
1809
  // 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
1810
  const result = await this.actionExecutor.executeAction({
2282
1811
  cid: litActionInfo.cid,
2283
1812
  pkpPublicKey: litActionInfo.pkp.publicKey,
2284
1813
  params: litActionParams,
2285
1814
  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
1815
  }, litClient);
2289
1816
  if (this.config.debug) {
2290
1817
  console.log("šŸ“„ LIT Action response:", {
@@ -2318,6 +1845,7 @@ class LitOps {
2318
1845
  actionHash: responseData?.actionHash,
2319
1846
  authorizedSpendsHash: responseData?.authorizedSpendsHash,
2320
1847
  ucdDebtHash: responseData?.ucdDebtHash,
1848
+ contractBundleHash: responseData?.contractBundleHash, // Binds to specific contract deployment
2321
1849
  totalDeduction: responseData?.totalDeduction,
2322
1850
  remainingCollateral: responseData?.remainingCollateral,
2323
1851
  newCollateralRatioBps: responseData?.newCollateralRatioBps,
@@ -2336,82 +1864,6 @@ class LitOps {
2336
1864
  }
2337
1865
  return returnValue;
2338
1866
  }
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
1867
  /**
2416
1868
  * Sign Bitcoin transaction for BTC withdrawal execution (Phase 2)
2417
1869
  *
@@ -2461,23 +1913,25 @@ class LitOps {
2461
1913
  if (this.config.debug) {
2462
1914
  console.log("šŸ“„ Service response:", envelope);
2463
1915
  }
1916
+ // Extract data from envelope (server wraps in { success, data } structure)
1917
+ const result = envelope.data || envelope;
2464
1918
  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,
1919
+ success: result.success ?? false,
1920
+ unsignedTxHex: result.unsignedTxHex,
1921
+ sigHash: result.sigHash,
1922
+ signature: result.signature,
1923
+ pkpPublicKey: result.pkpPublicKey,
1924
+ pkpBtcAddress: result.pkpBtcAddress,
1925
+ destination: result.destination,
1926
+ userReceivesAmount: result.userReceivesAmount,
1927
+ networkFee: result.networkFee,
1928
+ changeAmount: result.changeAmount,
1929
+ utxo: result.utxo,
1930
+ authorization: result.authorization,
1931
+ timestamp: result.timestamp,
1932
+ action: result.action,
1933
+ error: result.error,
1934
+ failedStep: result.failedStep,
2481
1935
  };
2482
1936
  }
2483
1937
  catch (error) {
@@ -2488,206 +1942,6 @@ class LitOps {
2488
1942
  };
2489
1943
  }
2490
1944
  }
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
1945
  /**
2692
1946
  * Sign Bitcoin transaction locally (STANDALONE mode)
2693
1947
  */
@@ -2721,14 +1975,18 @@ class LitOps {
2721
1975
  const chainId = request.auth.chainId;
2722
1976
  switch (chainId) {
2723
1977
  case 1: // Ethereum mainnet
2724
- bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
1978
+ bitcoinProviderUrl =
1979
+ process.env.BITCOIN_PROVIDER_URL || "https://mempool.space/api";
2725
1980
  break;
2726
1981
  case 11155111: // Sepolia testnet
2727
- bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "https://diamond-hands-btc-faucet-6b39a1072059.herokuapp.com/api";
1982
+ bitcoinProviderUrl =
1983
+ process.env.BITCOIN_PROVIDER_URL ||
1984
+ "https://diamond-hands-btc-faucet-jw-b86e9451a147.herokuapp.com/api";
2728
1985
  break;
2729
1986
  case 1337: // Hardhat local testnet (actual deployment chainId)
2730
1987
  case 31337: // Hardhat local testnet (standard default)
2731
- bitcoinProviderUrl = process.env.BITCOIN_PROVIDER_URL || "http://127.0.0.1:18443";
1988
+ bitcoinProviderUrl =
1989
+ process.env.BITCOIN_PROVIDER_URL || "http://127.0.0.1:18443";
2732
1990
  break;
2733
1991
  default:
2734
1992
  throw new Error(`Unsupported chainId: ${chainId}`);
@@ -2746,7 +2004,7 @@ class LitOps {
2746
2004
  bitcoinProviderUrl, // For Bitcoin UTXO queries
2747
2005
  auth: request.auth,
2748
2006
  publicKey: request.publicKey,
2749
- contracts: request.contracts,
2007
+ contractAddresses: request.contractAddresses,
2750
2008
  };
2751
2009
  // Add custom EVM RPC URL for local development (Hardhat)
2752
2010
  if (request.customRpcUrl) {
@@ -2771,6 +2029,30 @@ class LitOps {
2771
2029
  hasSignature: !!result.signatures,
2772
2030
  error: result.error,
2773
2031
  });
2032
+ // Log per-node debug information if available
2033
+ if (result.debug) {
2034
+ console.log("\nšŸ” PER-NODE DEBUG INFORMATION:");
2035
+ console.log("=====================================");
2036
+ const debugInfo = result.debug;
2037
+ if (debugInfo.allNodeResponses) {
2038
+ console.log("\nšŸ“Š All Node Responses:");
2039
+ console.log(JSON.stringify(debugInfo.allNodeResponses, null, 2));
2040
+ }
2041
+ if (debugInfo.allNodeLogs) {
2042
+ console.log("\nšŸ“ All Node Logs:");
2043
+ debugInfo.allNodeLogs.forEach((nodeLog, index) => {
2044
+ console.log(`\n--- Node ${index + 1} ---`);
2045
+ console.log(JSON.stringify(nodeLog, null, 2));
2046
+ });
2047
+ }
2048
+ if (debugInfo.rawNodeHTTPResponses) {
2049
+ console.log("\n🌐 Raw Node HTTP Responses:");
2050
+ console.log(JSON.stringify(debugInfo.rawNodeHTTPResponses, null, 2));
2051
+ }
2052
+ }
2053
+ else {
2054
+ console.log("āš ļø No per-node debug information available in result");
2055
+ }
2774
2056
  }
2775
2057
  // Parse response if it's a string
2776
2058
  let responseData = result.response;
@@ -2790,7 +2072,7 @@ class LitOps {
2790
2072
  // Extract combined signature from LIT SDK result
2791
2073
  // LIT SDK returns signatures in result.signatures.btcTxSig after combination
2792
2074
  let combinedSignature;
2793
- if (result.signatures && typeof result.signatures === 'object') {
2075
+ if (result.signatures && typeof result.signatures === "object") {
2794
2076
  const btcTxSig = result.signatures.btcTxSig;
2795
2077
  if (btcTxSig && btcTxSig.signature) {
2796
2078
  // LIT SDK combined signature
@@ -2798,7 +2080,7 @@ class LitOps {
2798
2080
  if (this.config.debug && combinedSignature) {
2799
2081
  console.log("āœ… Extracted combined signature from LIT SDK:", {
2800
2082
  signatureLength: combinedSignature.length,
2801
- signatureStart: combinedSignature.substring(0, 20) + "..."
2083
+ signatureStart: combinedSignature.substring(0, 20) + "...",
2802
2084
  });
2803
2085
  }
2804
2086
  }