@gvnrdao/dh-sdk 0.0.224 → 0.0.225

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,16 +14325,16 @@ var init_deployment_addresses = __esm({
14325
14325
  },
14326
14326
  upgraded: {
14327
14327
  PositionManager: {
14328
- previousImplementation: "0x0e40B4D1708f49319f32d51AF01674c26acACeBF",
14329
- newImplementation: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14330
- upgradedAt: "2026-04-30T16:23:00.805Z",
14328
+ previousImplementation: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14329
+ newImplementation: "0x45f74eFd06A08040DD69C3059E2edb6966d57518",
14330
+ upgradedAt: "2026-05-04T09:25:00.744Z",
14331
14331
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14332
14332
  reason: "Shared upgrade script: PositionManager implementation update"
14333
14333
  },
14334
14334
  LoanOperationsManagerModule: {
14335
- previousImplementation: "0xCf8998a639cC48139C4c61C8B1005EaC40419b88",
14336
- newImplementation: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14337
- upgradedAt: "2026-04-30T16:40:12.746Z",
14335
+ previousImplementation: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14336
+ newImplementation: "0x2C6740cc4F31Aa90a941686c56FFD37467a3164B",
14337
+ upgradedAt: "2026-05-04T08:28:12.942Z",
14338
14338
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14339
14339
  reason: "Shared upgrade script: LoanOperationsManagerModule implementation update"
14340
14340
  },
@@ -14395,9 +14395,9 @@ var init_deployment_addresses = __esm({
14395
14395
  reason: "Shared upgrade script: PositionManagerCoreModule implementation update"
14396
14396
  },
14397
14397
  CollateralManagerModule: {
14398
- previousImplementation: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14399
- newImplementation: "0x920e4f52c251B758e351c0d14c4418ad4E5B77ed",
14400
- upgradedAt: "2026-04-30T16:03:49.056Z",
14398
+ previousImplementation: "0x920e4f52c251B758e351c0d14c4418ad4E5B77ed",
14399
+ newImplementation: "0x1Fa0440d3803FEccB612ac9977DE43Cb4008621D",
14400
+ upgradedAt: "2026-05-04T08:26:01.565Z",
14401
14401
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14402
14402
  reason: "Shared upgrade script: CollateralManagerModule implementation update"
14403
14403
  },
@@ -14409,9 +14409,9 @@ var init_deployment_addresses = __esm({
14409
14409
  reason: "Shared upgrade script: LiquidationManagerModule implementation update"
14410
14410
  },
14411
14411
  BTCSpendAuthorizer: {
14412
- previousImplementation: "0xe7337422e2A4AE7709EFc01fB6C681C8899e673C",
14413
- newImplementation: "0x605bf1C988bb307AFA07326954D593A71580e99d",
14414
- upgradedAt: "2026-04-30T20:22:12.956Z",
14412
+ previousImplementation: "0x605bf1C988bb307AFA07326954D593A71580e99d",
14413
+ newImplementation: "0x914b3d46F533798A4EFf0Be318E7731c94bf86B1",
14414
+ upgradedAt: "2026-05-04T08:13:12.840Z",
14415
14415
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14416
14416
  reason: "Shared upgrade script: BTCSpendAuthorizer implementation update"
14417
14417
  },
@@ -14503,23 +14503,23 @@ var init_deployment_addresses = __esm({
14503
14503
  CIRCUIT_BREAKER_MODULE: "0x3D0B2cAE481821E57BA9CC3807bCC0d0D7F18bd8",
14504
14504
  ADMIN_MODULE: "0xAcd1f07915b17CA3727e7fE89BdF618A1545a1ed",
14505
14505
  UCD_CONTROLLER_IMPL: "0x2d4d689A70B56b6E0B9F70BffA6265A55173A4A1",
14506
- LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14506
+ LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x2C6740cc4F31Aa90a941686c56FFD37467a3164B",
14507
14507
  TERM_MANAGER_MODULE_IMPL: "0xcc3D2dD7aAfaE5DE923dfd53833a40077178dd75",
14508
14508
  CIRCUIT_BREAKER_MODULE_IMPL: "0x8e9e10B14E6a91ec271FBEb4FD3fB1FE06b545dD",
14509
14509
  ADMIN_MODULE_IMPL: "0x67AE2F872c37f33db9bC631e135432B2845d308b",
14510
14510
  POSITION_MANAGER_VIEWS_IMPL: "0xadF8e0F34082a8fC23e727276e0aEf3af183C8Fd",
14511
- POSITION_MANAGER_IMPL: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14511
+ POSITION_MANAGER_IMPL: "0x45f74eFd06A08040DD69C3059E2edb6966d57518",
14512
14512
  SIMPLE_PSM_V2: "0x19EcF7BA26e054fd4Ff06009A03070103dbBB058",
14513
14513
  SIMPLE_PSM_V2_IMPL: "0x4107104fDF61AACC674f1F168c275f034c8112BF",
14514
14514
  UCD_TOKEN_IMPL: "0x155Da00Ee0beb1d9D5BA34Aeb62c9ad4E8227d5D",
14515
14515
  POSITION_MANAGER_CORE_MODULE: "0xfFAA39a08887FeFB697eBC8691A8630CbCC33391",
14516
14516
  POSITION_MANAGER_CORE_MODULE_IMPL: "0x41168d9BF8e696eBAB05ea539321ac212859d80b",
14517
14517
  COLLATERAL_MANAGER_MODULE: "0x967E92c976Fc0fa8268D37D4d6B7245d912aA7dB",
14518
- COLLATERAL_MANAGER_MODULE_IMPL: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14518
+ COLLATERAL_MANAGER_MODULE_IMPL: "0x1Fa0440d3803FEccB612ac9977DE43Cb4008621D",
14519
14519
  LIQUIDATION_MANAGER_MODULE: "0xC4AB00f39e7ceD812F5C67058C9fa44e15d40e76",
14520
14520
  LIQUIDATION_MANAGER_MODULE_IMPL: "0xf74d5437691df92087170861213e26064358A7fb",
14521
14521
  BTC_SPEND_AUTHORIZER: "0xd7E9Eb5eE53f1d9ee55Dc162bBC7486bE437B6bD",
14522
- BTC_SPEND_AUTHORIZER_IMPL: "0x4CD021181bD2583d10aB37D27FE2994b75c41b77",
14522
+ BTC_SPEND_AUTHORIZER_IMPL: "0x914b3d46F533798A4EFf0Be318E7731c94bf86B1",
14523
14523
  UPGRADE_VALIDATOR: "0x592e650edD9bA26ecc407989fdd6F9cdcDeC27A6",
14524
14524
  UPGRADE_VALIDATOR_IMPL: "0xEFf189e5872bC7158191eD39d31E745aF2A6FDa7",
14525
14525
  BITCOIN_PROVIDER_REGISTRY: "0xbfA0c48B070D0a9A9CD27469AeacFD2d4261cEE2",
@@ -42387,6 +42387,107 @@ Error data: ${errorData || "none"}`
42387
42387
  };
42388
42388
  }
42389
42389
  }
42390
+ /**
42391
+ * Cancel a stale authorized BTC spend whose signing/broadcast step never completed.
42392
+ *
42393
+ * Removes the entry from BTCSpendAuthorizer, restoring the UTXO to the available
42394
+ * balance and allowing the borrower to retry via withdrawBTC() + executeBTCWithdrawal().
42395
+ * Only the position's borrower may call this. Inputs come from getPendingWithdrawals().
42396
+ *
42397
+ * @param positionId - Position identifier
42398
+ * @param txid - Bitcoin UTXO txid (from getPendingWithdrawals)
42399
+ * @param vout - Output index (from getPendingWithdrawals)
42400
+ */
42401
+ async cancelStaleSpend(positionId, txid, vout) {
42402
+ this.ensureInitialized();
42403
+ try {
42404
+ const utxoKey = ethers_exports.utils.solidityKeccak256(["string", "uint32"], [txid, vout]);
42405
+ const contract = new ethers_exports.Contract(
42406
+ this.getContractAddressesOrThrow().positionManager,
42407
+ ["function cancelStaleSpend(bytes32,bytes32) external"],
42408
+ this.getSignerOrThrow()
42409
+ );
42410
+ const tx = await contract["cancelStaleSpend"](
42411
+ this.toBytes32(positionId),
42412
+ utxoKey
42413
+ );
42414
+ const receipt = await tx.wait();
42415
+ return { success: true, transactionHash: receipt.transactionHash };
42416
+ } catch (error) {
42417
+ return {
42418
+ success: false,
42419
+ error: error instanceof Error ? error.message : String(error)
42420
+ };
42421
+ }
42422
+ }
42423
+ /**
42424
+ * Check which authorized BTC withdrawals have not yet been broadcast to Bitcoin.
42425
+ *
42426
+ * `withdrawBTC()` records an authorized spend on-chain but never clears it, even
42427
+ * after execution. This method cross-references each authorized spend against the
42428
+ * Bitcoin network (Esplora /outspend) to determine whether the signing+broadcast
42429
+ * step (`executeBTCWithdrawal`) was actually completed.
42430
+ *
42431
+ * status 'pending' → UTXO still unspent; executeBTCWithdrawal was never called
42432
+ * status 'executed' → UTXO has been spent; withdrawal completed successfully
42433
+ *
42434
+ * @param positionId - Position identifier
42435
+ */
42436
+ async getPendingWithdrawals(positionId) {
42437
+ this.ensureInitialized();
42438
+ const bitcoinProviderUrl = this.config.bitcoinProviders && this.config.bitcoinProviders.length > 0 ? this.config.bitcoinProviders[0]?.url || "" : "";
42439
+ if (!bitcoinProviderUrl) {
42440
+ throw new Error(
42441
+ "bitcoinProviders not configured in SDK config \u2014 required for UTXO spend check"
42442
+ );
42443
+ }
42444
+ const contractAddresses = this.getContractAddressesOrThrow();
42445
+ const positionManagerAbi = [
42446
+ "function getAuthorizedSpends(bytes32) view returns (tuple(string txid, uint32 vout, uint256 satoshis, string targetAddress, uint256 targetAmount, uint256 authorizedAt)[])"
42447
+ ];
42448
+ const positionManager = new ethers_exports.Contract(
42449
+ contractAddresses.positionManager,
42450
+ positionManagerAbi,
42451
+ this.getProviderOrThrow()
42452
+ );
42453
+ const positionIdBytes32 = this.toBytes32(positionId);
42454
+ const authorizedSpends = await positionManager["getAuthorizedSpends"](
42455
+ positionIdBytes32
42456
+ );
42457
+ const withdrawals = [];
42458
+ for (const spend of authorizedSpends) {
42459
+ let status = "pending";
42460
+ try {
42461
+ const resp = await fetch(
42462
+ `${bitcoinProviderUrl}/tx/${spend.txid}/outspend/${spend.vout}`
42463
+ );
42464
+ if (resp.ok) {
42465
+ const data = await resp.json();
42466
+ status = data.spent === true ? "executed" : "pending";
42467
+ }
42468
+ } catch {
42469
+ if (this.config.debug) {
42470
+ log.warn(`\u26A0\uFE0F Could not check outspend for ${spend.txid}:${spend.vout} \u2014 assuming pending`);
42471
+ }
42472
+ }
42473
+ withdrawals.push({
42474
+ txid: spend.txid,
42475
+ vout: Number(spend.vout),
42476
+ satoshis: BigInt(spend.satoshis.toString()),
42477
+ targetAddress: spend.targetAddress,
42478
+ targetAmount: BigInt(spend.targetAmount.toString()),
42479
+ authorizedAt: Number(spend.authorizedAt),
42480
+ status
42481
+ });
42482
+ }
42483
+ const totalPendingSats = withdrawals.filter((w) => w.status === "pending").reduce((sum, w) => sum + w.satoshis, 0n);
42484
+ return {
42485
+ positionId,
42486
+ withdrawals,
42487
+ hasPending: withdrawals.some((w) => w.status === "pending"),
42488
+ totalPendingSats
42489
+ };
42490
+ }
42390
42491
  /**
42391
42492
  * Execute pending Bitcoin transfers
42392
42493
  *
@@ -42447,7 +42548,7 @@ Error data: ${errorData || "none"}`
42447
42548
  positionId,
42448
42549
  utxoIdentifier,
42449
42550
  networkFee,
42450
- destination: spend.destination,
42551
+ destination: spend.targetAddress,
42451
42552
  rpcUrl
42452
42553
  });
42453
42554
  results.push({
package/dist/index.mjs CHANGED
@@ -14331,16 +14331,16 @@ var init_deployment_addresses = __esm({
14331
14331
  },
14332
14332
  upgraded: {
14333
14333
  PositionManager: {
14334
- previousImplementation: "0x0e40B4D1708f49319f32d51AF01674c26acACeBF",
14335
- newImplementation: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14336
- upgradedAt: "2026-04-30T16:23:00.805Z",
14334
+ previousImplementation: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14335
+ newImplementation: "0x45f74eFd06A08040DD69C3059E2edb6966d57518",
14336
+ upgradedAt: "2026-05-04T09:25:00.744Z",
14337
14337
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14338
14338
  reason: "Shared upgrade script: PositionManager implementation update"
14339
14339
  },
14340
14340
  LoanOperationsManagerModule: {
14341
- previousImplementation: "0xCf8998a639cC48139C4c61C8B1005EaC40419b88",
14342
- newImplementation: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14343
- upgradedAt: "2026-04-30T16:40:12.746Z",
14341
+ previousImplementation: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14342
+ newImplementation: "0x2C6740cc4F31Aa90a941686c56FFD37467a3164B",
14343
+ upgradedAt: "2026-05-04T08:28:12.942Z",
14344
14344
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14345
14345
  reason: "Shared upgrade script: LoanOperationsManagerModule implementation update"
14346
14346
  },
@@ -14401,9 +14401,9 @@ var init_deployment_addresses = __esm({
14401
14401
  reason: "Shared upgrade script: PositionManagerCoreModule implementation update"
14402
14402
  },
14403
14403
  CollateralManagerModule: {
14404
- previousImplementation: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14405
- newImplementation: "0x920e4f52c251B758e351c0d14c4418ad4E5B77ed",
14406
- upgradedAt: "2026-04-30T16:03:49.056Z",
14404
+ previousImplementation: "0x920e4f52c251B758e351c0d14c4418ad4E5B77ed",
14405
+ newImplementation: "0x1Fa0440d3803FEccB612ac9977DE43Cb4008621D",
14406
+ upgradedAt: "2026-05-04T08:26:01.565Z",
14407
14407
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14408
14408
  reason: "Shared upgrade script: CollateralManagerModule implementation update"
14409
14409
  },
@@ -14415,9 +14415,9 @@ var init_deployment_addresses = __esm({
14415
14415
  reason: "Shared upgrade script: LiquidationManagerModule implementation update"
14416
14416
  },
14417
14417
  BTCSpendAuthorizer: {
14418
- previousImplementation: "0xe7337422e2A4AE7709EFc01fB6C681C8899e673C",
14419
- newImplementation: "0x605bf1C988bb307AFA07326954D593A71580e99d",
14420
- upgradedAt: "2026-04-30T20:22:12.956Z",
14418
+ previousImplementation: "0x605bf1C988bb307AFA07326954D593A71580e99d",
14419
+ newImplementation: "0x914b3d46F533798A4EFf0Be318E7731c94bf86B1",
14420
+ upgradedAt: "2026-05-04T08:13:12.840Z",
14421
14421
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
14422
14422
  reason: "Shared upgrade script: BTCSpendAuthorizer implementation update"
14423
14423
  },
@@ -14509,23 +14509,23 @@ var init_deployment_addresses = __esm({
14509
14509
  CIRCUIT_BREAKER_MODULE: "0x3D0B2cAE481821E57BA9CC3807bCC0d0D7F18bd8",
14510
14510
  ADMIN_MODULE: "0xAcd1f07915b17CA3727e7fE89BdF618A1545a1ed",
14511
14511
  UCD_CONTROLLER_IMPL: "0x2d4d689A70B56b6E0B9F70BffA6265A55173A4A1",
14512
- LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0xF79384d5186B6081124a560e181dC5E0Cf0444dD",
14512
+ LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x2C6740cc4F31Aa90a941686c56FFD37467a3164B",
14513
14513
  TERM_MANAGER_MODULE_IMPL: "0xcc3D2dD7aAfaE5DE923dfd53833a40077178dd75",
14514
14514
  CIRCUIT_BREAKER_MODULE_IMPL: "0x8e9e10B14E6a91ec271FBEb4FD3fB1FE06b545dD",
14515
14515
  ADMIN_MODULE_IMPL: "0x67AE2F872c37f33db9bC631e135432B2845d308b",
14516
14516
  POSITION_MANAGER_VIEWS_IMPL: "0xadF8e0F34082a8fC23e727276e0aEf3af183C8Fd",
14517
- POSITION_MANAGER_IMPL: "0x94096F14f58Cb427B36f2a5aeE24348a26534C74",
14517
+ POSITION_MANAGER_IMPL: "0x45f74eFd06A08040DD69C3059E2edb6966d57518",
14518
14518
  SIMPLE_PSM_V2: "0x19EcF7BA26e054fd4Ff06009A03070103dbBB058",
14519
14519
  SIMPLE_PSM_V2_IMPL: "0x4107104fDF61AACC674f1F168c275f034c8112BF",
14520
14520
  UCD_TOKEN_IMPL: "0x155Da00Ee0beb1d9D5BA34Aeb62c9ad4E8227d5D",
14521
14521
  POSITION_MANAGER_CORE_MODULE: "0xfFAA39a08887FeFB697eBC8691A8630CbCC33391",
14522
14522
  POSITION_MANAGER_CORE_MODULE_IMPL: "0x41168d9BF8e696eBAB05ea539321ac212859d80b",
14523
14523
  COLLATERAL_MANAGER_MODULE: "0x967E92c976Fc0fa8268D37D4d6B7245d912aA7dB",
14524
- COLLATERAL_MANAGER_MODULE_IMPL: "0xd021ca6Dc2377F361E3c64f60C93E0e4075c2840",
14524
+ COLLATERAL_MANAGER_MODULE_IMPL: "0x1Fa0440d3803FEccB612ac9977DE43Cb4008621D",
14525
14525
  LIQUIDATION_MANAGER_MODULE: "0xC4AB00f39e7ceD812F5C67058C9fa44e15d40e76",
14526
14526
  LIQUIDATION_MANAGER_MODULE_IMPL: "0xf74d5437691df92087170861213e26064358A7fb",
14527
14527
  BTC_SPEND_AUTHORIZER: "0xd7E9Eb5eE53f1d9ee55Dc162bBC7486bE437B6bD",
14528
- BTC_SPEND_AUTHORIZER_IMPL: "0x4CD021181bD2583d10aB37D27FE2994b75c41b77",
14528
+ BTC_SPEND_AUTHORIZER_IMPL: "0x914b3d46F533798A4EFf0Be318E7731c94bf86B1",
14529
14529
  UPGRADE_VALIDATOR: "0x592e650edD9bA26ecc407989fdd6F9cdcDeC27A6",
14530
14530
  UPGRADE_VALIDATOR_IMPL: "0xEFf189e5872bC7158191eD39d31E745aF2A6FDa7",
14531
14531
  BITCOIN_PROVIDER_REGISTRY: "0xbfA0c48B070D0a9A9CD27469AeacFD2d4261cEE2",
@@ -42315,6 +42315,107 @@ Error data: ${errorData || "none"}`
42315
42315
  };
42316
42316
  }
42317
42317
  }
42318
+ /**
42319
+ * Cancel a stale authorized BTC spend whose signing/broadcast step never completed.
42320
+ *
42321
+ * Removes the entry from BTCSpendAuthorizer, restoring the UTXO to the available
42322
+ * balance and allowing the borrower to retry via withdrawBTC() + executeBTCWithdrawal().
42323
+ * Only the position's borrower may call this. Inputs come from getPendingWithdrawals().
42324
+ *
42325
+ * @param positionId - Position identifier
42326
+ * @param txid - Bitcoin UTXO txid (from getPendingWithdrawals)
42327
+ * @param vout - Output index (from getPendingWithdrawals)
42328
+ */
42329
+ async cancelStaleSpend(positionId, txid, vout) {
42330
+ this.ensureInitialized();
42331
+ try {
42332
+ const utxoKey = ethers_exports.utils.solidityKeccak256(["string", "uint32"], [txid, vout]);
42333
+ const contract = new ethers_exports.Contract(
42334
+ this.getContractAddressesOrThrow().positionManager,
42335
+ ["function cancelStaleSpend(bytes32,bytes32) external"],
42336
+ this.getSignerOrThrow()
42337
+ );
42338
+ const tx = await contract["cancelStaleSpend"](
42339
+ this.toBytes32(positionId),
42340
+ utxoKey
42341
+ );
42342
+ const receipt = await tx.wait();
42343
+ return { success: true, transactionHash: receipt.transactionHash };
42344
+ } catch (error) {
42345
+ return {
42346
+ success: false,
42347
+ error: error instanceof Error ? error.message : String(error)
42348
+ };
42349
+ }
42350
+ }
42351
+ /**
42352
+ * Check which authorized BTC withdrawals have not yet been broadcast to Bitcoin.
42353
+ *
42354
+ * `withdrawBTC()` records an authorized spend on-chain but never clears it, even
42355
+ * after execution. This method cross-references each authorized spend against the
42356
+ * Bitcoin network (Esplora /outspend) to determine whether the signing+broadcast
42357
+ * step (`executeBTCWithdrawal`) was actually completed.
42358
+ *
42359
+ * status 'pending' → UTXO still unspent; executeBTCWithdrawal was never called
42360
+ * status 'executed' → UTXO has been spent; withdrawal completed successfully
42361
+ *
42362
+ * @param positionId - Position identifier
42363
+ */
42364
+ async getPendingWithdrawals(positionId) {
42365
+ this.ensureInitialized();
42366
+ const bitcoinProviderUrl = this.config.bitcoinProviders && this.config.bitcoinProviders.length > 0 ? this.config.bitcoinProviders[0]?.url || "" : "";
42367
+ if (!bitcoinProviderUrl) {
42368
+ throw new Error(
42369
+ "bitcoinProviders not configured in SDK config \u2014 required for UTXO spend check"
42370
+ );
42371
+ }
42372
+ const contractAddresses = this.getContractAddressesOrThrow();
42373
+ const positionManagerAbi = [
42374
+ "function getAuthorizedSpends(bytes32) view returns (tuple(string txid, uint32 vout, uint256 satoshis, string targetAddress, uint256 targetAmount, uint256 authorizedAt)[])"
42375
+ ];
42376
+ const positionManager = new ethers_exports.Contract(
42377
+ contractAddresses.positionManager,
42378
+ positionManagerAbi,
42379
+ this.getProviderOrThrow()
42380
+ );
42381
+ const positionIdBytes32 = this.toBytes32(positionId);
42382
+ const authorizedSpends = await positionManager["getAuthorizedSpends"](
42383
+ positionIdBytes32
42384
+ );
42385
+ const withdrawals = [];
42386
+ for (const spend of authorizedSpends) {
42387
+ let status = "pending";
42388
+ try {
42389
+ const resp = await fetch(
42390
+ `${bitcoinProviderUrl}/tx/${spend.txid}/outspend/${spend.vout}`
42391
+ );
42392
+ if (resp.ok) {
42393
+ const data = await resp.json();
42394
+ status = data.spent === true ? "executed" : "pending";
42395
+ }
42396
+ } catch {
42397
+ if (this.config.debug) {
42398
+ log.warn(`\u26A0\uFE0F Could not check outspend for ${spend.txid}:${spend.vout} \u2014 assuming pending`);
42399
+ }
42400
+ }
42401
+ withdrawals.push({
42402
+ txid: spend.txid,
42403
+ vout: Number(spend.vout),
42404
+ satoshis: BigInt(spend.satoshis.toString()),
42405
+ targetAddress: spend.targetAddress,
42406
+ targetAmount: BigInt(spend.targetAmount.toString()),
42407
+ authorizedAt: Number(spend.authorizedAt),
42408
+ status
42409
+ });
42410
+ }
42411
+ const totalPendingSats = withdrawals.filter((w) => w.status === "pending").reduce((sum, w) => sum + w.satoshis, 0n);
42412
+ return {
42413
+ positionId,
42414
+ withdrawals,
42415
+ hasPending: withdrawals.some((w) => w.status === "pending"),
42416
+ totalPendingSats
42417
+ };
42418
+ }
42318
42419
  /**
42319
42420
  * Execute pending Bitcoin transfers
42320
42421
  *
@@ -42375,7 +42476,7 @@ Error data: ${errorData || "none"}`
42375
42476
  positionId,
42376
42477
  utxoIdentifier,
42377
42478
  networkFee,
42378
- destination: spend.destination,
42479
+ destination: spend.targetAddress,
42379
42480
  rpcUrl
42380
42481
  });
42381
42482
  results.push({
@@ -353,6 +353,49 @@ export declare class DiamondHandsSDK {
353
353
  destination?: string;
354
354
  error?: string;
355
355
  }>;
356
+ /**
357
+ * Cancel a stale authorized BTC spend whose signing/broadcast step never completed.
358
+ *
359
+ * Removes the entry from BTCSpendAuthorizer, restoring the UTXO to the available
360
+ * balance and allowing the borrower to retry via withdrawBTC() + executeBTCWithdrawal().
361
+ * Only the position's borrower may call this. Inputs come from getPendingWithdrawals().
362
+ *
363
+ * @param positionId - Position identifier
364
+ * @param txid - Bitcoin UTXO txid (from getPendingWithdrawals)
365
+ * @param vout - Output index (from getPendingWithdrawals)
366
+ */
367
+ cancelStaleSpend(positionId: string, txid: string, vout: number): Promise<{
368
+ success: boolean;
369
+ transactionHash?: string;
370
+ error?: string;
371
+ }>;
372
+ /**
373
+ * Check which authorized BTC withdrawals have not yet been broadcast to Bitcoin.
374
+ *
375
+ * `withdrawBTC()` records an authorized spend on-chain but never clears it, even
376
+ * after execution. This method cross-references each authorized spend against the
377
+ * Bitcoin network (Esplora /outspend) to determine whether the signing+broadcast
378
+ * step (`executeBTCWithdrawal`) was actually completed.
379
+ *
380
+ * status 'pending' → UTXO still unspent; executeBTCWithdrawal was never called
381
+ * status 'executed' → UTXO has been spent; withdrawal completed successfully
382
+ *
383
+ * @param positionId - Position identifier
384
+ */
385
+ getPendingWithdrawals(positionId: string): Promise<{
386
+ positionId: string;
387
+ withdrawals: Array<{
388
+ txid: string;
389
+ vout: number;
390
+ satoshis: bigint;
391
+ targetAddress: string;
392
+ targetAmount: bigint;
393
+ authorizedAt: number;
394
+ status: "pending" | "executed";
395
+ }>;
396
+ hasPending: boolean;
397
+ totalPendingSats: bigint;
398
+ }>;
356
399
  /**
357
400
  * Execute pending Bitcoin transfers
358
401
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gvnrdao/dh-sdk",
3
- "version": "0.0.224",
3
+ "version": "0.0.225",
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.286",
74
- "@gvnrdao/dh-lit-ops": "^0.0.259",
73
+ "@gvnrdao/dh-lit-actions": "^0.0.287",
74
+ "@gvnrdao/dh-lit-ops": "^0.0.260",
75
75
  "@noble/hashes": "^1.5.0",
76
76
  "axios": "^1.15.2",
77
77
  "bech32": "^2.0.0",