@gvnrdao/dh-sdk 0.0.220 → 0.0.222

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14325,53 +14325,53 @@ var init_deployment_addresses = __esm({
14325
14325
  },
14326
14326
  upgraded: {
14327
14327
  PositionManager: {
14328
- previousImplementation: "0x2A65512171ef119A838738B578B5cf0631f3Fcd2",
14329
- newImplementation: "0x1b854fE920AC409b5f407b3ABCd556C998F889E5",
14330
- upgradedAt: "2026-04-20T16:13:36.993Z",
14328
+ previousImplementation: "0x0e40B4D1708f49319f32d51AF01674c26acACeBF",
14329
+ newImplementation: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14330
+ upgradedAt: "2026-04-30T16:23:00.805Z",
14331
14331
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14332
14332
  reason: "Shared upgrade script: PositionManager implementation update"
14333
14333
  },
14334
14334
  LoanOperationsManagerModule: {
14335
- previousImplementation: "0x9CF63e5673530722CF931B55E0371Ad749fF7F1D",
14336
- newImplementation: "0x448Fb59Cad99FFe3d0766F6943E4B579A824d46b",
14337
- upgradedAt: "2026-04-20T16:14:12.783Z",
14335
+ previousImplementation: "0xCf8998a639cC48139C4c61C8B1005EaC40419b88",
14336
+ newImplementation: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14337
+ upgradedAt: "2026-04-30T16:40:12.746Z",
14338
14338
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14339
14339
  reason: "Shared upgrade script: LoanOperationsManagerModule implementation update"
14340
14340
  },
14341
14341
  UCDController: {
14342
- previousImplementation: "0xEE30B47B5Fa46bD9FeA46fB4d2E06EAcF8bBC8ec",
14343
- newImplementation: "0x9100bc3F3299642387C7aC2c626f8D1bDade6aB5",
14344
- upgradedAt: "2026-04-20T16:06:00.516Z",
14342
+ previousImplementation: "0xB5322F0D4a07d4342FA38137ebD95ac41D1c6036",
14343
+ newImplementation: "0x2d4d689A70B56b6E0B9F70BffA6265A55173A4A1",
14344
+ upgradedAt: "2026-04-30T08:24:24.765Z",
14345
14345
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14346
14346
  reason: "Shared upgrade script: UCDController implementation update"
14347
14347
  },
14348
14348
  TermManagerModule: {
14349
- previousImplementation: "0x2f4ED39E87fE53CE1ce28fCce3EE18D92663EAB6",
14350
- newImplementation: "0xa6CECD3f9C581938Dfb8D2423eEAf449BBA5d3aF",
14351
- upgradedAt: "2026-04-20T16:08:12.566Z",
14349
+ previousImplementation: "0x2EaF1052706120CAa6B6F75354F70f77ef2261eB",
14350
+ newImplementation: "0xcc3D2dD7aAfaE5DE923dfd53833a40077178dd75",
14351
+ upgradedAt: "2026-04-30T16:06:36.895Z",
14352
14352
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14353
14353
  reason: "Shared upgrade script: TermManagerModule implementation update"
14354
14354
  },
14355
14355
  CircuitBreakerModule: {
14356
- previousImplementation: "0x3E33049d74f0028e24b1d2475ed8E3444f265275",
14357
- newImplementation: "0xa4940082a7b58c45C3885C4B59714C0dD048cDdC",
14358
- upgradedAt: "2026-04-20T16:10:26.243Z",
14356
+ previousImplementation: "0x8e9e10B14E6a91ec271FBEb4FD3fB1FE06b545dD",
14357
+ newImplementation: "0x485F5E93E479830698Ffdc36957edfcf0084E4c6",
14358
+ upgradedAt: "2026-04-30T16:11:25.723Z",
14359
14359
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14360
14360
  reason: "Shared upgrade script: CircuitBreakerModule implementation update"
14361
14361
  },
14362
14362
  AdminModule: {
14363
- previousImplementation: "0xF298C9CB52DaE62c38392E16d62144C66C2CBe85",
14364
- newImplementation: "0x8bDe850573a947b816D1EC5C5Ca177853bDfD049",
14365
- upgradedAt: "2026-04-21T21:58:00.784Z",
14363
+ previousImplementation: "0x67AE2F872c37f33db9bC631e135432B2845d308b",
14364
+ newImplementation: "0xaC7c227EddCE4F03590Ad10e773219Ffc07f9277",
14365
+ upgradedAt: "2026-04-30T16:24:49.030Z",
14366
14366
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14367
- reason: "1.0.4: Allow setter functions to be called via executeGenericAdminOperation self-invocation"
14367
+ reason: "Bulk-pause functions and network-aware operationDelay"
14368
14368
  },
14369
14369
  PositionManagerViews: {
14370
- previousImplementation: "0x0678FB51a9E8Bd51b6919c48eaD52A5cfF2e29C0",
14371
- newImplementation: "0xE8b4D4b6E3163EdfF8958da4cF8267ACa369D486",
14372
- upgradedAt: "2026-04-21T21:28:48.774Z",
14370
+ previousImplementation: "0xE8b4D4b6E3163EdfF8958da4cF8267ACa369D486",
14371
+ newImplementation: "0xadF8e0F34082a8fC23e727276e0aEf3af183C8Fd",
14372
+ upgradedAt: "2026-04-30T08:32:48.463Z",
14373
14373
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14374
- reason: "1.1.1: Allow admin functions to be called via executeGenericAdminOperation (contract-to-contract calls)"
14374
+ reason: "Shared upgrade script: PositionManagerViews implementation update"
14375
14375
  },
14376
14376
  TestPositionManager: {
14377
14377
  previousImplementation: "0x0B46Ee1a9C6b42559758B7FF78294Cd867BB08f8",
@@ -14381,51 +14381,51 @@ var init_deployment_addresses = __esm({
14381
14381
  reason: "Add setPositionExpiry() for expiry-liquidation E2E testing"
14382
14382
  },
14383
14383
  UCDToken: {
14384
- previousImplementation: "0x66384F03A8915F17917FDc1596fc4fBD00a481C1",
14385
- newImplementation: "0x8671127F940e7bCa87Feb3A34A7ca2a50D16e24d",
14386
- upgradedAt: "2026-04-20T16:06:49.605Z",
14384
+ previousImplementation: "0xEFFF6f32Fc33C4Cb58a4d6858Bf90B8feA7D1D33",
14385
+ newImplementation: "0x155Da00Ee0beb1d9D5BA34Aeb62c9ad4E8227d5D",
14386
+ upgradedAt: "2026-04-30T08:25:01.929Z",
14387
14387
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14388
14388
  reason: "Shared upgrade script: UCDToken implementation update"
14389
14389
  },
14390
14390
  PositionManagerCoreModule: {
14391
- previousImplementation: "0x81f112B85Bc8b54327831DBa1D58b1eb0A166233",
14392
- newImplementation: "0x19470240A0B939141A5bD6cC7E3d784C37E3840E",
14393
- upgradedAt: "2026-04-20T16:07:37.424Z",
14391
+ previousImplementation: "0xED380dDdc919b94924cCd5697bEEfdc347Daa9A6",
14392
+ newImplementation: "0x9c7EF89F1F66F78522AA9D45F894f75583edEC3d",
14393
+ upgradedAt: "2026-04-30T16:21:05.763Z",
14394
14394
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14395
14395
  reason: "Shared upgrade script: PositionManagerCoreModule implementation update"
14396
14396
  },
14397
14397
  CollateralManagerModule: {
14398
- previousImplementation: "0xb26039e5FF9771b2899D54b6dE879D493616502c",
14399
- newImplementation: "0x84C5B89f60415F8df3Fee46Ef1a10a6484aa8e0A",
14400
- upgradedAt: "2026-04-29T12:13:12.465Z",
14398
+ previousImplementation: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14399
+ newImplementation: "0x920e4f52c251B758e351c0d14c4418ad4E5B77ed",
14400
+ upgradedAt: "2026-04-30T16:03:49.056Z",
14401
14401
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14402
14402
  reason: "Shared upgrade script: CollateralManagerModule implementation update"
14403
14403
  },
14404
14404
  LiquidationManagerModule: {
14405
- previousImplementation: "0xcc91578103f2Ec3F2DBbc08C5781e01844fBbCC0",
14406
- newImplementation: "0xBb625E44d72f3F1acDCbB08F73AFdAc38fCE3F64",
14407
- upgradedAt: "2026-04-20T16:09:48.898Z",
14405
+ previousImplementation: "0xf74d5437691df92087170861213e26064358A7fb",
14406
+ newImplementation: "0xcdd426D27bB2f54Dba76dF60EF3D14fD5776CEc7",
14407
+ upgradedAt: "2026-04-30T16:09:01.899Z",
14408
14408
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14409
14409
  reason: "Shared upgrade script: LiquidationManagerModule implementation update"
14410
14410
  },
14411
14411
  BTCSpendAuthorizer: {
14412
- previousImplementation: "0xFEd51Bb3A1e389Cbb8181B71Ea39fc29625BD6cf",
14413
- newImplementation: "0x0B46DCdB63CB9928789ef1979C367da6ef04beAf",
14414
- upgradedAt: "2026-04-20T16:12:13.836Z",
14412
+ previousImplementation: "0xe7337422e2A4AE7709EFc01fB6C681C8899e673C",
14413
+ newImplementation: "0x605bf1C988bb307AFA07326954D593A71580e99d",
14414
+ upgradedAt: "2026-04-30T20:22:12.956Z",
14415
14415
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14416
14416
  reason: "Shared upgrade script: BTCSpendAuthorizer implementation update"
14417
14417
  },
14418
14418
  SimplePSMV2: {
14419
- previousImplementation: "0xD1A16Fb36891b9F27A721ef9Aca4064E39a40B13",
14420
- newImplementation: "0xBdEFa375db7F9A498B81bcfdDd14FD16D02ca0BF",
14421
- upgradedAt: "2026-04-20T16:15:12.674Z",
14419
+ previousImplementation: "0xBdEFa375db7F9A498B81bcfdDd14FD16D02ca0BF",
14420
+ newImplementation: "0x4107104fDF61AACC674f1F168c275f034c8112BF",
14421
+ upgradedAt: "2026-04-30T08:35:01.138Z",
14422
14422
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14423
14423
  reason: "Shared upgrade script: SimplePSMV2 implementation update"
14424
14424
  },
14425
14425
  UpgradeValidator: {
14426
- previousImplementation: "0x4a5BE302c4b6531C0205b6432ECcDbE4405505c2",
14427
- newImplementation: "0x844353ab66C62FfF80377321C5D2331193f888fb",
14428
- upgradedAt: "2026-04-20T16:15:36.931Z",
14426
+ previousImplementation: "0x974C6F4e0F67Fa9d7Ab1aee8C10Bd85B201ec5D7",
14427
+ newImplementation: "0xEFf189e5872bC7158191eD39d31E745aF2A6FDa7",
14428
+ upgradedAt: "2026-04-30T16:47:01.406Z",
14429
14429
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14430
14430
  reason: "Shared upgrade script: UpgradeValidator implementation update"
14431
14431
  },
@@ -14502,26 +14502,26 @@ var init_deployment_addresses = __esm({
14502
14502
  POSITION_MANAGER_VIEWS: "0x3b970E41a0668508B4B2ACb83653b2A402F745AE",
14503
14503
  CIRCUIT_BREAKER_MODULE: "0x3D0B2cAE481821E57BA9CC3807bCC0d0D7F18bd8",
14504
14504
  ADMIN_MODULE: "0xAcd1f07915b17CA3727e7fE89BdF618A1545a1ed",
14505
- UCD_CONTROLLER_IMPL: "0x9100bc3F3299642387C7aC2c626f8D1bDade6aB5",
14506
- LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x448Fb59Cad99FFe3d0766F6943E4B579A824d46b",
14507
- TERM_MANAGER_MODULE_IMPL: "0xa6CECD3f9C581938Dfb8D2423eEAf449BBA5d3aF",
14508
- CIRCUIT_BREAKER_MODULE_IMPL: "0xa4940082a7b58c45C3885C4B59714C0dD048cDdC",
14509
- ADMIN_MODULE_IMPL: "0xF1f9C446BfBB942BfB344EDaC20cDeF2A44A56c5",
14510
- POSITION_MANAGER_VIEWS_IMPL: "0xaBF292941b14c09867A1861B5150187C309E3418",
14511
- POSITION_MANAGER_IMPL: "0x1b854fE920AC409b5f407b3ABCd556C998F889E5",
14505
+ UCD_CONTROLLER_IMPL: "0x2d4d689A70B56b6E0B9F70BffA6265A55173A4A1",
14506
+ LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14507
+ TERM_MANAGER_MODULE_IMPL: "0xcc3D2dD7aAfaE5DE923dfd53833a40077178dd75",
14508
+ CIRCUIT_BREAKER_MODULE_IMPL: "0x8e9e10B14E6a91ec271FBEb4FD3fB1FE06b545dD",
14509
+ ADMIN_MODULE_IMPL: "0x67AE2F872c37f33db9bC631e135432B2845d308b",
14510
+ POSITION_MANAGER_VIEWS_IMPL: "0xadF8e0F34082a8fC23e727276e0aEf3af183C8Fd",
14511
+ POSITION_MANAGER_IMPL: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14512
14512
  SIMPLE_PSM_V2: "0x19EcF7BA26e054fd4Ff06009A03070103dbBB058",
14513
- SIMPLE_PSM_V2_IMPL: "0xBdEFa375db7F9A498B81bcfdDd14FD16D02ca0BF",
14514
- UCD_TOKEN_IMPL: "0x8671127F940e7bCa87Feb3A34A7ca2a50D16e24d",
14513
+ SIMPLE_PSM_V2_IMPL: "0x4107104fDF61AACC674f1F168c275f034c8112BF",
14514
+ UCD_TOKEN_IMPL: "0x155Da00Ee0beb1d9D5BA34Aeb62c9ad4E8227d5D",
14515
14515
  POSITION_MANAGER_CORE_MODULE: "0xfFAA39a08887FeFB697eBC8691A8630CbCC33391",
14516
- POSITION_MANAGER_CORE_MODULE_IMPL: "0x19470240A0B939141A5bD6cC7E3d784C37E3840E",
14516
+ POSITION_MANAGER_CORE_MODULE_IMPL: "0x41168d9BF8e696eBAB05ea539321ac212859d80b",
14517
14517
  COLLATERAL_MANAGER_MODULE: "0x967E92c976Fc0fa8268D37D4d6B7245d912aA7dB",
14518
- COLLATERAL_MANAGER_MODULE_IMPL: "0xb26039e5FF9771b2899D54b6dE879D493616502c",
14518
+ COLLATERAL_MANAGER_MODULE_IMPL: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14519
14519
  LIQUIDATION_MANAGER_MODULE: "0xC4AB00f39e7ceD812F5C67058C9fa44e15d40e76",
14520
- LIQUIDATION_MANAGER_MODULE_IMPL: "0xBb625E44d72f3F1acDCbB08F73AFdAc38fCE3F64",
14520
+ LIQUIDATION_MANAGER_MODULE_IMPL: "0xf74d5437691df92087170861213e26064358A7fb",
14521
14521
  BTC_SPEND_AUTHORIZER: "0xd7E9Eb5eE53f1d9ee55Dc162bBC7486bE437B6bD",
14522
- BTC_SPEND_AUTHORIZER_IMPL: "0x0B46DCdB63CB9928789ef1979C367da6ef04beAf",
14522
+ BTC_SPEND_AUTHORIZER_IMPL: "0x4CD021181bD2583d10aB37D27FE2994b75c41b77",
14523
14523
  UPGRADE_VALIDATOR: "0x592e650edD9bA26ecc407989fdd6F9cdcDeC27A6",
14524
- UPGRADE_VALIDATOR_IMPL: "0x844353ab66C62FfF80377321C5D2331193f888fb",
14524
+ UPGRADE_VALIDATOR_IMPL: "0xEFf189e5872bC7158191eD39d31E745aF2A6FDa7",
14525
14525
  BITCOIN_PROVIDER_REGISTRY: "0xbfA0c48B070D0a9A9CD27469AeacFD2d4261cEE2",
14526
14526
  BITCOIN_PROVIDER_REGISTRY_IMPL: "0x225309A4ae6D146ba93A3278A7b40224FfC81448",
14527
14527
  LIT_ACTION_VALIDATOR: "0x54eECd7C90F8A8fac27749Ba30BbE8AFBAccc856",
@@ -31184,11 +31184,62 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signer)
31184
31184
  signature: signature2
31185
31185
  };
31186
31186
  }
31187
- async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAddress) {
31187
+ function isChipotlePkpId(pkpTokenId) {
31188
31188
  const rawHex = pkpTokenId.startsWith("0x") ? pkpTokenId.slice(2) : pkpTokenId;
31189
- if (rawHex.length === 64 && rawHex.startsWith("000000000000000000000000") && rawHex !== "0".repeat(64)) {
31189
+ return rawHex.length === 64 && rawHex.startsWith("000000000000000000000000") && rawHex !== "0".repeat(64);
31190
+ }
31191
+ async function deriveChipotlePublicKeyViaService(pkpTokenId, fallback) {
31192
+ const url = `${fallback.serviceEndpoint}/api/lit/pkp/derive-public-key`;
31193
+ const controller = new AbortController();
31194
+ const timeout = setTimeout(
31195
+ () => controller.abort(),
31196
+ fallback.timeoutMs ?? 6e4
31197
+ );
31198
+ try {
31199
+ const headers = {
31200
+ "Content-Type": "application/json"
31201
+ };
31202
+ if (fallback.serviceAuthToken) {
31203
+ headers["Authorization"] = `Bearer ${fallback.serviceAuthToken}`;
31204
+ }
31205
+ const response = await fetch(url, {
31206
+ method: "POST",
31207
+ headers,
31208
+ body: JSON.stringify({
31209
+ pkpId: pkpTokenId,
31210
+ ...fallback.borrowerAddress && {
31211
+ borrowerAddress: fallback.borrowerAddress
31212
+ }
31213
+ }),
31214
+ signal: controller.signal
31215
+ });
31216
+ if (!response.ok) {
31217
+ const errorText = await response.text();
31218
+ throw new Error(
31219
+ `derive-public-key service error (${response.status}): ${errorText}`
31220
+ );
31221
+ }
31222
+ const envelope = await response.json();
31223
+ const publicKey = envelope?.data?.publicKey;
31224
+ if (!envelope?.success || !publicKey) {
31225
+ throw new Error(
31226
+ `derive-public-key returned no publicKey (envelope keys: ${Object.keys(
31227
+ envelope ?? {}
31228
+ ).join(", ")})`
31229
+ );
31230
+ }
31231
+ return publicKey.startsWith("0x") ? publicKey : `0x${publicKey}`;
31232
+ } finally {
31233
+ clearTimeout(timeout);
31234
+ }
31235
+ }
31236
+ async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAddress, chipotleFallback) {
31237
+ if (isChipotlePkpId(pkpTokenId)) {
31238
+ if (chipotleFallback?.serviceEndpoint) {
31239
+ return deriveChipotlePublicKeyViaService(pkpTokenId, chipotleFallback);
31240
+ }
31190
31241
  throw new Error(
31191
- `pkpId ${pkpTokenId} is a Chipotle wallet address (ABI-encoded ETH address). Chipotle PKPs are not NFTs and have no on-chain public key lookup. Ensure the PKP public key is populated in cache during position creation.`
31242
+ `pkpId ${pkpTokenId} is a Chipotle wallet address (ABI-encoded ETH address). Chipotle PKPs are not NFTs and have no on-chain public key lookup. Provide chipotleFallback.serviceEndpoint to recover via lit-ops-server, or ensure the PKP public key is populated in cache during position creation.`
31192
31243
  );
31193
31244
  }
31194
31245
  if (!provider) {
@@ -31483,7 +31534,7 @@ function extractOptionalLitSignature(raw) {
31483
31534
 
31484
31535
  // src/modules/contract/contract-manager.module.ts
31485
31536
  var POSITION_MANAGER_ABI = [
31486
- "function createPosition(bytes32 pkpId, bytes calldata validatorSignature, string mainnetVaultAddress, string regtestVaultAddress, uint256 selectedTermMonths, uint256 validatorVersion) external returns (bytes32 positionId)",
31537
+ "function createPosition(bytes32 pkpId, bytes calldata validatorSignature, string mainnetVaultAddress, string regtestVaultAddress, uint256 selectedTermMonths, uint256 validatorVersion, bytes calldata pkpPublicKey) external returns (bytes32 positionId)",
31487
31538
  "function mintUCD(bytes32 positionId, uint256 mintAmount, uint256 mintFee, uint256 newDebt, uint256 newCollateral, uint256 btcPrice, bytes32 authorizedSpendsHash, bytes32 ucdDebtHash, bytes32 contractHash, uint256 quantumTimestamp, bytes calldata mintValidatorSignature) external returns (bool)",
31488
31539
  "function makePayment(bytes32 positionId, uint256 paymentAmount, uint256 quantumTimestamp, uint256 btcPrice, bytes calldata paymentValidatorSignature) external returns (bool)",
31489
31540
  "function extendPosition(bytes32 positionId, uint256 selectedTerm, uint256 quantumTimestamp, uint256 btcPrice, uint256 availableBTCBalance, uint256 proRataRenewalFee, bytes calldata extensionValidatorSignature) external returns (bool)",
@@ -33132,6 +33183,10 @@ var LoanCreator = class {
33132
33183
  ethers_exports.utils.hexlify(BigInt(pkpData.tokenId)),
33133
33184
  32
33134
33185
  );
33186
+ const pkpPublicKeyUncompressed = ethers_exports.utils.computePublicKey(
33187
+ pkpData.publicKey,
33188
+ false
33189
+ );
33135
33190
  console.log("\n\u{1F50D} PKP TOKEN ID CONVERSION TRACE (SDK):");
33136
33191
  console.log("==========================================");
33137
33192
  console.log(
@@ -33182,7 +33237,8 @@ var LoanCreator = class {
33182
33237
  mainnetVaultAddress,
33183
33238
  regtestVaultAddress,
33184
33239
  request.selectedTerm,
33185
- validatorVersion
33240
+ validatorVersion,
33241
+ pkpPublicKeyUncompressed
33186
33242
  ]);
33187
33243
  console.log("\u{1F50D} ENCODED CALLDATA (first 256 chars):", encoded.substring(0, 256));
33188
33244
  console.log("\u{1F50D} ENCODED CALLDATA full length:", encoded.length);
@@ -33195,7 +33251,8 @@ var LoanCreator = class {
33195
33251
  mainnetVaultAddress,
33196
33252
  regtestVaultAddress,
33197
33253
  request.selectedTerm,
33198
- validatorVersion
33254
+ validatorVersion,
33255
+ pkpPublicKeyUncompressed
33199
33256
  );
33200
33257
  if (!tx) {
33201
33258
  return failure(
@@ -33747,8 +33804,8 @@ var LoanQuery = class {
33747
33804
  batch.map(async (loan) => {
33748
33805
  try {
33749
33806
  const rawId = loan.pkpId?.startsWith("0x") ? loan.pkpId.slice(2) : loan.pkpId;
33750
- const isChipotlePkpId = typeof rawId === "string" && rawId.length === 40 && !rawId.toLowerCase().startsWith("04");
33751
- if (isChipotlePkpId) {
33807
+ const isChipotlePkpId2 = typeof rawId === "string" && rawId.length === 40 && !rawId.toLowerCase().startsWith("04");
33808
+ if (isChipotlePkpId2) {
33752
33809
  if (this.config.positionManagerCoreAddress && this.config.provider) {
33753
33810
  const pmContract = new ethers_exports.Contract(
33754
33811
  this.config.positionManagerCoreAddress,
@@ -36898,7 +36955,7 @@ function formatLoanCreationMessage(positionId, pkpId, vaultAddress) {
36898
36955
  }
36899
36956
  function formatBTCWithdrawalFailureMessage(withdrawalAmount, btcVault, btcDestinationAddress, loanId) {
36900
36957
  const formattedAmount = formatBTCAmount(withdrawalAmount);
36901
- return `There was a failure withdrawing ${formattedAmount} from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}`;
36958
+ return `\u274C BTC withdrawal FAILED: ${formattedAmount} from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}`;
36902
36959
  }
36903
36960
  function formatLoanRenewalMessage(positionId, txHash) {
36904
36961
  return `Loan id ${positionId} was successfully renewed. Tx: https://sepolia.etherscan.io/tx/${txHash}`;
@@ -36912,9 +36969,10 @@ function formatBalanceConfirmationMessage(loanId) {
36912
36969
  function formatBalanceConfirmationFailureMessage(loanId) {
36913
36970
  return `FAILED to update to PENDING_MINT for loan id ${loanId}`;
36914
36971
  }
36915
- function formatBTCWithdrawalSuccessMessage(withdrawalAmount, btcVault, btcDestinationAddress, loanId) {
36972
+ function formatBTCWithdrawalSuccessMessage(withdrawalAmount, btcVault, btcDestinationAddress, loanId, btcTxId) {
36916
36973
  const formattedAmount = formatBTCAmount(withdrawalAmount);
36917
- return `${formattedAmount} was withdrawn from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}`;
36974
+ const txSuffix = btcTxId ? ` (tx: ${btcTxId})` : "";
36975
+ return `\u2705 BTC withdrawal SUCCEEDED: ${formattedAmount} sent from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}${txSuffix}`;
36918
36976
  }
36919
36977
  function formatLiquidationSkippedMessage(loanId, ratio, threshold, btcVault, btcVaultBalance, ucdDebt, btcPrice) {
36920
36978
  const formattedPrice = formatBTCPrice(btcPrice);
@@ -37644,6 +37702,18 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
37644
37702
  * Check if SDK is ready for operations
37645
37703
  */
37646
37704
  async _relayNotification(message) {
37705
+ const handler = this.config.notificationHandler;
37706
+ if (typeof handler === "function") {
37707
+ try {
37708
+ await handler(message);
37709
+ } catch (err) {
37710
+ if (this.config.debug) {
37711
+ log.warn("notificationHandler threw", {
37712
+ error: err instanceof Error ? err.message : String(err)
37713
+ });
37714
+ }
37715
+ }
37716
+ }
37647
37717
  if (this.config.mode !== "service")
37648
37718
  return;
37649
37719
  const endpoint = this.config.serviceEndpoint;
@@ -37954,7 +38024,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
37954
38024
  pkpPublicKey = await getPKPPublicKeyFromTokenId(
37955
38025
  position2.pkpId,
37956
38026
  this.getProviderOrThrow(),
37957
- nagaPkpNftAddress
38027
+ nagaPkpNftAddress,
38028
+ this.getChipotlePublicKeyFallback()
37958
38029
  );
37959
38030
  pkpEthAddress = ethers_exports.utils.computeAddress(pkpPublicKey);
37960
38031
  pkpCache.set(request.positionId, {
@@ -39057,7 +39128,8 @@ Error data: ${errorData || "none"}`
39057
39128
  const pkpPublicKey = await getPKPPublicKeyFromTokenId(
39058
39129
  position.pkpId,
39059
39130
  this.getProviderOrThrow(),
39060
- nagaPkpNftAddressLiq
39131
+ nagaPkpNftAddressLiq,
39132
+ this.getChipotlePublicKeyFallback()
39061
39133
  );
39062
39134
  const pkpEthAddress = ethers_exports.utils.computeAddress(pkpPublicKey);
39063
39135
  pkpData = {
@@ -40239,7 +40311,14 @@ Error data: ${errorData || "none"}`
40239
40311
  LoanOperationsManagerModule: this.config.contractAddresses?.loanOperationsManager || "",
40240
40312
  TermManagerModule: this.config.contractAddresses?.termManager || "",
40241
40313
  LiquidationManagerModule: this.config.contractAddresses?.liquidationManager || "",
40242
- ...this.config.contractAddresses?.btcSpendAuthorizer ? { BTCSpendAuthorizer: this.config.contractAddresses.btcSpendAuthorizer } : {}
40314
+ ...this.config.contractAddresses?.btcSpendAuthorizer ? { BTCSpendAuthorizer: this.config.contractAddresses.btcSpendAuthorizer } : {},
40315
+ // Required on non-hardhat chains by Lit Actions after audit C-1/H-6:
40316
+ // the Bitcoin provider whitelist now lives on-chain. Other SDK paths
40317
+ // (mintUCD, extendPosition, withdrawBTC) already forward this; keep
40318
+ // confirmBalance aligned so Sepolia behaves identically to Hardhat.
40319
+ ...this.config.contractAddresses?.bitcoinProviderRegistry ? {
40320
+ BitcoinProviderRegistry: this.config.contractAddresses.bitcoinProviderRegistry
40321
+ } : {}
40243
40322
  };
40244
40323
  const chainId = await this.config.provider?.getNetwork().then((n) => n.chainId) || 11155111;
40245
40324
  const chain = chainId === 11155111 ? "sepolia" : chainId === 1337 ? "hardhat" : "sepolia";
@@ -41140,7 +41219,8 @@ Error data: ${errorData || "none"}`
41140
41219
  pkpPublicKey = await getPKPPublicKeyFromTokenId(
41141
41220
  position.pkpId,
41142
41221
  this.getProviderOrThrow(),
41143
- nagaPkpNftAddress
41222
+ nagaPkpNftAddress,
41223
+ this.getChipotlePublicKeyFallback()
41144
41224
  );
41145
41225
  pkpEthAddress = ethers_exports.utils.computeAddress(pkpPublicKey);
41146
41226
  pkpCache.set(positionId, {
@@ -41610,22 +41690,6 @@ Error data: ${errorData || "none"}`
41610
41690
  gasUsed: receipt.gasUsed?.toString() || "unknown"
41611
41691
  });
41612
41692
  }
41613
- try {
41614
- const position = await this.getPosition(positionId);
41615
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
41616
- const message = formatBTCWithdrawalSuccessMessage(
41617
- btcAmount,
41618
- position?.vaultAddress || "unknown",
41619
- validationResponse.destinationAddress,
41620
- positionId
41621
- );
41622
- await this._relayNotification(message);
41623
- } catch (telegramError) {
41624
- console.error(
41625
- "Telegram notification failed:",
41626
- telegramError instanceof Error ? telegramError.message : String(telegramError)
41627
- );
41628
- }
41629
41693
  return {
41630
41694
  success: true,
41631
41695
  positionId,
@@ -41798,7 +41862,8 @@ Error data: ${errorData || "none"}`
41798
41862
  pkpPublicKey = await getPKPPublicKeyFromTokenId(
41799
41863
  pkpId,
41800
41864
  this.getProviderOrThrow(),
41801
- nagaPkpNftAddress
41865
+ nagaPkpNftAddress,
41866
+ this.getChipotlePublicKeyFallback()
41802
41867
  );
41803
41868
  pkpCache.set(request.positionId, {
41804
41869
  publicKey: pkpPublicKey,
@@ -41977,13 +42042,37 @@ Error data: ${errorData || "none"}`
41977
42042
  if (utxoListResponse.ok) {
41978
42043
  const utxoList = await utxoListResponse.json();
41979
42044
  if (Array.isArray(utxoList)) {
41980
- allUTXOs = utxoList.filter((u) => u.status?.confirmed === true).map((u) => ({
41981
- txid: u.txid,
41982
- vout: u.vout,
41983
- value: u.value,
41984
- // satoshis
41985
- scriptPubKey: derivedScriptPubKey
41986
- }));
42045
+ const confirmed = utxoList.filter((u) => u.status?.confirmed === true);
42046
+ const verified = [];
42047
+ for (const u of confirmed) {
42048
+ try {
42049
+ const txResp = await fetch(`${bitcoinRpcUrl}/tx/${u.txid}`);
42050
+ if (!txResp.ok)
42051
+ continue;
42052
+ const txData = await txResp.json();
42053
+ if (!Array.isArray(txData.vout))
42054
+ continue;
42055
+ let voutIdx = u.vout;
42056
+ const voutData = txData.vout[voutIdx];
42057
+ const spk = voutData?.scriptpubkey || voutData?.scriptPubKey || voutData?.scriptpubkey_hex;
42058
+ if (spk !== derivedScriptPubKey) {
42059
+ const correctIdx = txData.vout.findIndex(
42060
+ (v) => (v.scriptpubkey || v.scriptPubKey || v.scriptpubkey_hex) === derivedScriptPubKey
42061
+ );
42062
+ if (correctIdx < 0)
42063
+ continue;
42064
+ voutIdx = correctIdx;
42065
+ }
42066
+ verified.push({
42067
+ txid: u.txid,
42068
+ vout: voutIdx,
42069
+ value: txData.vout[voutIdx].value,
42070
+ scriptPubKey: derivedScriptPubKey
42071
+ });
42072
+ } catch {
42073
+ }
42074
+ }
42075
+ allUTXOs = verified;
41987
42076
  if (this.config.debug) {
41988
42077
  log.info(`\u2705 Fetched ${allUTXOs.length} confirmed UTXO(s) for consolidation`, {
41989
42078
  vaultAddress,
@@ -42514,6 +42603,27 @@ Error data: ${errorData || "none"}`
42514
42603
  txid: executionResult.txid
42515
42604
  });
42516
42605
  }
42606
+ try {
42607
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
42608
+ const message = executionResult.success ? formatBTCWithdrawalSuccessMessage(
42609
+ btcAmount,
42610
+ vaultAddress,
42611
+ withdrawalAddress,
42612
+ positionId,
42613
+ executionResult.txid
42614
+ ) : formatBTCWithdrawalFailureMessage(
42615
+ btcAmount,
42616
+ vaultAddress,
42617
+ withdrawalAddress,
42618
+ positionId
42619
+ );
42620
+ await this._relayNotification(message);
42621
+ } catch (telegramError) {
42622
+ console.error(
42623
+ "Telegram notification failed:",
42624
+ telegramError instanceof Error ? telegramError.message : String(telegramError)
42625
+ );
42626
+ }
42517
42627
  const transfers = [
42518
42628
  {
42519
42629
  success: executionResult.success,
@@ -42921,6 +43031,19 @@ Error data: ${errorData || "none"}`
42921
43031
  // ============================================================================
42922
43032
  // PRIVATE HELPER METHODS
42923
43033
  // ============================================================================
43034
+ /**
43035
+ * Build the Chipotle service-mode fallback config for getPKPPublicKeyFromTokenId.
43036
+ * Returns undefined in standalone mode so the helper falls back to throwing.
43037
+ */
43038
+ getChipotlePublicKeyFallback() {
43039
+ if (!this.config.serviceEndpoint)
43040
+ return void 0;
43041
+ return {
43042
+ serviceEndpoint: this.config.serviceEndpoint,
43043
+ serviceAuthToken: this.config.serviceAuthToken,
43044
+ debug: this.config.debug
43045
+ };
43046
+ }
42924
43047
  /**
42925
43048
  * Get provider or throw error
42926
43049
  */
package/dist/index.mjs CHANGED
@@ -14331,53 +14331,53 @@ var init_deployment_addresses = __esm({
14331
14331
  },
14332
14332
  upgraded: {
14333
14333
  PositionManager: {
14334
- previousImplementation: "0x2A65512171ef119A838738B578B5cf0631f3Fcd2",
14335
- newImplementation: "0x1b854fE920AC409b5f407b3ABCd556C998F889E5",
14336
- upgradedAt: "2026-04-20T16:13:36.993Z",
14334
+ previousImplementation: "0x0e40B4D1708f49319f32d51AF01674c26acACeBF",
14335
+ newImplementation: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14336
+ upgradedAt: "2026-04-30T16:23:00.805Z",
14337
14337
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14338
14338
  reason: "Shared upgrade script: PositionManager implementation update"
14339
14339
  },
14340
14340
  LoanOperationsManagerModule: {
14341
- previousImplementation: "0x9CF63e5673530722CF931B55E0371Ad749fF7F1D",
14342
- newImplementation: "0x448Fb59Cad99FFe3d0766F6943E4B579A824d46b",
14343
- upgradedAt: "2026-04-20T16:14:12.783Z",
14341
+ previousImplementation: "0xCf8998a639cC48139C4c61C8B1005EaC40419b88",
14342
+ newImplementation: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14343
+ upgradedAt: "2026-04-30T16:40:12.746Z",
14344
14344
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14345
14345
  reason: "Shared upgrade script: LoanOperationsManagerModule implementation update"
14346
14346
  },
14347
14347
  UCDController: {
14348
- previousImplementation: "0xEE30B47B5Fa46bD9FeA46fB4d2E06EAcF8bBC8ec",
14349
- newImplementation: "0x9100bc3F3299642387C7aC2c626f8D1bDade6aB5",
14350
- upgradedAt: "2026-04-20T16:06:00.516Z",
14348
+ previousImplementation: "0xB5322F0D4a07d4342FA38137ebD95ac41D1c6036",
14349
+ newImplementation: "0x2d4d689A70B56b6E0B9F70BffA6265A55173A4A1",
14350
+ upgradedAt: "2026-04-30T08:24:24.765Z",
14351
14351
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14352
14352
  reason: "Shared upgrade script: UCDController implementation update"
14353
14353
  },
14354
14354
  TermManagerModule: {
14355
- previousImplementation: "0x2f4ED39E87fE53CE1ce28fCce3EE18D92663EAB6",
14356
- newImplementation: "0xa6CECD3f9C581938Dfb8D2423eEAf449BBA5d3aF",
14357
- upgradedAt: "2026-04-20T16:08:12.566Z",
14355
+ previousImplementation: "0x2EaF1052706120CAa6B6F75354F70f77ef2261eB",
14356
+ newImplementation: "0xcc3D2dD7aAfaE5DE923dfd53833a40077178dd75",
14357
+ upgradedAt: "2026-04-30T16:06:36.895Z",
14358
14358
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14359
14359
  reason: "Shared upgrade script: TermManagerModule implementation update"
14360
14360
  },
14361
14361
  CircuitBreakerModule: {
14362
- previousImplementation: "0x3E33049d74f0028e24b1d2475ed8E3444f265275",
14363
- newImplementation: "0xa4940082a7b58c45C3885C4B59714C0dD048cDdC",
14364
- upgradedAt: "2026-04-20T16:10:26.243Z",
14362
+ previousImplementation: "0x8e9e10B14E6a91ec271FBEb4FD3fB1FE06b545dD",
14363
+ newImplementation: "0x485F5E93E479830698Ffdc36957edfcf0084E4c6",
14364
+ upgradedAt: "2026-04-30T16:11:25.723Z",
14365
14365
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14366
14366
  reason: "Shared upgrade script: CircuitBreakerModule implementation update"
14367
14367
  },
14368
14368
  AdminModule: {
14369
- previousImplementation: "0xF298C9CB52DaE62c38392E16d62144C66C2CBe85",
14370
- newImplementation: "0x8bDe850573a947b816D1EC5C5Ca177853bDfD049",
14371
- upgradedAt: "2026-04-21T21:58:00.784Z",
14369
+ previousImplementation: "0x67AE2F872c37f33db9bC631e135432B2845d308b",
14370
+ newImplementation: "0xaC7c227EddCE4F03590Ad10e773219Ffc07f9277",
14371
+ upgradedAt: "2026-04-30T16:24:49.030Z",
14372
14372
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14373
- reason: "1.0.4: Allow setter functions to be called via executeGenericAdminOperation self-invocation"
14373
+ reason: "Bulk-pause functions and network-aware operationDelay"
14374
14374
  },
14375
14375
  PositionManagerViews: {
14376
- previousImplementation: "0x0678FB51a9E8Bd51b6919c48eaD52A5cfF2e29C0",
14377
- newImplementation: "0xE8b4D4b6E3163EdfF8958da4cF8267ACa369D486",
14378
- upgradedAt: "2026-04-21T21:28:48.774Z",
14376
+ previousImplementation: "0xE8b4D4b6E3163EdfF8958da4cF8267ACa369D486",
14377
+ newImplementation: "0xadF8e0F34082a8fC23e727276e0aEf3af183C8Fd",
14378
+ upgradedAt: "2026-04-30T08:32:48.463Z",
14379
14379
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14380
- reason: "1.1.1: Allow admin functions to be called via executeGenericAdminOperation (contract-to-contract calls)"
14380
+ reason: "Shared upgrade script: PositionManagerViews implementation update"
14381
14381
  },
14382
14382
  TestPositionManager: {
14383
14383
  previousImplementation: "0x0B46Ee1a9C6b42559758B7FF78294Cd867BB08f8",
@@ -14387,51 +14387,51 @@ var init_deployment_addresses = __esm({
14387
14387
  reason: "Add setPositionExpiry() for expiry-liquidation E2E testing"
14388
14388
  },
14389
14389
  UCDToken: {
14390
- previousImplementation: "0x66384F03A8915F17917FDc1596fc4fBD00a481C1",
14391
- newImplementation: "0x8671127F940e7bCa87Feb3A34A7ca2a50D16e24d",
14392
- upgradedAt: "2026-04-20T16:06:49.605Z",
14390
+ previousImplementation: "0xEFFF6f32Fc33C4Cb58a4d6858Bf90B8feA7D1D33",
14391
+ newImplementation: "0x155Da00Ee0beb1d9D5BA34Aeb62c9ad4E8227d5D",
14392
+ upgradedAt: "2026-04-30T08:25:01.929Z",
14393
14393
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14394
14394
  reason: "Shared upgrade script: UCDToken implementation update"
14395
14395
  },
14396
14396
  PositionManagerCoreModule: {
14397
- previousImplementation: "0x81f112B85Bc8b54327831DBa1D58b1eb0A166233",
14398
- newImplementation: "0x19470240A0B939141A5bD6cC7E3d784C37E3840E",
14399
- upgradedAt: "2026-04-20T16:07:37.424Z",
14397
+ previousImplementation: "0xED380dDdc919b94924cCd5697bEEfdc347Daa9A6",
14398
+ newImplementation: "0x9c7EF89F1F66F78522AA9D45F894f75583edEC3d",
14399
+ upgradedAt: "2026-04-30T16:21:05.763Z",
14400
14400
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14401
14401
  reason: "Shared upgrade script: PositionManagerCoreModule implementation update"
14402
14402
  },
14403
14403
  CollateralManagerModule: {
14404
- previousImplementation: "0xb26039e5FF9771b2899D54b6dE879D493616502c",
14405
- newImplementation: "0x84C5B89f60415F8df3Fee46Ef1a10a6484aa8e0A",
14406
- upgradedAt: "2026-04-29T12:13:12.465Z",
14404
+ previousImplementation: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14405
+ newImplementation: "0x920e4f52c251B758e351c0d14c4418ad4E5B77ed",
14406
+ upgradedAt: "2026-04-30T16:03:49.056Z",
14407
14407
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14408
14408
  reason: "Shared upgrade script: CollateralManagerModule implementation update"
14409
14409
  },
14410
14410
  LiquidationManagerModule: {
14411
- previousImplementation: "0xcc91578103f2Ec3F2DBbc08C5781e01844fBbCC0",
14412
- newImplementation: "0xBb625E44d72f3F1acDCbB08F73AFdAc38fCE3F64",
14413
- upgradedAt: "2026-04-20T16:09:48.898Z",
14411
+ previousImplementation: "0xf74d5437691df92087170861213e26064358A7fb",
14412
+ newImplementation: "0xcdd426D27bB2f54Dba76dF60EF3D14fD5776CEc7",
14413
+ upgradedAt: "2026-04-30T16:09:01.899Z",
14414
14414
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14415
14415
  reason: "Shared upgrade script: LiquidationManagerModule implementation update"
14416
14416
  },
14417
14417
  BTCSpendAuthorizer: {
14418
- previousImplementation: "0xFEd51Bb3A1e389Cbb8181B71Ea39fc29625BD6cf",
14419
- newImplementation: "0x0B46DCdB63CB9928789ef1979C367da6ef04beAf",
14420
- upgradedAt: "2026-04-20T16:12:13.836Z",
14418
+ previousImplementation: "0xe7337422e2A4AE7709EFc01fB6C681C8899e673C",
14419
+ newImplementation: "0x605bf1C988bb307AFA07326954D593A71580e99d",
14420
+ upgradedAt: "2026-04-30T20:22:12.956Z",
14421
14421
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14422
14422
  reason: "Shared upgrade script: BTCSpendAuthorizer implementation update"
14423
14423
  },
14424
14424
  SimplePSMV2: {
14425
- previousImplementation: "0xD1A16Fb36891b9F27A721ef9Aca4064E39a40B13",
14426
- newImplementation: "0xBdEFa375db7F9A498B81bcfdDd14FD16D02ca0BF",
14427
- upgradedAt: "2026-04-20T16:15:12.674Z",
14425
+ previousImplementation: "0xBdEFa375db7F9A498B81bcfdDd14FD16D02ca0BF",
14426
+ newImplementation: "0x4107104fDF61AACC674f1F168c275f034c8112BF",
14427
+ upgradedAt: "2026-04-30T08:35:01.138Z",
14428
14428
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14429
14429
  reason: "Shared upgrade script: SimplePSMV2 implementation update"
14430
14430
  },
14431
14431
  UpgradeValidator: {
14432
- previousImplementation: "0x4a5BE302c4b6531C0205b6432ECcDbE4405505c2",
14433
- newImplementation: "0x844353ab66C62FfF80377321C5D2331193f888fb",
14434
- upgradedAt: "2026-04-20T16:15:36.931Z",
14432
+ previousImplementation: "0x974C6F4e0F67Fa9d7Ab1aee8C10Bd85B201ec5D7",
14433
+ newImplementation: "0xEFf189e5872bC7158191eD39d31E745aF2A6FDa7",
14434
+ upgradedAt: "2026-04-30T16:47:01.406Z",
14435
14435
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14436
14436
  reason: "Shared upgrade script: UpgradeValidator implementation update"
14437
14437
  },
@@ -14508,26 +14508,26 @@ var init_deployment_addresses = __esm({
14508
14508
  POSITION_MANAGER_VIEWS: "0x3b970E41a0668508B4B2ACb83653b2A402F745AE",
14509
14509
  CIRCUIT_BREAKER_MODULE: "0x3D0B2cAE481821E57BA9CC3807bCC0d0D7F18bd8",
14510
14510
  ADMIN_MODULE: "0xAcd1f07915b17CA3727e7fE89BdF618A1545a1ed",
14511
- UCD_CONTROLLER_IMPL: "0x9100bc3F3299642387C7aC2c626f8D1bDade6aB5",
14512
- LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x448Fb59Cad99FFe3d0766F6943E4B579A824d46b",
14513
- TERM_MANAGER_MODULE_IMPL: "0xa6CECD3f9C581938Dfb8D2423eEAf449BBA5d3aF",
14514
- CIRCUIT_BREAKER_MODULE_IMPL: "0xa4940082a7b58c45C3885C4B59714C0dD048cDdC",
14515
- ADMIN_MODULE_IMPL: "0xF1f9C446BfBB942BfB344EDaC20cDeF2A44A56c5",
14516
- POSITION_MANAGER_VIEWS_IMPL: "0xaBF292941b14c09867A1861B5150187C309E3418",
14517
- POSITION_MANAGER_IMPL: "0x1b854fE920AC409b5f407b3ABCd556C998F889E5",
14511
+ UCD_CONTROLLER_IMPL: "0x2d4d689A70B56b6E0B9F70BffA6265A55173A4A1",
14512
+ LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14513
+ TERM_MANAGER_MODULE_IMPL: "0xcc3D2dD7aAfaE5DE923dfd53833a40077178dd75",
14514
+ CIRCUIT_BREAKER_MODULE_IMPL: "0x8e9e10B14E6a91ec271FBEb4FD3fB1FE06b545dD",
14515
+ ADMIN_MODULE_IMPL: "0x67AE2F872c37f33db9bC631e135432B2845d308b",
14516
+ POSITION_MANAGER_VIEWS_IMPL: "0xadF8e0F34082a8fC23e727276e0aEf3af183C8Fd",
14517
+ POSITION_MANAGER_IMPL: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14518
14518
  SIMPLE_PSM_V2: "0x19EcF7BA26e054fd4Ff06009A03070103dbBB058",
14519
- SIMPLE_PSM_V2_IMPL: "0xBdEFa375db7F9A498B81bcfdDd14FD16D02ca0BF",
14520
- UCD_TOKEN_IMPL: "0x8671127F940e7bCa87Feb3A34A7ca2a50D16e24d",
14519
+ SIMPLE_PSM_V2_IMPL: "0x4107104fDF61AACC674f1F168c275f034c8112BF",
14520
+ UCD_TOKEN_IMPL: "0x155Da00Ee0beb1d9D5BA34Aeb62c9ad4E8227d5D",
14521
14521
  POSITION_MANAGER_CORE_MODULE: "0xfFAA39a08887FeFB697eBC8691A8630CbCC33391",
14522
- POSITION_MANAGER_CORE_MODULE_IMPL: "0x19470240A0B939141A5bD6cC7E3d784C37E3840E",
14522
+ POSITION_MANAGER_CORE_MODULE_IMPL: "0x41168d9BF8e696eBAB05ea539321ac212859d80b",
14523
14523
  COLLATERAL_MANAGER_MODULE: "0x967E92c976Fc0fa8268D37D4d6B7245d912aA7dB",
14524
- COLLATERAL_MANAGER_MODULE_IMPL: "0xb26039e5FF9771b2899D54b6dE879D493616502c",
14524
+ COLLATERAL_MANAGER_MODULE_IMPL: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14525
14525
  LIQUIDATION_MANAGER_MODULE: "0xC4AB00f39e7ceD812F5C67058C9fa44e15d40e76",
14526
- LIQUIDATION_MANAGER_MODULE_IMPL: "0xBb625E44d72f3F1acDCbB08F73AFdAc38fCE3F64",
14526
+ LIQUIDATION_MANAGER_MODULE_IMPL: "0xf74d5437691df92087170861213e26064358A7fb",
14527
14527
  BTC_SPEND_AUTHORIZER: "0xd7E9Eb5eE53f1d9ee55Dc162bBC7486bE437B6bD",
14528
- BTC_SPEND_AUTHORIZER_IMPL: "0x0B46DCdB63CB9928789ef1979C367da6ef04beAf",
14528
+ BTC_SPEND_AUTHORIZER_IMPL: "0x4CD021181bD2583d10aB37D27FE2994b75c41b77",
14529
14529
  UPGRADE_VALIDATOR: "0x592e650edD9bA26ecc407989fdd6F9cdcDeC27A6",
14530
- UPGRADE_VALIDATOR_IMPL: "0x844353ab66C62FfF80377321C5D2331193f888fb",
14530
+ UPGRADE_VALIDATOR_IMPL: "0xEFf189e5872bC7158191eD39d31E745aF2A6FDa7",
14531
14531
  BITCOIN_PROVIDER_REGISTRY: "0xbfA0c48B070D0a9A9CD27469AeacFD2d4261cEE2",
14532
14532
  BITCOIN_PROVIDER_REGISTRY_IMPL: "0x225309A4ae6D146ba93A3278A7b40224FfC81448",
14533
14533
  LIT_ACTION_VALIDATOR: "0x54eECd7C90F8A8fac27749Ba30BbE8AFBAccc856",
@@ -31112,11 +31112,62 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signer)
31112
31112
  signature: signature2
31113
31113
  };
31114
31114
  }
31115
- async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAddress) {
31115
+ function isChipotlePkpId(pkpTokenId) {
31116
31116
  const rawHex = pkpTokenId.startsWith("0x") ? pkpTokenId.slice(2) : pkpTokenId;
31117
- if (rawHex.length === 64 && rawHex.startsWith("000000000000000000000000") && rawHex !== "0".repeat(64)) {
31117
+ return rawHex.length === 64 && rawHex.startsWith("000000000000000000000000") && rawHex !== "0".repeat(64);
31118
+ }
31119
+ async function deriveChipotlePublicKeyViaService(pkpTokenId, fallback) {
31120
+ const url = `${fallback.serviceEndpoint}/api/lit/pkp/derive-public-key`;
31121
+ const controller = new AbortController();
31122
+ const timeout = setTimeout(
31123
+ () => controller.abort(),
31124
+ fallback.timeoutMs ?? 6e4
31125
+ );
31126
+ try {
31127
+ const headers = {
31128
+ "Content-Type": "application/json"
31129
+ };
31130
+ if (fallback.serviceAuthToken) {
31131
+ headers["Authorization"] = `Bearer ${fallback.serviceAuthToken}`;
31132
+ }
31133
+ const response = await fetch(url, {
31134
+ method: "POST",
31135
+ headers,
31136
+ body: JSON.stringify({
31137
+ pkpId: pkpTokenId,
31138
+ ...fallback.borrowerAddress && {
31139
+ borrowerAddress: fallback.borrowerAddress
31140
+ }
31141
+ }),
31142
+ signal: controller.signal
31143
+ });
31144
+ if (!response.ok) {
31145
+ const errorText = await response.text();
31146
+ throw new Error(
31147
+ `derive-public-key service error (${response.status}): ${errorText}`
31148
+ );
31149
+ }
31150
+ const envelope = await response.json();
31151
+ const publicKey = envelope?.data?.publicKey;
31152
+ if (!envelope?.success || !publicKey) {
31153
+ throw new Error(
31154
+ `derive-public-key returned no publicKey (envelope keys: ${Object.keys(
31155
+ envelope ?? {}
31156
+ ).join(", ")})`
31157
+ );
31158
+ }
31159
+ return publicKey.startsWith("0x") ? publicKey : `0x${publicKey}`;
31160
+ } finally {
31161
+ clearTimeout(timeout);
31162
+ }
31163
+ }
31164
+ async function getPKPPublicKeyFromTokenId(pkpTokenId, provider, pkpNftContractAddress, chipotleFallback) {
31165
+ if (isChipotlePkpId(pkpTokenId)) {
31166
+ if (chipotleFallback?.serviceEndpoint) {
31167
+ return deriveChipotlePublicKeyViaService(pkpTokenId, chipotleFallback);
31168
+ }
31118
31169
  throw new Error(
31119
- `pkpId ${pkpTokenId} is a Chipotle wallet address (ABI-encoded ETH address). Chipotle PKPs are not NFTs and have no on-chain public key lookup. Ensure the PKP public key is populated in cache during position creation.`
31170
+ `pkpId ${pkpTokenId} is a Chipotle wallet address (ABI-encoded ETH address). Chipotle PKPs are not NFTs and have no on-chain public key lookup. Provide chipotleFallback.serviceEndpoint to recover via lit-ops-server, or ensure the PKP public key is populated in cache during position creation.`
31120
31171
  );
31121
31172
  }
31122
31173
  if (!provider) {
@@ -31411,7 +31462,7 @@ function extractOptionalLitSignature(raw) {
31411
31462
 
31412
31463
  // src/modules/contract/contract-manager.module.ts
31413
31464
  var POSITION_MANAGER_ABI = [
31414
- "function createPosition(bytes32 pkpId, bytes calldata validatorSignature, string mainnetVaultAddress, string regtestVaultAddress, uint256 selectedTermMonths, uint256 validatorVersion) external returns (bytes32 positionId)",
31465
+ "function createPosition(bytes32 pkpId, bytes calldata validatorSignature, string mainnetVaultAddress, string regtestVaultAddress, uint256 selectedTermMonths, uint256 validatorVersion, bytes calldata pkpPublicKey) external returns (bytes32 positionId)",
31415
31466
  "function mintUCD(bytes32 positionId, uint256 mintAmount, uint256 mintFee, uint256 newDebt, uint256 newCollateral, uint256 btcPrice, bytes32 authorizedSpendsHash, bytes32 ucdDebtHash, bytes32 contractHash, uint256 quantumTimestamp, bytes calldata mintValidatorSignature) external returns (bool)",
31416
31467
  "function makePayment(bytes32 positionId, uint256 paymentAmount, uint256 quantumTimestamp, uint256 btcPrice, bytes calldata paymentValidatorSignature) external returns (bool)",
31417
31468
  "function extendPosition(bytes32 positionId, uint256 selectedTerm, uint256 quantumTimestamp, uint256 btcPrice, uint256 availableBTCBalance, uint256 proRataRenewalFee, bytes calldata extensionValidatorSignature) external returns (bool)",
@@ -33060,6 +33111,10 @@ var LoanCreator = class {
33060
33111
  ethers_exports.utils.hexlify(BigInt(pkpData.tokenId)),
33061
33112
  32
33062
33113
  );
33114
+ const pkpPublicKeyUncompressed = ethers_exports.utils.computePublicKey(
33115
+ pkpData.publicKey,
33116
+ false
33117
+ );
33063
33118
  console.log("\n\u{1F50D} PKP TOKEN ID CONVERSION TRACE (SDK):");
33064
33119
  console.log("==========================================");
33065
33120
  console.log(
@@ -33110,7 +33165,8 @@ var LoanCreator = class {
33110
33165
  mainnetVaultAddress,
33111
33166
  regtestVaultAddress,
33112
33167
  request.selectedTerm,
33113
- validatorVersion
33168
+ validatorVersion,
33169
+ pkpPublicKeyUncompressed
33114
33170
  ]);
33115
33171
  console.log("\u{1F50D} ENCODED CALLDATA (first 256 chars):", encoded.substring(0, 256));
33116
33172
  console.log("\u{1F50D} ENCODED CALLDATA full length:", encoded.length);
@@ -33123,7 +33179,8 @@ var LoanCreator = class {
33123
33179
  mainnetVaultAddress,
33124
33180
  regtestVaultAddress,
33125
33181
  request.selectedTerm,
33126
- validatorVersion
33182
+ validatorVersion,
33183
+ pkpPublicKeyUncompressed
33127
33184
  );
33128
33185
  if (!tx) {
33129
33186
  return failure(
@@ -33675,8 +33732,8 @@ var LoanQuery = class {
33675
33732
  batch.map(async (loan) => {
33676
33733
  try {
33677
33734
  const rawId = loan.pkpId?.startsWith("0x") ? loan.pkpId.slice(2) : loan.pkpId;
33678
- const isChipotlePkpId = typeof rawId === "string" && rawId.length === 40 && !rawId.toLowerCase().startsWith("04");
33679
- if (isChipotlePkpId) {
33735
+ const isChipotlePkpId2 = typeof rawId === "string" && rawId.length === 40 && !rawId.toLowerCase().startsWith("04");
33736
+ if (isChipotlePkpId2) {
33680
33737
  if (this.config.positionManagerCoreAddress && this.config.provider) {
33681
33738
  const pmContract = new ethers_exports.Contract(
33682
33739
  this.config.positionManagerCoreAddress,
@@ -36826,7 +36883,7 @@ function formatLoanCreationMessage(positionId, pkpId, vaultAddress) {
36826
36883
  }
36827
36884
  function formatBTCWithdrawalFailureMessage(withdrawalAmount, btcVault, btcDestinationAddress, loanId) {
36828
36885
  const formattedAmount = formatBTCAmount(withdrawalAmount);
36829
- return `There was a failure withdrawing ${formattedAmount} from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}`;
36886
+ return `\u274C BTC withdrawal FAILED: ${formattedAmount} from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}`;
36830
36887
  }
36831
36888
  function formatLoanRenewalMessage(positionId, txHash) {
36832
36889
  return `Loan id ${positionId} was successfully renewed. Tx: https://sepolia.etherscan.io/tx/${txHash}`;
@@ -36840,9 +36897,10 @@ function formatBalanceConfirmationMessage(loanId) {
36840
36897
  function formatBalanceConfirmationFailureMessage(loanId) {
36841
36898
  return `FAILED to update to PENDING_MINT for loan id ${loanId}`;
36842
36899
  }
36843
- function formatBTCWithdrawalSuccessMessage(withdrawalAmount, btcVault, btcDestinationAddress, loanId) {
36900
+ function formatBTCWithdrawalSuccessMessage(withdrawalAmount, btcVault, btcDestinationAddress, loanId, btcTxId) {
36844
36901
  const formattedAmount = formatBTCAmount(withdrawalAmount);
36845
- return `${formattedAmount} was withdrawn from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}`;
36902
+ const txSuffix = btcTxId ? ` (tx: ${btcTxId})` : "";
36903
+ return `\u2705 BTC withdrawal SUCCEEDED: ${formattedAmount} sent from ${btcVault} to ${btcDestinationAddress} for loan id: ${loanId}${txSuffix}`;
36846
36904
  }
36847
36905
  function formatLiquidationSkippedMessage(loanId, ratio, threshold, btcVault, btcVaultBalance, ucdDebt, btcPrice) {
36848
36906
  const formattedPrice = formatBTCPrice(btcPrice);
@@ -37572,6 +37630,18 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
37572
37630
  * Check if SDK is ready for operations
37573
37631
  */
37574
37632
  async _relayNotification(message) {
37633
+ const handler = this.config.notificationHandler;
37634
+ if (typeof handler === "function") {
37635
+ try {
37636
+ await handler(message);
37637
+ } catch (err) {
37638
+ if (this.config.debug) {
37639
+ log.warn("notificationHandler threw", {
37640
+ error: err instanceof Error ? err.message : String(err)
37641
+ });
37642
+ }
37643
+ }
37644
+ }
37575
37645
  if (this.config.mode !== "service")
37576
37646
  return;
37577
37647
  const endpoint = this.config.serviceEndpoint;
@@ -37882,7 +37952,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
37882
37952
  pkpPublicKey = await getPKPPublicKeyFromTokenId(
37883
37953
  position2.pkpId,
37884
37954
  this.getProviderOrThrow(),
37885
- nagaPkpNftAddress
37955
+ nagaPkpNftAddress,
37956
+ this.getChipotlePublicKeyFallback()
37886
37957
  );
37887
37958
  pkpEthAddress = ethers_exports.utils.computeAddress(pkpPublicKey);
37888
37959
  pkpCache.set(request.positionId, {
@@ -38985,7 +39056,8 @@ Error data: ${errorData || "none"}`
38985
39056
  const pkpPublicKey = await getPKPPublicKeyFromTokenId(
38986
39057
  position.pkpId,
38987
39058
  this.getProviderOrThrow(),
38988
- nagaPkpNftAddressLiq
39059
+ nagaPkpNftAddressLiq,
39060
+ this.getChipotlePublicKeyFallback()
38989
39061
  );
38990
39062
  const pkpEthAddress = ethers_exports.utils.computeAddress(pkpPublicKey);
38991
39063
  pkpData = {
@@ -40167,7 +40239,14 @@ Error data: ${errorData || "none"}`
40167
40239
  LoanOperationsManagerModule: this.config.contractAddresses?.loanOperationsManager || "",
40168
40240
  TermManagerModule: this.config.contractAddresses?.termManager || "",
40169
40241
  LiquidationManagerModule: this.config.contractAddresses?.liquidationManager || "",
40170
- ...this.config.contractAddresses?.btcSpendAuthorizer ? { BTCSpendAuthorizer: this.config.contractAddresses.btcSpendAuthorizer } : {}
40242
+ ...this.config.contractAddresses?.btcSpendAuthorizer ? { BTCSpendAuthorizer: this.config.contractAddresses.btcSpendAuthorizer } : {},
40243
+ // Required on non-hardhat chains by Lit Actions after audit C-1/H-6:
40244
+ // the Bitcoin provider whitelist now lives on-chain. Other SDK paths
40245
+ // (mintUCD, extendPosition, withdrawBTC) already forward this; keep
40246
+ // confirmBalance aligned so Sepolia behaves identically to Hardhat.
40247
+ ...this.config.contractAddresses?.bitcoinProviderRegistry ? {
40248
+ BitcoinProviderRegistry: this.config.contractAddresses.bitcoinProviderRegistry
40249
+ } : {}
40171
40250
  };
40172
40251
  const chainId = await this.config.provider?.getNetwork().then((n) => n.chainId) || 11155111;
40173
40252
  const chain = chainId === 11155111 ? "sepolia" : chainId === 1337 ? "hardhat" : "sepolia";
@@ -41068,7 +41147,8 @@ Error data: ${errorData || "none"}`
41068
41147
  pkpPublicKey = await getPKPPublicKeyFromTokenId(
41069
41148
  position.pkpId,
41070
41149
  this.getProviderOrThrow(),
41071
- nagaPkpNftAddress
41150
+ nagaPkpNftAddress,
41151
+ this.getChipotlePublicKeyFallback()
41072
41152
  );
41073
41153
  pkpEthAddress = ethers_exports.utils.computeAddress(pkpPublicKey);
41074
41154
  pkpCache.set(positionId, {
@@ -41538,22 +41618,6 @@ Error data: ${errorData || "none"}`
41538
41618
  gasUsed: receipt.gasUsed?.toString() || "unknown"
41539
41619
  });
41540
41620
  }
41541
- try {
41542
- const position = await this.getPosition(positionId);
41543
- const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
41544
- const message = formatBTCWithdrawalSuccessMessage(
41545
- btcAmount,
41546
- position?.vaultAddress || "unknown",
41547
- validationResponse.destinationAddress,
41548
- positionId
41549
- );
41550
- await this._relayNotification(message);
41551
- } catch (telegramError) {
41552
- console.error(
41553
- "Telegram notification failed:",
41554
- telegramError instanceof Error ? telegramError.message : String(telegramError)
41555
- );
41556
- }
41557
41621
  return {
41558
41622
  success: true,
41559
41623
  positionId,
@@ -41726,7 +41790,8 @@ Error data: ${errorData || "none"}`
41726
41790
  pkpPublicKey = await getPKPPublicKeyFromTokenId(
41727
41791
  pkpId,
41728
41792
  this.getProviderOrThrow(),
41729
- nagaPkpNftAddress
41793
+ nagaPkpNftAddress,
41794
+ this.getChipotlePublicKeyFallback()
41730
41795
  );
41731
41796
  pkpCache.set(request.positionId, {
41732
41797
  publicKey: pkpPublicKey,
@@ -41905,13 +41970,37 @@ Error data: ${errorData || "none"}`
41905
41970
  if (utxoListResponse.ok) {
41906
41971
  const utxoList = await utxoListResponse.json();
41907
41972
  if (Array.isArray(utxoList)) {
41908
- allUTXOs = utxoList.filter((u) => u.status?.confirmed === true).map((u) => ({
41909
- txid: u.txid,
41910
- vout: u.vout,
41911
- value: u.value,
41912
- // satoshis
41913
- scriptPubKey: derivedScriptPubKey
41914
- }));
41973
+ const confirmed = utxoList.filter((u) => u.status?.confirmed === true);
41974
+ const verified = [];
41975
+ for (const u of confirmed) {
41976
+ try {
41977
+ const txResp = await fetch(`${bitcoinRpcUrl}/tx/${u.txid}`);
41978
+ if (!txResp.ok)
41979
+ continue;
41980
+ const txData = await txResp.json();
41981
+ if (!Array.isArray(txData.vout))
41982
+ continue;
41983
+ let voutIdx = u.vout;
41984
+ const voutData = txData.vout[voutIdx];
41985
+ const spk = voutData?.scriptpubkey || voutData?.scriptPubKey || voutData?.scriptpubkey_hex;
41986
+ if (spk !== derivedScriptPubKey) {
41987
+ const correctIdx = txData.vout.findIndex(
41988
+ (v) => (v.scriptpubkey || v.scriptPubKey || v.scriptpubkey_hex) === derivedScriptPubKey
41989
+ );
41990
+ if (correctIdx < 0)
41991
+ continue;
41992
+ voutIdx = correctIdx;
41993
+ }
41994
+ verified.push({
41995
+ txid: u.txid,
41996
+ vout: voutIdx,
41997
+ value: txData.vout[voutIdx].value,
41998
+ scriptPubKey: derivedScriptPubKey
41999
+ });
42000
+ } catch {
42001
+ }
42002
+ }
42003
+ allUTXOs = verified;
41915
42004
  if (this.config.debug) {
41916
42005
  log.info(`\u2705 Fetched ${allUTXOs.length} confirmed UTXO(s) for consolidation`, {
41917
42006
  vaultAddress,
@@ -42442,6 +42531,27 @@ Error data: ${errorData || "none"}`
42442
42531
  txid: executionResult.txid
42443
42532
  });
42444
42533
  }
42534
+ try {
42535
+ const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
42536
+ const message = executionResult.success ? formatBTCWithdrawalSuccessMessage(
42537
+ btcAmount,
42538
+ vaultAddress,
42539
+ withdrawalAddress,
42540
+ positionId,
42541
+ executionResult.txid
42542
+ ) : formatBTCWithdrawalFailureMessage(
42543
+ btcAmount,
42544
+ vaultAddress,
42545
+ withdrawalAddress,
42546
+ positionId
42547
+ );
42548
+ await this._relayNotification(message);
42549
+ } catch (telegramError) {
42550
+ console.error(
42551
+ "Telegram notification failed:",
42552
+ telegramError instanceof Error ? telegramError.message : String(telegramError)
42553
+ );
42554
+ }
42445
42555
  const transfers = [
42446
42556
  {
42447
42557
  success: executionResult.success,
@@ -42849,6 +42959,19 @@ Error data: ${errorData || "none"}`
42849
42959
  // ============================================================================
42850
42960
  // PRIVATE HELPER METHODS
42851
42961
  // ============================================================================
42962
+ /**
42963
+ * Build the Chipotle service-mode fallback config for getPKPPublicKeyFromTokenId.
42964
+ * Returns undefined in standalone mode so the helper falls back to throwing.
42965
+ */
42966
+ getChipotlePublicKeyFallback() {
42967
+ if (!this.config.serviceEndpoint)
42968
+ return void 0;
42969
+ return {
42970
+ serviceEndpoint: this.config.serviceEndpoint,
42971
+ serviceAuthToken: this.config.serviceAuthToken,
42972
+ debug: this.config.debug
42973
+ };
42974
+ }
42852
42975
  /**
42853
42976
  * Get provider or throw error
42854
42977
  */
@@ -138,6 +138,19 @@ interface BaseSDKConfig {
138
138
  };
139
139
  defaultSelectedTermMonths?: number;
140
140
  temperSignaturesTest?: boolean;
141
+ /**
142
+ * Optional in-process notification sink invoked alongside the existing service-mode
143
+ * HTTP relay. Fires in BOTH `standalone` and `service` mode so consumers can observe
144
+ * lifecycle events (e.g. loan renewal, mint, payment, withdrawal) without depending
145
+ * on `lit-ops-server`. The SDK already emits messages via `formatLoan*Message` helpers
146
+ * — this hook just exposes them locally. Errors thrown by the handler are swallowed
147
+ * so notification failures cannot break business operations.
148
+ *
149
+ * @example
150
+ * const notifications: string[] = [];
151
+ * sdkConfig.notificationHandler = (msg) => { notifications.push(msg); };
152
+ */
153
+ notificationHandler?: (message: string) => void | Promise<void>;
141
154
  }
142
155
  /**
143
156
  * Service Mode Configuration
@@ -12,7 +12,7 @@ import type { BigNumber } from "ethers";
12
12
  * Based on contracts/src/interfaces/IPositionManager.sol
13
13
  */
14
14
  export interface PositionManager extends ethers5.Contract {
15
- createPosition(pkpId: string, validatorSignature: string, mainnetVaultAddress: string, regtestVaultAddress: string, selectedTermMonths: number | BigNumber, validatorVersion: number | BigNumber): Promise<ethers5.ContractTransaction>;
15
+ createPosition(pkpId: string, validatorSignature: string, mainnetVaultAddress: string, regtestVaultAddress: string, selectedTermMonths: number | BigNumber, validatorVersion: number | BigNumber, pkpPublicKey: string): Promise<ethers5.ContractTransaction>;
16
16
  mintUCD(positionId: string, mintAmount: BigNumber, mintFee: BigNumber, newDebt: BigNumber, newCollateral: BigNumber, btcPrice: BigNumber, authorizedSpendsHash: string, ucdDebtHash: string, contractHash: string, quantumTimestamp: BigNumber, mintValidatorSignature: string): Promise<ethers5.ContractTransaction>;
17
17
  liquidatePosition(positionId: string, btcPrice: BigNumber, quantumTimestamp: BigNumber, liquidationValidatorSignature: string): Promise<ethers5.ContractTransaction>;
18
18
  getPosition(positionId: string): Promise<{
@@ -589,6 +589,11 @@ export declare class DiamondHandsSDK {
589
589
  * Will be integrated into core methods in Round 2
590
590
  */
591
591
  private extractLitActionError;
592
+ /**
593
+ * Build the Chipotle service-mode fallback config for getPKPPublicKeyFromTokenId.
594
+ * Returns undefined in standalone mode so the helper falls back to throwing.
595
+ */
596
+ private getChipotlePublicKeyFallback;
592
597
  /**
593
598
  * Get provider or throw error
594
599
  */
@@ -132,24 +132,40 @@ export declare function generatePaymentAuthorization(positionId: string, amount:
132
132
  * - LIT Action validates recovered address === position owner
133
133
  */
134
134
  export declare function generateExtendAuthorization(positionId: string, selectedTerm: number, chainId: number, signer: ethers5.Signer): Promise<ExtendOwnerAuthorization>;
135
+ /**
136
+ * Optional Chipotle service fallback for `getPKPPublicKeyFromTokenId`.
137
+ *
138
+ * Chipotle PKPs have no on-chain `getPubkey(tokenId)` lookup, so when the
139
+ * SDK's in-memory `pkp-data` cache is empty (page reload, new device, cleared
140
+ * browser data) we recover the public key by re-running pkp-validator via the
141
+ * lit-ops-server `/api/lit/pkp/derive-public-key` endpoint. Chipotle key
142
+ * derivation is deterministic from `pkpId`, so this returns the same key.
143
+ */
144
+ export interface ChipotleServiceFallback {
145
+ serviceEndpoint: string;
146
+ serviceAuthToken?: string;
147
+ borrowerAddress?: string;
148
+ timeoutMs?: number;
149
+ debug?: boolean;
150
+ }
135
151
  /**
136
152
  * Get PKP public key from PKP token ID.
137
153
  *
138
- * Only valid for datil/naga-era PKPs minted as NFTs on Chronicle Yellowstone.
139
- * The caller must supply both the provider (connected to the PKP NFT's chain)
140
- * and the PKP NFT contract address for that chain.
154
+ * For datil/naga-era PKPs minted as NFTs on Chronicle Yellowstone: looks up
155
+ * via `getPubkey(tokenId)` on the supplied PKP NFT contract.
141
156
  *
142
- * Chipotle PKPs are wallet addresses returned by the Chipotle REST API — they
143
- * are not NFTs and cannot be looked up via this function. Passing a Chipotle
144
- * pkpId (ABI-encoded ETH address, e.g. 0x000...00<20-byte-addr>) throws an
145
- * explicit error so callers surface a clear diagnostic.
157
+ * For Chipotle PKPs (ABI-encoded ETH address): there is no on-chain lookup, so
158
+ * if `chipotleFallback.serviceEndpoint` is configured, the public key is
159
+ * derived by calling lit-ops-server. If the fallback is not configured, this
160
+ * throws with a clear diagnostic.
146
161
  *
147
162
  * @param pkpTokenId - PKP token ID (bytes32 hex string)
148
- * @param provider - Ethereum provider connected to the PKP NFT chain
149
- * @param pkpNftContractAddress - PKP NFT contract address on that chain (required)
163
+ * @param provider - Ethereum provider connected to the PKP NFT chain (datil/naga only)
164
+ * @param pkpNftContractAddress - PKP NFT contract address on that chain (datil/naga only)
165
+ * @param chipotleFallback - Service-mode fallback used when pkpTokenId is a Chipotle id
150
166
  * @returns PKP public key as hex string with '0x' prefix
151
167
  */
152
- export declare function getPKPPublicKeyFromTokenId(pkpTokenId: string, provider?: ethers5.providers.Provider, pkpNftContractAddress?: string): Promise<string>;
168
+ export declare function getPKPPublicKeyFromTokenId(pkpTokenId: string, provider?: ethers5.providers.Provider, pkpNftContractAddress?: string, chipotleFallback?: ChipotleServiceFallback): Promise<string>;
153
169
  /**
154
170
  * Withdraw Owner Authorization Interface (matches lit-actions)
155
171
  */
@@ -132,7 +132,7 @@ export declare function formatBalanceConfirmationFailureMessage(loanId: string):
132
132
  * @param loanId - Position/loan ID
133
133
  * @returns Formatted message string
134
134
  */
135
- export declare function formatBTCWithdrawalSuccessMessage(withdrawalAmount: number | string, btcVault: string, btcDestinationAddress: string, loanId: string): string;
135
+ export declare function formatBTCWithdrawalSuccessMessage(withdrawalAmount: number | string, btcVault: string, btcDestinationAddress: string, loanId: string, btcTxId?: string): string;
136
136
  /**
137
137
  * Format a liquidation skipped notification message
138
138
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gvnrdao/dh-sdk",
3
- "version": "0.0.220",
3
+ "version": "0.0.222",
4
4
  "description": "TypeScript SDK for Diamond Hands Protocol - Bitcoin-backed lending with LIT Protocol PKPs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -70,8 +70,8 @@
70
70
  },
71
71
  "sideEffects": false,
72
72
  "dependencies": {
73
- "@gvnrdao/dh-lit-actions": "^0.0.284",
74
- "@gvnrdao/dh-lit-ops": "^0.0.256",
73
+ "@gvnrdao/dh-lit-actions": "^0.0.285",
74
+ "@gvnrdao/dh-lit-ops": "^0.0.258",
75
75
  "@noble/hashes": "^1.5.0",
76
76
  "axios": "^1.15.2",
77
77
  "bech32": "^2.0.0",