@gvnrdao/dh-sdk 0.0.274 → 0.0.276

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
@@ -3671,7 +3671,8 @@ var init_deployment_addresses = __esm({
3671
3671
  mockUsdcToken: "0x96409A98e0D322d6566b7F44a0fAbD1BD4ce2AEc",
3672
3672
  mockUsdtToken: "0xF8b7fB38b17a310960E47805Be9adba0b0e0394D",
3673
3673
  PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
3674
- FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374"
3674
+ FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
3675
+ BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe"
3675
3676
  },
3676
3677
  upgraded: {
3677
3678
  PositionManager: {
@@ -3682,11 +3683,11 @@ var init_deployment_addresses = __esm({
3682
3683
  reason: "Shared upgrade script: PositionManager implementation update"
3683
3684
  },
3684
3685
  LoanOperationsManagerModule: {
3685
- previousImplementation: "0x291B412c573a4F52410f09D7Ba82eead17D9a674",
3686
- newImplementation: "0x9DA8d69d7BcF9Fa3ba5734580e8C32618aB52D36",
3687
- upgradedAt: "2026-05-17T20:02:12.883Z",
3686
+ previousImplementation: "0x9DA8d69d7BcF9Fa3ba5734580e8C32618aB52D36",
3687
+ newImplementation: "0x8c20e9Edf44146718F2EF15eEF47A201CaC229B8",
3688
+ upgradedAt: "2026-06-05T10:52:25.179Z",
3688
3689
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
3689
- reason: "Shared upgrade script: LoanOperationsManagerModule implementation update"
3690
+ reason: "audit #3 v1.6.0: LoanOperationsManagerModule \u2014 Chainlink feed-staleness gate (maxBtcFeedAgeBorrow / maxBtcFeedAgeLiquidation)"
3690
3691
  },
3691
3692
  UCDController: {
3692
3693
  previousImplementation: "0x30d0458bE846f4C5D231242eB5a9e9Db68e7232F",
@@ -3745,9 +3746,9 @@ var init_deployment_addresses = __esm({
3745
3746
  reason: "Shared upgrade script: PositionManagerCoreModule implementation update"
3746
3747
  },
3747
3748
  CollateralManagerModule: {
3748
- previousImplementation: "0x428982fCC9A0455c56881B8e21C96B220CC1506B",
3749
- newImplementation: "0x124e61aBff60CC70c4B81ab3019A8A7D35B412d4",
3750
- upgradedAt: "2026-05-17T19:17:01.129Z",
3749
+ previousImplementation: "0x124e61aBff60CC70c4B81ab3019A8A7D35B412d4",
3750
+ newImplementation: "0xd47FE9126daE9A1e0fFdaCf539BE7345D3642bcb",
3751
+ upgradedAt: "2026-06-05T09:14:12.892Z",
3751
3752
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
3752
3753
  reason: "Shared upgrade script: CollateralManagerModule implementation update"
3753
3754
  },
@@ -3891,7 +3892,7 @@ var init_deployment_addresses = __esm({
3891
3892
  CIRCUIT_BREAKER_MODULE: "0x3D0B2cAE481821E57BA9CC3807bCC0d0D7F18bd8",
3892
3893
  ADMIN_MODULE: "0xAcd1f07915b17CA3727e7fE89BdF618A1545a1ed",
3893
3894
  UCD_CONTROLLER_IMPL: "0x30d0458bE846f4C5D231242eB5a9e9Db68e7232F",
3894
- LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x9DA8d69d7BcF9Fa3ba5734580e8C32618aB52D36",
3895
+ LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x8c20e9Edf44146718F2EF15eEF47A201CaC229B8",
3895
3896
  TERM_MANAGER_MODULE_IMPL: "0x358d6A7A864853beAA3E157fEB83dCEb1628E8eB",
3896
3897
  CIRCUIT_BREAKER_MODULE_IMPL: "0xF6277dEF72D51312CC99616B5380f34Eb7603D75",
3897
3898
  ADMIN_MODULE_IMPL: "0xBBA86246169f81a307Fafff02C1e3D8456aab973",
@@ -3923,7 +3924,9 @@ var init_deployment_addresses = __esm({
3923
3924
  AGENT_MODULE: "0xefb8C29C1e7e92ed7d81a52dbedaed74e37fe380",
3924
3925
  FEE_RECIPIENT_REGISTRY: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
3925
3926
  FEE_RECIPIENT_REGISTRY_IMPL: "0xd08513a7cB2dd354B26cDDf549616F12054c34c9",
3926
- OPERATION_AUTHORIZATION_REGISTRY_IMPL: "0x9f8072d4672d643e39d8638478e900Fea1f2c81D"
3927
+ OPERATION_AUTHORIZATION_REGISTRY_IMPL: "0x9f8072d4672d643e39d8638478e900Fea1f2c81D",
3928
+ BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe",
3929
+ BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_IMPL: "0xFF270BC4470dBA80430Bd1a3a66EB691599354fA"
3927
3930
  }
3928
3931
  };
3929
3932
  SEPOLIA_CONTRACTS = {
@@ -3950,7 +3953,8 @@ var init_deployment_addresses = __esm({
3950
3953
  mockUsdcToken: "0x96409A98e0D322d6566b7F44a0fAbD1BD4ce2AEc",
3951
3954
  mockUsdtToken: "0xF8b7fB38b17a310960E47805Be9adba0b0e0394D",
3952
3955
  PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
3953
- FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374"
3956
+ FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
3957
+ BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe"
3954
3958
  };
3955
3959
  LOCALHOST_DEPLOYMENT = {
3956
3960
  network: "localhost",
@@ -7266,7 +7270,7 @@ var require_abstract_coder = __commonJS({
7266
7270
  function toObject2(names2, items, deep) {
7267
7271
  if (names2.indexOf(null) >= 0) {
7268
7272
  return items.map((item, index) => {
7269
- if (item instanceof Result10) {
7273
+ if (item instanceof Result11) {
7270
7274
  return toObject2(getNames2(item), item, deep);
7271
7275
  }
7272
7276
  return item;
@@ -7275,7 +7279,7 @@ var require_abstract_coder = __commonJS({
7275
7279
  return names2.reduce((accum, name, index) => {
7276
7280
  let item = items.getValue(name);
7277
7281
  if (!(name in accum)) {
7278
- if (deep && item instanceof Result10) {
7282
+ if (deep && item instanceof Result11) {
7279
7283
  item = toObject2(getNames2(item), item, deep);
7280
7284
  }
7281
7285
  accum[name] = item;
@@ -7283,7 +7287,7 @@ var require_abstract_coder = __commonJS({
7283
7287
  return accum;
7284
7288
  }, {});
7285
7289
  }
7286
- var Result10 = class _Result extends Array {
7290
+ var Result11 = class _Result extends Array {
7287
7291
  // No longer used; but cannot be removed as it will remove the
7288
7292
  // #private field from the .d.ts which may break backwards
7289
7293
  // compatibility
@@ -7487,7 +7491,7 @@ var require_abstract_coder = __commonJS({
7487
7491
  return new _Result(_guard5, items, keys);
7488
7492
  }
7489
7493
  };
7490
- exports2.Result = Result10;
7494
+ exports2.Result = Result11;
7491
7495
  function checkResultErrors2(result) {
7492
7496
  const errors2 = [];
7493
7497
  const checkErrors = function(path2, object2) {
@@ -20178,9 +20182,9 @@ var require_contract = __commonJS({
20178
20182
  function _ContractBase2() {
20179
20183
  return BaseContract2;
20180
20184
  }
20181
- var Contract2 = class extends _ContractBase2() {
20185
+ var Contract3 = class extends _ContractBase2() {
20182
20186
  };
20183
- exports2.Contract = Contract2;
20187
+ exports2.Contract = Contract3;
20184
20188
  }
20185
20189
  });
20186
20190
 
@@ -31445,17 +31449,17 @@ var require_pkg_src = __commonJS({
31445
31449
  }
31446
31450
  },
31447
31451
  btcWithdrawal: {
31448
- cid: "QmbsmTg6RuE6SGUkXqkcXSaWy99ydUtyLoFCBxiHuqpSKC",
31452
+ cid: "QmNqErzpgDUair9bPK7oPQczjKjRcsmcej37izponrEcqp",
31449
31453
  authorizedCidHex: cidToHex(
31450
- "QmbsmTg6RuE6SGUkXqkcXSaWy99ydUtyLoFCBxiHuqpSKC"
31454
+ "QmNqErzpgDUair9bPK7oPQczjKjRcsmcej37izponrEcqp"
31451
31455
  ),
31452
31456
  name: "Btc Withdrawal",
31453
31457
  description: "Production Btc Withdrawal",
31454
31458
  version: "1.0.0",
31455
31459
  deployed: true,
31456
- deployedAt: 1780400560069,
31457
- size: 74485,
31458
- hash: "dc62aa5f52c8ad3c86f8c99f9f08519d036e716554682ccb1f7227ca969df118",
31460
+ deployedAt: 1780651980768,
31461
+ size: 75137,
31462
+ hash: "368f9aea32cf2e660b0f75b88b6ee043cf5956319d7b3c6c695d4b984b3bd555",
31459
31463
  validatorWalletAddress: "0xbb137fbda353199e9419b698c57a742124d4987d",
31460
31464
  pkp: {
31461
31465
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -32328,7 +32332,7 @@ ${errorReport}`);
32328
32332
  }
32329
32333
  init_debug_logger();
32330
32334
  init_session_signature_cache();
32331
- var import_ethers13 = require_lib2();
32335
+ var import_ethers14 = require_lib2();
32332
32336
  var EXPIRED_LOAN_MIN_LIQUIDATION_THRESHOLD_BPS = 11e3;
32333
32337
  var GRACE_PERIOD_DAYS = 30;
32334
32338
  var SATOSHIS_PER_BITCOIN = 100000000n;
@@ -34480,12 +34484,12 @@ ${errorReport}`);
34480
34484
  }
34481
34485
  async function executeVaultSnapshot(params) {
34482
34486
  global.ethers = {
34483
- ...import_ethers13.ethers,
34487
+ ...import_ethers14.ethers,
34484
34488
  providers: {
34485
- StaticJsonRpcProvider: import_ethers13.ethers.JsonRpcProvider
34489
+ StaticJsonRpcProvider: import_ethers14.ethers.JsonRpcProvider
34486
34490
  },
34487
- Contract: import_ethers13.ethers.Contract,
34488
- utils: import_ethers13.ethers
34491
+ Contract: import_ethers14.ethers.Contract,
34492
+ utils: import_ethers14.ethers
34489
34493
  // v6 moved utils to top level
34490
34494
  };
34491
34495
  global.Lit = {
@@ -34753,7 +34757,8 @@ function getSepoliaConfig() {
34753
34757
  bitcoinProviderRegistry: SEPOLIA_CONTRACTS.BitcoinProviderRegistry || "",
34754
34758
  contractVersionRegistry: SEPOLIA_CONTRACTS.ContractVersionRegistry || "",
34755
34759
  feeRecipientRegistry: SEPOLIA_CONTRACTS.FeeRecipientRegistry || "",
34756
- positionDelegateRegistry: SEPOLIA_CONTRACTS.PositionDelegateRegistry || ""
34760
+ positionDelegateRegistry: SEPOLIA_CONTRACTS.PositionDelegateRegistry || "",
34761
+ bitcoinWithdrawalAddressRegistry: SEPOLIA_CONTRACTS.BitcoinWithdrawalAddressRegistry || ""
34757
34762
  },
34758
34763
  subgraphs: {
34759
34764
  // Lazy getter for the same module-init snapshot reason as serviceEndpoint.
@@ -37197,9 +37202,9 @@ var require_ToPrimitive = __commonJS({
37197
37202
  }
37198
37203
  });
37199
37204
 
37200
- // node_modules/es-abstract/2024/ToString.js
37205
+ // node_modules/es-abstract/2025/ToString.js
37201
37206
  var require_ToString = __commonJS({
37202
- "node_modules/es-abstract/2024/ToString.js"(exports2, module2) {
37207
+ "node_modules/es-abstract/2025/ToString.js"(exports2, module2) {
37203
37208
  "use strict";
37204
37209
  var GetIntrinsic = require_get_intrinsic();
37205
37210
  var $String = GetIntrinsic("%String%");
@@ -37220,13 +37225,20 @@ var require_implementation3 = __commonJS({
37220
37225
  var RequireObjectCoercible = require_RequireObjectCoercible();
37221
37226
  var ToString = require_ToString();
37222
37227
  var callBound = require_call_bound();
37228
+ var safeRegexTester = require_safe_regex_test();
37223
37229
  var $replace = callBound("String.prototype.replace");
37230
+ var $charAt = callBound("String.prototype.charAt");
37231
+ var $slice = callBound("String.prototype.slice");
37224
37232
  var mvsIsWS = /^\s$/.test("\u180E");
37225
37233
  var leftWhitespace = mvsIsWS ? /^[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+/ : /^[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+/;
37226
- var rightWhitespace = mvsIsWS ? /[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+$/ : /[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+$/;
37234
+ var isWhitespace = safeRegexTester(mvsIsWS ? /[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]$/ : /[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]$/);
37227
37235
  module2.exports = function trim() {
37228
- var S = ToString(RequireObjectCoercible(this));
37229
- return $replace($replace(S, leftWhitespace, ""), rightWhitespace, "");
37236
+ var S = $replace(ToString(RequireObjectCoercible(this)), leftWhitespace, "");
37237
+ var end = S.length;
37238
+ while (end > 0 && isWhitespace($charAt(S, end - 1))) {
37239
+ end -= 1;
37240
+ }
37241
+ return $slice(S, 0, end);
37230
37242
  };
37231
37243
  }
37232
37244
  });
@@ -37479,6 +37491,22 @@ var require_ToObject = __commonJS({
37479
37491
  }
37480
37492
  });
37481
37493
 
37494
+ // node_modules/es-abstract/2024/ToString.js
37495
+ var require_ToString2 = __commonJS({
37496
+ "node_modules/es-abstract/2024/ToString.js"(exports2, module2) {
37497
+ "use strict";
37498
+ var GetIntrinsic = require_get_intrinsic();
37499
+ var $String = GetIntrinsic("%String%");
37500
+ var $TypeError = require_type();
37501
+ module2.exports = function ToString(argument) {
37502
+ if (typeof argument === "symbol") {
37503
+ throw new $TypeError("Cannot convert a Symbol value to a string");
37504
+ }
37505
+ return $String(argument);
37506
+ };
37507
+ }
37508
+ });
37509
+
37482
37510
  // node_modules/array.prototype.findindex/implementation.js
37483
37511
  var require_implementation4 = __commonJS({
37484
37512
  "node_modules/array.prototype.findindex/implementation.js"(exports2, module2) {
@@ -37489,7 +37517,7 @@ var require_implementation4 = __commonJS({
37489
37517
  var LengthOfArrayLike = require_LengthOfArrayLike();
37490
37518
  var ToBoolean = require_ToBoolean();
37491
37519
  var ToObject = require_ToObject();
37492
- var ToString = require_ToString();
37520
+ var ToString = require_ToString2();
37493
37521
  module2.exports = function findIndex(predicate) {
37494
37522
  var O = ToObject(this);
37495
37523
  var len = LengthOfArrayLike(O);
@@ -90082,6 +90110,7 @@ __export(src_exports, {
90082
90110
  UCDConversions: () => UCDConversions,
90083
90111
  VALID_LIT_NETWORKS: () => VALID_LIT_NETWORKS,
90084
90112
  WeiConversions: () => WeiConversions,
90113
+ WithdrawalAddressModule: () => WithdrawalAddressModule,
90085
90114
  andThen: () => andThen,
90086
90115
  assertProtocolNotPaused: () => assertProtocolNotPaused,
90087
90116
  assertSafeServiceEndpoint: () => assertSafeServiceEndpoint,
@@ -90096,6 +90125,7 @@ __export(src_exports, {
90096
90125
  createLoanQuery: () => createLoanQuery,
90097
90126
  createMockTokenManager: () => createMockTokenManager,
90098
90127
  createPKPManager: () => createPKPManager,
90128
+ createWithdrawalAddressModule: () => createWithdrawalAddressModule,
90099
90129
  default: () => DiamondHandsSDK,
90100
90130
  failure: () => failure,
90101
90131
  fetchProtocolPauseStatus: () => fetchProtocolPauseStatus,
@@ -94331,6 +94361,13 @@ var ZeroAddress = "0x0000000000000000000000000000000000000000";
94331
94361
  // node_modules/ethers/lib.esm/constants/hashes.js
94332
94362
  var ZeroHash = "0x0000000000000000000000000000000000000000000000000000000000000000";
94333
94363
 
94364
+ // node_modules/ethers/lib.esm/constants/numbers.js
94365
+ var N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
94366
+ var WeiPerEther = BigInt("1000000000000000000");
94367
+ var MaxUint256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
94368
+ var MinInt256 = BigInt("0x8000000000000000000000000000000000000000000000000000000000000000") * BigInt(-1);
94369
+ var MaxInt256 = BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
94370
+
94334
94371
  // node_modules/ethers/lib.esm/crypto/signature.js
94335
94372
  var BN_04 = BigInt(0);
94336
94373
  var BN_13 = BigInt(1);
@@ -108864,6 +108901,15 @@ function safeValidateBitcoinAddress(address, network = "regtest") {
108864
108901
  }
108865
108902
  return address;
108866
108903
  }
108904
+ function normalizeBitcoinAddress(address) {
108905
+ if (!address || typeof address !== "string")
108906
+ return address;
108907
+ const trimmed = address.trim();
108908
+ if (/^(bc1|tb1|bcrt1)/i.test(trimmed)) {
108909
+ return trimmed.toLowerCase();
108910
+ }
108911
+ return trimmed;
108912
+ }
108867
108913
 
108868
108914
  // src/protocol/protocol-pause.ts
108869
108915
  var GET_PROTOCOL_PAUSE_STATUS_ABI = [
@@ -109055,6 +109101,21 @@ var LIQUIDATION_MANAGER_ABI = [
109055
109101
  "function canLiquidate(bytes32 positionId) external view returns (bool)",
109056
109102
  "function vrfSeeds(bytes32 positionId) external view returns (uint256)"
109057
109103
  ];
109104
+ var BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_ABI = [
109105
+ "function addAddress(string btcAddress) external",
109106
+ "function removeAddress(string btcAddress) external",
109107
+ "function removeAddressByHash(bytes32 addrHash) external",
109108
+ "function isApproved(address user, string btcAddress) external view returns (bool)",
109109
+ "function isApprovedByHash(address user, bytes32 addrHash) external view returns (bool)",
109110
+ "function isPresent(address user, bytes32 addrHash) external view returns (bool)",
109111
+ "function getAddedAt(address user, bytes32 addrHash) external view returns (uint64)",
109112
+ "function getUsableAt(address user, bytes32 addrHash) external view returns (uint256)",
109113
+ "function getAddressHashes(address user) external view returns (bytes32[])",
109114
+ "function addressCount(address user) external view returns (uint256)",
109115
+ "function addressDelay() external view returns (uint256)",
109116
+ "event AddressAdded(address indexed user, bytes32 indexed addrHash, string btcAddress, uint64 addedAt, uint256 usableAt)",
109117
+ "event AddressRemoved(address indexed user, bytes32 indexed addrHash, string btcAddress)"
109118
+ ];
109058
109119
  var ContractManager = class {
109059
109120
  config;
109060
109121
  contracts = null;
@@ -109115,6 +109176,11 @@ var ContractManager = class {
109115
109176
  contractAddresses.liquidationManager || ZeroAddress,
109116
109177
  LIQUIDATION_MANAGER_ABI,
109117
109178
  contractRunner
109179
+ ),
109180
+ bitcoinWithdrawalAddressRegistry: new Contract(
109181
+ contractAddresses.bitcoinWithdrawalAddressRegistry || ZeroAddress,
109182
+ BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_ABI,
109183
+ contractRunner
109118
109184
  )
109119
109185
  };
109120
109186
  this.contracts = contracts;
@@ -109145,7 +109211,16 @@ var ContractManager = class {
109145
109211
  "loanOperationsManager",
109146
109212
  "termManager",
109147
109213
  "circuitBreaker",
109148
- "liquidationManager"
109214
+ "liquidationManager",
109215
+ // INTENTIONALLY OPTIONAL — do not promote to requiredAddresses.
109216
+ // The on-chain CollateralManager gate is inert while its registry is
109217
+ // address(0) (staged rollout), so pre-v1.3 deployments, browser/default
109218
+ // configs, and tests legitimately omit this address. The SDK's layer-1
109219
+ // early-reject (WithdrawalAddressModule.assertApprovedForWithdrawal)
109220
+ // already no-ops via isConfigured() when the address is absent/ZeroAddress,
109221
+ // and the contract instance defaults to ZeroAddress. Making this required
109222
+ // would throw at init for every config that hasn't deployed the registry.
109223
+ "bitcoinWithdrawalAddressRegistry"
109149
109224
  ];
109150
109225
  const missing = [];
109151
109226
  const invalid = [];
@@ -109258,6 +109333,16 @@ var ContractManager = class {
109258
109333
  }
109259
109334
  return success(contractsResult.value.liquidationManager);
109260
109335
  }
109336
+ /**
109337
+ * Get the BitcoinWithdrawalAddressRegistry contract (per-wallet approved-address allowlist).
109338
+ */
109339
+ getBitcoinWithdrawalAddressRegistry() {
109340
+ const contractsResult = this.getContracts();
109341
+ if (!contractsResult.success) {
109342
+ return contractsResult;
109343
+ }
109344
+ return success(contractsResult.value.bitcoinWithdrawalAddressRegistry);
109345
+ }
109261
109346
  /**
109262
109347
  * Get the provider instance
109263
109348
  */
@@ -111347,6 +111432,168 @@ function createLoanQuery(config) {
111347
111432
  }
111348
111433
  }
111349
111434
 
111435
+ // src/modules/withdrawal-address/withdrawal-address.module.ts
111436
+ var WithdrawalAddressModule = class {
111437
+ config;
111438
+ constructor(config) {
111439
+ this.config = config;
111440
+ }
111441
+ /** Resolve the registry contract, or fail if it isn't configured for this network. */
111442
+ getRegistry() {
111443
+ const res = this.config.contractManager.getBitcoinWithdrawalAddressRegistry();
111444
+ if (!res.success)
111445
+ return res;
111446
+ const target = res.value.target;
111447
+ if (!target || target === ZeroAddress) {
111448
+ return failure(
111449
+ new SDKError({
111450
+ code: "SDK_WITHDRAWAL_REGISTRY_NOT_CONFIGURED",
111451
+ message: "BitcoinWithdrawalAddressRegistry address is not configured for this network",
111452
+ category: "CONFIGURATION" /* CONFIGURATION */,
111453
+ severity: "MEDIUM" /* MEDIUM */
111454
+ })
111455
+ );
111456
+ }
111457
+ return success(res.value);
111458
+ }
111459
+ /** True iff the registry is wired for this network (enforcement is active). */
111460
+ isConfigured() {
111461
+ return this.getRegistry().success;
111462
+ }
111463
+ /** keccak256 of the canonicalized address — matches the on-chain key. */
111464
+ static addressHash(btcAddress) {
111465
+ return keccak256(toUtf8Bytes(normalizeBitcoinAddress(btcAddress)));
111466
+ }
111467
+ /**
111468
+ * Add a Bitcoin address to the caller's allowlist. It becomes usable only
111469
+ * after the registry's delay elapses. Returns the submitted tx.
111470
+ */
111471
+ async addAddress(btcAddress) {
111472
+ const reg = this.getRegistry();
111473
+ if (!reg.success)
111474
+ return reg;
111475
+ try {
111476
+ const tx = await reg.value.addAddress(
111477
+ normalizeBitcoinAddress(btcAddress)
111478
+ );
111479
+ return success(tx);
111480
+ } catch (error2) {
111481
+ return this.txFailure("addAddress", error2, btcAddress);
111482
+ }
111483
+ }
111484
+ /** Remove a Bitcoin address from the caller's allowlist (effective immediately). */
111485
+ async removeAddress(btcAddress) {
111486
+ const reg = this.getRegistry();
111487
+ if (!reg.success)
111488
+ return reg;
111489
+ try {
111490
+ const tx = await reg.value.removeAddress(
111491
+ normalizeBitcoinAddress(btcAddress)
111492
+ );
111493
+ return success(tx);
111494
+ } catch (error2) {
111495
+ return this.txFailure("removeAddress", error2, btcAddress);
111496
+ }
111497
+ }
111498
+ /**
111499
+ * Authoritative contract read: is `btcAddress` approved (present AND past its
111500
+ * delay) for `user`?
111501
+ */
111502
+ async isApproved(user, btcAddress) {
111503
+ const reg = this.getRegistry();
111504
+ if (!reg.success)
111505
+ return reg;
111506
+ try {
111507
+ const ok = await reg.value.isApproved(
111508
+ user,
111509
+ normalizeBitcoinAddress(btcAddress)
111510
+ );
111511
+ return success(ok);
111512
+ } catch (error2) {
111513
+ return this.txFailure("isApproved", error2, btcAddress);
111514
+ }
111515
+ }
111516
+ /**
111517
+ * Read the user's allowlist from the contract: hashes + timestamps + derived
111518
+ * approval state. NOTE: the raw address strings are NOT on-chain — use the
111519
+ * subgraph (WithdrawalAddressBook) to render human-readable addresses.
111520
+ */
111521
+ async getEntries(user) {
111522
+ const reg = this.getRegistry();
111523
+ if (!reg.success)
111524
+ return reg;
111525
+ try {
111526
+ const hashes = await reg.value.getAddressHashes(user);
111527
+ const entries = [];
111528
+ for (const addrHash of hashes) {
111529
+ const addedAt = Number(await reg.value.getAddedAt(user, addrHash));
111530
+ const usableAt = Number(await reg.value.getUsableAt(user, addrHash));
111531
+ const approved = await reg.value.isApprovedByHash(
111532
+ user,
111533
+ addrHash
111534
+ );
111535
+ entries.push({ addrHash, addedAt, usableAt, approved });
111536
+ }
111537
+ return success(entries);
111538
+ } catch (error2) {
111539
+ return this.txFailure("getEntries", error2, user);
111540
+ }
111541
+ }
111542
+ /** The current global delay (seconds) before a newly-added address is usable. */
111543
+ async getAddressDelay() {
111544
+ const reg = this.getRegistry();
111545
+ if (!reg.success)
111546
+ return reg;
111547
+ try {
111548
+ const delay = await reg.value.addressDelay();
111549
+ return success(Number(delay));
111550
+ } catch (error2) {
111551
+ return this.txFailure("addressDelay", error2, "");
111552
+ }
111553
+ }
111554
+ /**
111555
+ * Early-reject guard used by `withdrawBTC`. Resolves to a typed error if the
111556
+ * destination is not approved for `borrower`. When the registry is not
111557
+ * configured for the network, this is a no-op (the on-chain gate remains the
111558
+ * hard guarantee).
111559
+ */
111560
+ async assertApprovedForWithdrawal(borrower, btcAddress) {
111561
+ if (!this.isConfigured())
111562
+ return success(void 0);
111563
+ const res = await this.isApproved(borrower, btcAddress);
111564
+ if (!res.success)
111565
+ return res;
111566
+ if (!res.value) {
111567
+ return failure(
111568
+ new SDKError({
111569
+ code: "SDK_WITHDRAWAL_ADDRESS_NOT_APPROVED",
111570
+ message: `Bitcoin address ${btcAddress} is not an approved withdrawal destination for ${borrower} (not on the allowlist, or its time-lock has not elapsed). Add it and wait for the delay first.`,
111571
+ category: "VALIDATION" /* VALIDATION */,
111572
+ severity: "MEDIUM" /* MEDIUM */,
111573
+ context: { borrower, btcAddress }
111574
+ })
111575
+ );
111576
+ }
111577
+ return success(void 0);
111578
+ }
111579
+ txFailure(op, error2, context) {
111580
+ const msg = error2 instanceof Error ? error2.message : String(error2);
111581
+ return failure(
111582
+ new SDKError({
111583
+ code: `SDK_WITHDRAWAL_REGISTRY_${op.toUpperCase()}_FAILED`,
111584
+ message: `WithdrawalAddressRegistry.${op} failed: ${msg}`,
111585
+ category: "CONTRACT" /* CONTRACT */,
111586
+ severity: "MEDIUM" /* MEDIUM */,
111587
+ originalError: error2 instanceof Error ? error2 : new Error(String(error2)),
111588
+ context: { op, context }
111589
+ })
111590
+ );
111591
+ }
111592
+ };
111593
+ function createWithdrawalAddressModule(config) {
111594
+ return new WithdrawalAddressModule(config);
111595
+ }
111596
+
111350
111597
  // src/types/branded/domain-values.ts
111351
111598
  var UCD_BRAND = Symbol.for("diamond-hands.UCD");
111352
111599
  var SATOSHIS_BRAND = Symbol.for("diamond-hands.Satoshis");
@@ -117179,6 +117426,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
117179
117426
  loanCreator;
117180
117427
  loanQuery;
117181
117428
  bitcoinOperations;
117429
+ withdrawalAddressModule;
117182
117430
  mockTokenManager;
117183
117431
  graphClient;
117184
117432
  /**
@@ -117362,6 +117610,10 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
117362
117610
  );
117363
117611
  }
117364
117612
  this.contractManager = contractManagerResult.value;
117613
+ this.withdrawalAddressModule = createWithdrawalAddressModule({
117614
+ contractManager: this.contractManager,
117615
+ debug: config.debug
117616
+ });
117365
117617
  this.litOps = new import_dh_lit_ops.LitOps({
117366
117618
  mode: config.mode || "standalone",
117367
117619
  network: config.litNetwork || DEFAULT_LIT_NETWORK,
@@ -117436,6 +117688,11 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
117436
117688
  );
117437
117689
  }
117438
117690
  const graphHeaders = !serviceMode && config.graphApiKey ? { Authorization: `Bearer ${config.graphApiKey}` } : void 0;
117691
+ if (graphHeaders && typeof window !== "undefined" && typeof window.document !== "undefined") {
117692
+ log.warn(
117693
+ "graphApiKey is being used in standalone mode inside a browser \u2014 the key will be exposed to end users. Use service mode (serviceEndpoint + session auth) for any user-facing app so GRAPH_API_KEY stays server-side."
117694
+ );
117695
+ }
117439
117696
  this.graphClient = new DiamondHandsGraph(
117440
117697
  {
117441
117698
  endpoint: graphEndpoint,
@@ -118247,7 +118504,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
118247
118504
  );
118248
118505
  }
118249
118506
  const chain = this.config.chain || (Number(network2.chainId) === 1 ? "ethereum" : "sepolia");
118250
- const devBitcoinProviderUrl = void 0;
118507
+ const devBitcoinProviderUrl = request.customBitcoinRpcUrl || this.config.bitcoinProviders?.[0]?.url;
118251
118508
  if (this.config.debug) {
118252
118509
  log.info(` Network: ${chain} (chainId: ${network2.chainId})`);
118253
118510
  }
@@ -118293,7 +118550,17 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
118293
118550
  contractAddresses: contracts
118294
118551
  },
118295
118552
  userSignature: auth.signature,
118296
- ...devBitcoinProviderUrl ? { devBitcoinProviderUrl } : {},
118553
+ // lit-ops reads `bitcoinProviderUrl` (request field) and maps it to the
118554
+ // validator's `devBitcoinProviderUrl` jsParam on Hardhat.
118555
+ ...devBitcoinProviderUrl ? { bitcoinProviderUrl: devBitcoinProviderUrl } : {},
118556
+ // Optional override of the mint validator PKP/wallet (e.g. an on-chain-multisig-authorized
118557
+ // validator) — applied to a local copy in lit-ops, never mutating the registry singleton.
118558
+ // When set, authorization is by the on-chain ACTION CID, so the posted code must stay
118559
+ // byte-identical to the registry code (no cache-bust nonce) or the derived CID won't match.
118560
+ ...this.config.mintValidatorOverride ? {
118561
+ validatorOverride: this.config.mintValidatorOverride,
118562
+ disableCacheBust: true
118563
+ } : {},
118297
118564
  rpcUrl: request.rpcUrl || this.config.ethRpcUrl,
118298
118565
  // Pass RPC URL to LIT Action (ngrok for Hardhat)
118299
118566
  ...request.debugOverrides && {
@@ -121309,6 +121576,40 @@ Error data: ${errorData || "none"}`
121309
121576
  this.releaseWriteLock(request.positionId);
121310
121577
  }
121311
121578
  }
121579
+ /**
121580
+ * Access the approved-withdrawal-address allowlist module (self-service
121581
+ * add/remove + reads). The connected wallet manages its OWN addresses; a
121582
+ * newly-added address is only usable after the registry's time-lock delay.
121583
+ */
121584
+ get withdrawalAddresses() {
121585
+ return this.withdrawalAddressModule;
121586
+ }
121587
+ /**
121588
+ * Add a Bitcoin address to the connected wallet's approved-withdrawal allowlist.
121589
+ * Usable only after the registry's delay (default 24h) elapses.
121590
+ */
121591
+ async addApprovedWithdrawalAddress(btcAddress) {
121592
+ return this.withdrawalAddressModule.addAddress(btcAddress);
121593
+ }
121594
+ /** Remove a Bitcoin address from the connected wallet's allowlist (immediate). */
121595
+ async removeApprovedWithdrawalAddress(btcAddress) {
121596
+ return this.withdrawalAddressModule.removeAddress(btcAddress);
121597
+ }
121598
+ /**
121599
+ * Read the connected wallet's (or `user`'s) approved-address entries from the
121600
+ * contract (hashes + timestamps + derived approval state). For human-readable
121601
+ * address strings, query the subgraph `WithdrawalAddressBook`.
121602
+ */
121603
+ async getApprovedWithdrawalAddresses(user) {
121604
+ let target = user;
121605
+ if (!target) {
121606
+ const signerRes = this.contractManager.getSigner();
121607
+ if (!signerRes.success)
121608
+ return signerRes;
121609
+ target = await signerRes.value.getAddress();
121610
+ }
121611
+ return this.withdrawalAddressModule.getEntries(target);
121612
+ }
121312
121613
  /**
121313
121614
  * Withdraw Bitcoin from a position
121314
121615
  *
@@ -121393,6 +121694,48 @@ Error data: ${errorData || "none"}`
121393
121694
  if (this.config.debug) {
121394
121695
  log.info(` Position PKP ID: ${position.pkpId}`);
121395
121696
  }
121697
+ if (this.withdrawalAddressModule.isConfigured()) {
121698
+ const rawStatus = position.status;
121699
+ const isLiquidated = Number(rawStatus) === 5 || String(rawStatus).toUpperCase() === "LIQUIDATED";
121700
+ let controller;
121701
+ if (isLiquidated) {
121702
+ const litValidatorAddr = this.getContractAddressesOrThrow().litActionValidator;
121703
+ const pkpId = position.pkpId;
121704
+ if (litValidatorAddr && pkpId) {
121705
+ try {
121706
+ const litValidator = new Contract(
121707
+ litValidatorAddr,
121708
+ ["function pkpOwners(bytes32) view returns (address)"],
121709
+ this.getProviderOrThrow()
121710
+ );
121711
+ const owner = await litValidator.pkpOwners(
121712
+ pkpId
121713
+ );
121714
+ if (owner && owner !== ZeroAddress) {
121715
+ controller = owner;
121716
+ }
121717
+ } catch {
121718
+ }
121719
+ }
121720
+ } else {
121721
+ controller = position.borrower;
121722
+ if (!controller) {
121723
+ const signerRes = this.contractManager.getSigner();
121724
+ if (signerRes.success) {
121725
+ controller = await signerRes.value.getAddress();
121726
+ }
121727
+ }
121728
+ }
121729
+ if (controller) {
121730
+ const approval = await this.withdrawalAddressModule.assertApprovedForWithdrawal(
121731
+ controller,
121732
+ withdrawalAddress.trim()
121733
+ );
121734
+ if (!approval.success) {
121735
+ return { success: false, error: approval.error.message };
121736
+ }
121737
+ }
121738
+ }
121396
121739
  let pkpPublicKey;
121397
121740
  let pkpEthAddress;
121398
121741
  const pkpCache = this.cacheManager.getCache("pkp-data", {
@@ -122707,6 +123050,78 @@ Error data: ${errorData || "none"}`
122707
123050
  );
122708
123051
  return psm.getAvailableReserves(stablecoinAddress);
122709
123052
  }
123053
+ /**
123054
+ * Execute a PSM stablecoin → UCD swap.
123055
+ * Handles stablecoin approval to the PSM contract if the current allowance is insufficient.
123056
+ *
123057
+ * @param params.stablecoinAddress - ERC-20 address of the stablecoin to swap in
123058
+ * @param params.amountWei - Stablecoin amount in native decimals (bigint)
123059
+ * @param params.minUcdOutWei - Minimum UCD to receive; reverts if below this (1% slippage guard)
123060
+ * @param params.signer - Connected signer for the approval and swap transactions
123061
+ */
123062
+ async psmSwap(params) {
123063
+ const psmAddress = this.config.contractAddresses?.simplePsmV2;
123064
+ if (!psmAddress) {
123065
+ throw new Error(
123066
+ "SimplePSMV2 address not configured \u2014 provide contractAddresses.simplePsmV2"
123067
+ );
123068
+ }
123069
+ const signerAddress = await params.signer.getAddress();
123070
+ const erc20Abi = [
123071
+ "function allowance(address owner, address spender) view returns (uint256)",
123072
+ "function approve(address spender, uint256 amount) returns (bool)"
123073
+ ];
123074
+ const stablecoin = new Contract(params.stablecoinAddress, erc20Abi, params.signer);
123075
+ const allowance = await stablecoin.allowance(signerAddress, psmAddress);
123076
+ if (allowance < params.amountWei) {
123077
+ const approveTx = await stablecoin.approve(psmAddress, MaxUint256);
123078
+ await approveTx.wait();
123079
+ }
123080
+ const psm = SimplePSMV2__factory.connect(psmAddress, params.signer);
123081
+ const tx = await psm.swap(params.stablecoinAddress, params.amountWei, params.minUcdOutWei);
123082
+ const receipt = await tx.wait();
123083
+ if (!receipt)
123084
+ throw new Error("PSM swap transaction receipt unavailable");
123085
+ return { hash: tx.hash, blockNumber: receipt.blockNumber };
123086
+ }
123087
+ /**
123088
+ * Execute a PSM UCD → stablecoin redeem.
123089
+ * Handles UCD approval to UCDController (not PSM) to satisfy the M-4 burn allowance guard:
123090
+ * UCDToken.burn(from, amount) calls _spendAllowance(from, msg.sender=ucdController, amount).
123091
+ *
123092
+ * @param params.stablecoinAddress - ERC-20 address of the stablecoin to receive
123093
+ * @param params.ucdAmountWei - UCD amount to redeem (18 decimals, bigint)
123094
+ * @param params.minStablecoinOutWei - Minimum stablecoin to receive (slippage guard)
123095
+ * @param params.signer - Connected signer
123096
+ */
123097
+ async psmRedeem(params) {
123098
+ const psmAddress = this.config.contractAddresses?.simplePsmV2;
123099
+ const ucdAddress = this.config.contractAddresses?.ucdToken;
123100
+ const ucdControllerAddress = this.config.contractAddresses?.ucdController;
123101
+ if (!psmAddress)
123102
+ throw new Error("SimplePSMV2 address not configured \u2014 provide contractAddresses.simplePsmV2");
123103
+ if (!ucdAddress)
123104
+ throw new Error("UCDToken address not configured \u2014 provide contractAddresses.ucdToken");
123105
+ if (!ucdControllerAddress)
123106
+ throw new Error("UCDController address not configured \u2014 provide contractAddresses.ucdController");
123107
+ const signerAddress = await params.signer.getAddress();
123108
+ const erc20Abi = [
123109
+ "function allowance(address owner, address spender) view returns (uint256)",
123110
+ "function approve(address spender, uint256 amount) returns (bool)"
123111
+ ];
123112
+ const ucdToken = new Contract(ucdAddress, erc20Abi, params.signer);
123113
+ const allowance = await ucdToken.allowance(signerAddress, ucdControllerAddress);
123114
+ if (allowance < params.ucdAmountWei) {
123115
+ const approveTx = await ucdToken.approve(ucdControllerAddress, MaxUint256);
123116
+ await approveTx.wait();
123117
+ }
123118
+ const psm = SimplePSMV2__factory.connect(psmAddress, params.signer);
123119
+ const tx = await psm.redeem(params.stablecoinAddress, params.ucdAmountWei, params.minStablecoinOutWei);
123120
+ const receipt = await tx.wait();
123121
+ if (!receipt)
123122
+ throw new Error("PSM redeem transaction receipt unavailable");
123123
+ return { hash: tx.hash, blockNumber: receipt.blockNumber };
123124
+ }
122710
123125
  /**
122711
123126
  * Wait for the subgraph to index up to (and including) the given block number.
122712
123127
  * Call after on-chain actions (createLoan, mintUCD, etc.) before querying the subgraph.
@@ -123896,6 +124311,7 @@ async function getPositionDelegate(positionId, provider, registryAddress) {
123896
124311
  UCDConversions,
123897
124312
  VALID_LIT_NETWORKS,
123898
124313
  WeiConversions,
124314
+ WithdrawalAddressModule,
123899
124315
  andThen,
123900
124316
  assertProtocolNotPaused,
123901
124317
  assertSafeServiceEndpoint,
@@ -123910,6 +124326,7 @@ async function getPositionDelegate(positionId, provider, registryAddress) {
123910
124326
  createLoanQuery,
123911
124327
  createMockTokenManager,
123912
124328
  createPKPManager,
124329
+ createWithdrawalAddressModule,
123913
124330
  failure,
123914
124331
  fetchProtocolPauseStatus,
123915
124332
  firstSuccess,