@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.mjs CHANGED
@@ -3677,7 +3677,8 @@ var init_deployment_addresses = __esm({
3677
3677
  mockUsdcToken: "0x96409A98e0D322d6566b7F44a0fAbD1BD4ce2AEc",
3678
3678
  mockUsdtToken: "0xF8b7fB38b17a310960E47805Be9adba0b0e0394D",
3679
3679
  PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
3680
- FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374"
3680
+ FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
3681
+ BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe"
3681
3682
  },
3682
3683
  upgraded: {
3683
3684
  PositionManager: {
@@ -3688,11 +3689,11 @@ var init_deployment_addresses = __esm({
3688
3689
  reason: "Shared upgrade script: PositionManager implementation update"
3689
3690
  },
3690
3691
  LoanOperationsManagerModule: {
3691
- previousImplementation: "0x291B412c573a4F52410f09D7Ba82eead17D9a674",
3692
- newImplementation: "0x9DA8d69d7BcF9Fa3ba5734580e8C32618aB52D36",
3693
- upgradedAt: "2026-05-17T20:02:12.883Z",
3692
+ previousImplementation: "0x9DA8d69d7BcF9Fa3ba5734580e8C32618aB52D36",
3693
+ newImplementation: "0x8c20e9Edf44146718F2EF15eEF47A201CaC229B8",
3694
+ upgradedAt: "2026-06-05T10:52:25.179Z",
3694
3695
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
3695
- reason: "Shared upgrade script: LoanOperationsManagerModule implementation update"
3696
+ reason: "audit #3 v1.6.0: LoanOperationsManagerModule \u2014 Chainlink feed-staleness gate (maxBtcFeedAgeBorrow / maxBtcFeedAgeLiquidation)"
3696
3697
  },
3697
3698
  UCDController: {
3698
3699
  previousImplementation: "0x30d0458bE846f4C5D231242eB5a9e9Db68e7232F",
@@ -3751,9 +3752,9 @@ var init_deployment_addresses = __esm({
3751
3752
  reason: "Shared upgrade script: PositionManagerCoreModule implementation update"
3752
3753
  },
3753
3754
  CollateralManagerModule: {
3754
- previousImplementation: "0x428982fCC9A0455c56881B8e21C96B220CC1506B",
3755
- newImplementation: "0x124e61aBff60CC70c4B81ab3019A8A7D35B412d4",
3756
- upgradedAt: "2026-05-17T19:17:01.129Z",
3755
+ previousImplementation: "0x124e61aBff60CC70c4B81ab3019A8A7D35B412d4",
3756
+ newImplementation: "0xd47FE9126daE9A1e0fFdaCf539BE7345D3642bcb",
3757
+ upgradedAt: "2026-06-05T09:14:12.892Z",
3757
3758
  upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
3758
3759
  reason: "Shared upgrade script: CollateralManagerModule implementation update"
3759
3760
  },
@@ -3897,7 +3898,7 @@ var init_deployment_addresses = __esm({
3897
3898
  CIRCUIT_BREAKER_MODULE: "0x3D0B2cAE481821E57BA9CC3807bCC0d0D7F18bd8",
3898
3899
  ADMIN_MODULE: "0xAcd1f07915b17CA3727e7fE89BdF618A1545a1ed",
3899
3900
  UCD_CONTROLLER_IMPL: "0x30d0458bE846f4C5D231242eB5a9e9Db68e7232F",
3900
- LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x9DA8d69d7BcF9Fa3ba5734580e8C32618aB52D36",
3901
+ LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x8c20e9Edf44146718F2EF15eEF47A201CaC229B8",
3901
3902
  TERM_MANAGER_MODULE_IMPL: "0x358d6A7A864853beAA3E157fEB83dCEb1628E8eB",
3902
3903
  CIRCUIT_BREAKER_MODULE_IMPL: "0xF6277dEF72D51312CC99616B5380f34Eb7603D75",
3903
3904
  ADMIN_MODULE_IMPL: "0xBBA86246169f81a307Fafff02C1e3D8456aab973",
@@ -3929,7 +3930,9 @@ var init_deployment_addresses = __esm({
3929
3930
  AGENT_MODULE: "0xefb8C29C1e7e92ed7d81a52dbedaed74e37fe380",
3930
3931
  FEE_RECIPIENT_REGISTRY: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
3931
3932
  FEE_RECIPIENT_REGISTRY_IMPL: "0xd08513a7cB2dd354B26cDDf549616F12054c34c9",
3932
- OPERATION_AUTHORIZATION_REGISTRY_IMPL: "0x9f8072d4672d643e39d8638478e900Fea1f2c81D"
3933
+ OPERATION_AUTHORIZATION_REGISTRY_IMPL: "0x9f8072d4672d643e39d8638478e900Fea1f2c81D",
3934
+ BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe",
3935
+ BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_IMPL: "0xFF270BC4470dBA80430Bd1a3a66EB691599354fA"
3933
3936
  }
3934
3937
  };
3935
3938
  SEPOLIA_CONTRACTS = {
@@ -3956,7 +3959,8 @@ var init_deployment_addresses = __esm({
3956
3959
  mockUsdcToken: "0x96409A98e0D322d6566b7F44a0fAbD1BD4ce2AEc",
3957
3960
  mockUsdtToken: "0xF8b7fB38b17a310960E47805Be9adba0b0e0394D",
3958
3961
  PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
3959
- FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374"
3962
+ FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
3963
+ BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe"
3960
3964
  };
3961
3965
  LOCALHOST_DEPLOYMENT = {
3962
3966
  network: "localhost",
@@ -7272,7 +7276,7 @@ var require_abstract_coder = __commonJS({
7272
7276
  function toObject2(names2, items, deep) {
7273
7277
  if (names2.indexOf(null) >= 0) {
7274
7278
  return items.map((item, index) => {
7275
- if (item instanceof Result10) {
7279
+ if (item instanceof Result11) {
7276
7280
  return toObject2(getNames2(item), item, deep);
7277
7281
  }
7278
7282
  return item;
@@ -7281,7 +7285,7 @@ var require_abstract_coder = __commonJS({
7281
7285
  return names2.reduce((accum, name, index) => {
7282
7286
  let item = items.getValue(name);
7283
7287
  if (!(name in accum)) {
7284
- if (deep && item instanceof Result10) {
7288
+ if (deep && item instanceof Result11) {
7285
7289
  item = toObject2(getNames2(item), item, deep);
7286
7290
  }
7287
7291
  accum[name] = item;
@@ -7289,7 +7293,7 @@ var require_abstract_coder = __commonJS({
7289
7293
  return accum;
7290
7294
  }, {});
7291
7295
  }
7292
- var Result10 = class _Result extends Array {
7296
+ var Result11 = class _Result extends Array {
7293
7297
  // No longer used; but cannot be removed as it will remove the
7294
7298
  // #private field from the .d.ts which may break backwards
7295
7299
  // compatibility
@@ -7493,7 +7497,7 @@ var require_abstract_coder = __commonJS({
7493
7497
  return new _Result(_guard5, items, keys);
7494
7498
  }
7495
7499
  };
7496
- exports2.Result = Result10;
7500
+ exports2.Result = Result11;
7497
7501
  function checkResultErrors2(result) {
7498
7502
  const errors2 = [];
7499
7503
  const checkErrors = function(path2, object2) {
@@ -20184,9 +20188,9 @@ var require_contract = __commonJS({
20184
20188
  function _ContractBase2() {
20185
20189
  return BaseContract2;
20186
20190
  }
20187
- var Contract2 = class extends _ContractBase2() {
20191
+ var Contract3 = class extends _ContractBase2() {
20188
20192
  };
20189
- exports2.Contract = Contract2;
20193
+ exports2.Contract = Contract3;
20190
20194
  }
20191
20195
  });
20192
20196
 
@@ -31451,17 +31455,17 @@ var require_pkg_src = __commonJS({
31451
31455
  }
31452
31456
  },
31453
31457
  btcWithdrawal: {
31454
- cid: "QmbsmTg6RuE6SGUkXqkcXSaWy99ydUtyLoFCBxiHuqpSKC",
31458
+ cid: "QmNqErzpgDUair9bPK7oPQczjKjRcsmcej37izponrEcqp",
31455
31459
  authorizedCidHex: cidToHex(
31456
- "QmbsmTg6RuE6SGUkXqkcXSaWy99ydUtyLoFCBxiHuqpSKC"
31460
+ "QmNqErzpgDUair9bPK7oPQczjKjRcsmcej37izponrEcqp"
31457
31461
  ),
31458
31462
  name: "Btc Withdrawal",
31459
31463
  description: "Production Btc Withdrawal",
31460
31464
  version: "1.0.0",
31461
31465
  deployed: true,
31462
- deployedAt: 1780400560069,
31463
- size: 74485,
31464
- hash: "dc62aa5f52c8ad3c86f8c99f9f08519d036e716554682ccb1f7227ca969df118",
31466
+ deployedAt: 1780651980768,
31467
+ size: 75137,
31468
+ hash: "368f9aea32cf2e660b0f75b88b6ee043cf5956319d7b3c6c695d4b984b3bd555",
31465
31469
  validatorWalletAddress: "0xbb137fbda353199e9419b698c57a742124d4987d",
31466
31470
  pkp: {
31467
31471
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -32334,7 +32338,7 @@ ${errorReport}`);
32334
32338
  }
32335
32339
  init_debug_logger();
32336
32340
  init_session_signature_cache();
32337
- var import_ethers13 = require_lib2();
32341
+ var import_ethers14 = require_lib2();
32338
32342
  var EXPIRED_LOAN_MIN_LIQUIDATION_THRESHOLD_BPS = 11e3;
32339
32343
  var GRACE_PERIOD_DAYS = 30;
32340
32344
  var SATOSHIS_PER_BITCOIN = 100000000n;
@@ -34486,12 +34490,12 @@ ${errorReport}`);
34486
34490
  }
34487
34491
  async function executeVaultSnapshot(params) {
34488
34492
  global.ethers = {
34489
- ...import_ethers13.ethers,
34493
+ ...import_ethers14.ethers,
34490
34494
  providers: {
34491
- StaticJsonRpcProvider: import_ethers13.ethers.JsonRpcProvider
34495
+ StaticJsonRpcProvider: import_ethers14.ethers.JsonRpcProvider
34492
34496
  },
34493
- Contract: import_ethers13.ethers.Contract,
34494
- utils: import_ethers13.ethers
34497
+ Contract: import_ethers14.ethers.Contract,
34498
+ utils: import_ethers14.ethers
34495
34499
  // v6 moved utils to top level
34496
34500
  };
34497
34501
  global.Lit = {
@@ -34759,7 +34763,8 @@ function getSepoliaConfig() {
34759
34763
  bitcoinProviderRegistry: SEPOLIA_CONTRACTS.BitcoinProviderRegistry || "",
34760
34764
  contractVersionRegistry: SEPOLIA_CONTRACTS.ContractVersionRegistry || "",
34761
34765
  feeRecipientRegistry: SEPOLIA_CONTRACTS.FeeRecipientRegistry || "",
34762
- positionDelegateRegistry: SEPOLIA_CONTRACTS.PositionDelegateRegistry || ""
34766
+ positionDelegateRegistry: SEPOLIA_CONTRACTS.PositionDelegateRegistry || "",
34767
+ bitcoinWithdrawalAddressRegistry: SEPOLIA_CONTRACTS.BitcoinWithdrawalAddressRegistry || ""
34763
34768
  },
34764
34769
  subgraphs: {
34765
34770
  // Lazy getter for the same module-init snapshot reason as serviceEndpoint.
@@ -37203,9 +37208,9 @@ var require_ToPrimitive = __commonJS({
37203
37208
  }
37204
37209
  });
37205
37210
 
37206
- // node_modules/es-abstract/2024/ToString.js
37211
+ // node_modules/es-abstract/2025/ToString.js
37207
37212
  var require_ToString = __commonJS({
37208
- "node_modules/es-abstract/2024/ToString.js"(exports2, module2) {
37213
+ "node_modules/es-abstract/2025/ToString.js"(exports2, module2) {
37209
37214
  "use strict";
37210
37215
  var GetIntrinsic = require_get_intrinsic();
37211
37216
  var $String = GetIntrinsic("%String%");
@@ -37226,13 +37231,20 @@ var require_implementation3 = __commonJS({
37226
37231
  var RequireObjectCoercible = require_RequireObjectCoercible();
37227
37232
  var ToString = require_ToString();
37228
37233
  var callBound = require_call_bound();
37234
+ var safeRegexTester = require_safe_regex_test();
37229
37235
  var $replace = callBound("String.prototype.replace");
37236
+ var $charAt = callBound("String.prototype.charAt");
37237
+ var $slice = callBound("String.prototype.slice");
37230
37238
  var mvsIsWS = /^\s$/.test("\u180E");
37231
37239
  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]+/;
37232
- 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]+$/;
37240
+ 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]$/);
37233
37241
  module2.exports = function trim() {
37234
- var S = ToString(RequireObjectCoercible(this));
37235
- return $replace($replace(S, leftWhitespace, ""), rightWhitespace, "");
37242
+ var S = $replace(ToString(RequireObjectCoercible(this)), leftWhitespace, "");
37243
+ var end = S.length;
37244
+ while (end > 0 && isWhitespace($charAt(S, end - 1))) {
37245
+ end -= 1;
37246
+ }
37247
+ return $slice(S, 0, end);
37236
37248
  };
37237
37249
  }
37238
37250
  });
@@ -37485,6 +37497,22 @@ var require_ToObject = __commonJS({
37485
37497
  }
37486
37498
  });
37487
37499
 
37500
+ // node_modules/es-abstract/2024/ToString.js
37501
+ var require_ToString2 = __commonJS({
37502
+ "node_modules/es-abstract/2024/ToString.js"(exports2, module2) {
37503
+ "use strict";
37504
+ var GetIntrinsic = require_get_intrinsic();
37505
+ var $String = GetIntrinsic("%String%");
37506
+ var $TypeError = require_type();
37507
+ module2.exports = function ToString(argument) {
37508
+ if (typeof argument === "symbol") {
37509
+ throw new $TypeError("Cannot convert a Symbol value to a string");
37510
+ }
37511
+ return $String(argument);
37512
+ };
37513
+ }
37514
+ });
37515
+
37488
37516
  // node_modules/array.prototype.findindex/implementation.js
37489
37517
  var require_implementation4 = __commonJS({
37490
37518
  "node_modules/array.prototype.findindex/implementation.js"(exports2, module2) {
@@ -37495,7 +37523,7 @@ var require_implementation4 = __commonJS({
37495
37523
  var LengthOfArrayLike = require_LengthOfArrayLike();
37496
37524
  var ToBoolean = require_ToBoolean();
37497
37525
  var ToObject = require_ToObject();
37498
- var ToString = require_ToString();
37526
+ var ToString = require_ToString2();
37499
37527
  module2.exports = function findIndex(predicate) {
37500
37528
  var O = ToObject(this);
37501
37529
  var len = LengthOfArrayLike(O);
@@ -94255,6 +94283,13 @@ var ZeroAddress = "0x0000000000000000000000000000000000000000";
94255
94283
  // node_modules/ethers/lib.esm/constants/hashes.js
94256
94284
  var ZeroHash = "0x0000000000000000000000000000000000000000000000000000000000000000";
94257
94285
 
94286
+ // node_modules/ethers/lib.esm/constants/numbers.js
94287
+ var N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
94288
+ var WeiPerEther = BigInt("1000000000000000000");
94289
+ var MaxUint256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
94290
+ var MinInt256 = BigInt("0x8000000000000000000000000000000000000000000000000000000000000000") * BigInt(-1);
94291
+ var MaxInt256 = BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
94292
+
94258
94293
  // node_modules/ethers/lib.esm/crypto/signature.js
94259
94294
  var BN_04 = BigInt(0);
94260
94295
  var BN_13 = BigInt(1);
@@ -108788,6 +108823,15 @@ function safeValidateBitcoinAddress(address, network = "regtest") {
108788
108823
  }
108789
108824
  return address;
108790
108825
  }
108826
+ function normalizeBitcoinAddress(address) {
108827
+ if (!address || typeof address !== "string")
108828
+ return address;
108829
+ const trimmed = address.trim();
108830
+ if (/^(bc1|tb1|bcrt1)/i.test(trimmed)) {
108831
+ return trimmed.toLowerCase();
108832
+ }
108833
+ return trimmed;
108834
+ }
108791
108835
 
108792
108836
  // src/protocol/protocol-pause.ts
108793
108837
  var GET_PROTOCOL_PAUSE_STATUS_ABI = [
@@ -108979,6 +109023,21 @@ var LIQUIDATION_MANAGER_ABI = [
108979
109023
  "function canLiquidate(bytes32 positionId) external view returns (bool)",
108980
109024
  "function vrfSeeds(bytes32 positionId) external view returns (uint256)"
108981
109025
  ];
109026
+ var BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_ABI = [
109027
+ "function addAddress(string btcAddress) external",
109028
+ "function removeAddress(string btcAddress) external",
109029
+ "function removeAddressByHash(bytes32 addrHash) external",
109030
+ "function isApproved(address user, string btcAddress) external view returns (bool)",
109031
+ "function isApprovedByHash(address user, bytes32 addrHash) external view returns (bool)",
109032
+ "function isPresent(address user, bytes32 addrHash) external view returns (bool)",
109033
+ "function getAddedAt(address user, bytes32 addrHash) external view returns (uint64)",
109034
+ "function getUsableAt(address user, bytes32 addrHash) external view returns (uint256)",
109035
+ "function getAddressHashes(address user) external view returns (bytes32[])",
109036
+ "function addressCount(address user) external view returns (uint256)",
109037
+ "function addressDelay() external view returns (uint256)",
109038
+ "event AddressAdded(address indexed user, bytes32 indexed addrHash, string btcAddress, uint64 addedAt, uint256 usableAt)",
109039
+ "event AddressRemoved(address indexed user, bytes32 indexed addrHash, string btcAddress)"
109040
+ ];
108982
109041
  var ContractManager = class {
108983
109042
  config;
108984
109043
  contracts = null;
@@ -109039,6 +109098,11 @@ var ContractManager = class {
109039
109098
  contractAddresses.liquidationManager || ZeroAddress,
109040
109099
  LIQUIDATION_MANAGER_ABI,
109041
109100
  contractRunner
109101
+ ),
109102
+ bitcoinWithdrawalAddressRegistry: new Contract(
109103
+ contractAddresses.bitcoinWithdrawalAddressRegistry || ZeroAddress,
109104
+ BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_ABI,
109105
+ contractRunner
109042
109106
  )
109043
109107
  };
109044
109108
  this.contracts = contracts;
@@ -109069,7 +109133,16 @@ var ContractManager = class {
109069
109133
  "loanOperationsManager",
109070
109134
  "termManager",
109071
109135
  "circuitBreaker",
109072
- "liquidationManager"
109136
+ "liquidationManager",
109137
+ // INTENTIONALLY OPTIONAL — do not promote to requiredAddresses.
109138
+ // The on-chain CollateralManager gate is inert while its registry is
109139
+ // address(0) (staged rollout), so pre-v1.3 deployments, browser/default
109140
+ // configs, and tests legitimately omit this address. The SDK's layer-1
109141
+ // early-reject (WithdrawalAddressModule.assertApprovedForWithdrawal)
109142
+ // already no-ops via isConfigured() when the address is absent/ZeroAddress,
109143
+ // and the contract instance defaults to ZeroAddress. Making this required
109144
+ // would throw at init for every config that hasn't deployed the registry.
109145
+ "bitcoinWithdrawalAddressRegistry"
109073
109146
  ];
109074
109147
  const missing = [];
109075
109148
  const invalid = [];
@@ -109182,6 +109255,16 @@ var ContractManager = class {
109182
109255
  }
109183
109256
  return success(contractsResult.value.liquidationManager);
109184
109257
  }
109258
+ /**
109259
+ * Get the BitcoinWithdrawalAddressRegistry contract (per-wallet approved-address allowlist).
109260
+ */
109261
+ getBitcoinWithdrawalAddressRegistry() {
109262
+ const contractsResult = this.getContracts();
109263
+ if (!contractsResult.success) {
109264
+ return contractsResult;
109265
+ }
109266
+ return success(contractsResult.value.bitcoinWithdrawalAddressRegistry);
109267
+ }
109185
109268
  /**
109186
109269
  * Get the provider instance
109187
109270
  */
@@ -111271,6 +111354,168 @@ function createLoanQuery(config) {
111271
111354
  }
111272
111355
  }
111273
111356
 
111357
+ // src/modules/withdrawal-address/withdrawal-address.module.ts
111358
+ var WithdrawalAddressModule = class {
111359
+ config;
111360
+ constructor(config) {
111361
+ this.config = config;
111362
+ }
111363
+ /** Resolve the registry contract, or fail if it isn't configured for this network. */
111364
+ getRegistry() {
111365
+ const res = this.config.contractManager.getBitcoinWithdrawalAddressRegistry();
111366
+ if (!res.success)
111367
+ return res;
111368
+ const target = res.value.target;
111369
+ if (!target || target === ZeroAddress) {
111370
+ return failure(
111371
+ new SDKError({
111372
+ code: "SDK_WITHDRAWAL_REGISTRY_NOT_CONFIGURED",
111373
+ message: "BitcoinWithdrawalAddressRegistry address is not configured for this network",
111374
+ category: "CONFIGURATION" /* CONFIGURATION */,
111375
+ severity: "MEDIUM" /* MEDIUM */
111376
+ })
111377
+ );
111378
+ }
111379
+ return success(res.value);
111380
+ }
111381
+ /** True iff the registry is wired for this network (enforcement is active). */
111382
+ isConfigured() {
111383
+ return this.getRegistry().success;
111384
+ }
111385
+ /** keccak256 of the canonicalized address — matches the on-chain key. */
111386
+ static addressHash(btcAddress) {
111387
+ return keccak256(toUtf8Bytes(normalizeBitcoinAddress(btcAddress)));
111388
+ }
111389
+ /**
111390
+ * Add a Bitcoin address to the caller's allowlist. It becomes usable only
111391
+ * after the registry's delay elapses. Returns the submitted tx.
111392
+ */
111393
+ async addAddress(btcAddress) {
111394
+ const reg = this.getRegistry();
111395
+ if (!reg.success)
111396
+ return reg;
111397
+ try {
111398
+ const tx = await reg.value.addAddress(
111399
+ normalizeBitcoinAddress(btcAddress)
111400
+ );
111401
+ return success(tx);
111402
+ } catch (error2) {
111403
+ return this.txFailure("addAddress", error2, btcAddress);
111404
+ }
111405
+ }
111406
+ /** Remove a Bitcoin address from the caller's allowlist (effective immediately). */
111407
+ async removeAddress(btcAddress) {
111408
+ const reg = this.getRegistry();
111409
+ if (!reg.success)
111410
+ return reg;
111411
+ try {
111412
+ const tx = await reg.value.removeAddress(
111413
+ normalizeBitcoinAddress(btcAddress)
111414
+ );
111415
+ return success(tx);
111416
+ } catch (error2) {
111417
+ return this.txFailure("removeAddress", error2, btcAddress);
111418
+ }
111419
+ }
111420
+ /**
111421
+ * Authoritative contract read: is `btcAddress` approved (present AND past its
111422
+ * delay) for `user`?
111423
+ */
111424
+ async isApproved(user, btcAddress) {
111425
+ const reg = this.getRegistry();
111426
+ if (!reg.success)
111427
+ return reg;
111428
+ try {
111429
+ const ok = await reg.value.isApproved(
111430
+ user,
111431
+ normalizeBitcoinAddress(btcAddress)
111432
+ );
111433
+ return success(ok);
111434
+ } catch (error2) {
111435
+ return this.txFailure("isApproved", error2, btcAddress);
111436
+ }
111437
+ }
111438
+ /**
111439
+ * Read the user's allowlist from the contract: hashes + timestamps + derived
111440
+ * approval state. NOTE: the raw address strings are NOT on-chain — use the
111441
+ * subgraph (WithdrawalAddressBook) to render human-readable addresses.
111442
+ */
111443
+ async getEntries(user) {
111444
+ const reg = this.getRegistry();
111445
+ if (!reg.success)
111446
+ return reg;
111447
+ try {
111448
+ const hashes = await reg.value.getAddressHashes(user);
111449
+ const entries = [];
111450
+ for (const addrHash of hashes) {
111451
+ const addedAt = Number(await reg.value.getAddedAt(user, addrHash));
111452
+ const usableAt = Number(await reg.value.getUsableAt(user, addrHash));
111453
+ const approved = await reg.value.isApprovedByHash(
111454
+ user,
111455
+ addrHash
111456
+ );
111457
+ entries.push({ addrHash, addedAt, usableAt, approved });
111458
+ }
111459
+ return success(entries);
111460
+ } catch (error2) {
111461
+ return this.txFailure("getEntries", error2, user);
111462
+ }
111463
+ }
111464
+ /** The current global delay (seconds) before a newly-added address is usable. */
111465
+ async getAddressDelay() {
111466
+ const reg = this.getRegistry();
111467
+ if (!reg.success)
111468
+ return reg;
111469
+ try {
111470
+ const delay = await reg.value.addressDelay();
111471
+ return success(Number(delay));
111472
+ } catch (error2) {
111473
+ return this.txFailure("addressDelay", error2, "");
111474
+ }
111475
+ }
111476
+ /**
111477
+ * Early-reject guard used by `withdrawBTC`. Resolves to a typed error if the
111478
+ * destination is not approved for `borrower`. When the registry is not
111479
+ * configured for the network, this is a no-op (the on-chain gate remains the
111480
+ * hard guarantee).
111481
+ */
111482
+ async assertApprovedForWithdrawal(borrower, btcAddress) {
111483
+ if (!this.isConfigured())
111484
+ return success(void 0);
111485
+ const res = await this.isApproved(borrower, btcAddress);
111486
+ if (!res.success)
111487
+ return res;
111488
+ if (!res.value) {
111489
+ return failure(
111490
+ new SDKError({
111491
+ code: "SDK_WITHDRAWAL_ADDRESS_NOT_APPROVED",
111492
+ 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.`,
111493
+ category: "VALIDATION" /* VALIDATION */,
111494
+ severity: "MEDIUM" /* MEDIUM */,
111495
+ context: { borrower, btcAddress }
111496
+ })
111497
+ );
111498
+ }
111499
+ return success(void 0);
111500
+ }
111501
+ txFailure(op, error2, context) {
111502
+ const msg = error2 instanceof Error ? error2.message : String(error2);
111503
+ return failure(
111504
+ new SDKError({
111505
+ code: `SDK_WITHDRAWAL_REGISTRY_${op.toUpperCase()}_FAILED`,
111506
+ message: `WithdrawalAddressRegistry.${op} failed: ${msg}`,
111507
+ category: "CONTRACT" /* CONTRACT */,
111508
+ severity: "MEDIUM" /* MEDIUM */,
111509
+ originalError: error2 instanceof Error ? error2 : new Error(String(error2)),
111510
+ context: { op, context }
111511
+ })
111512
+ );
111513
+ }
111514
+ };
111515
+ function createWithdrawalAddressModule(config) {
111516
+ return new WithdrawalAddressModule(config);
111517
+ }
111518
+
111274
111519
  // src/types/branded/domain-values.ts
111275
111520
  var UCD_BRAND = Symbol.for("diamond-hands.UCD");
111276
111521
  var SATOSHIS_BRAND = Symbol.for("diamond-hands.Satoshis");
@@ -117103,6 +117348,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
117103
117348
  loanCreator;
117104
117349
  loanQuery;
117105
117350
  bitcoinOperations;
117351
+ withdrawalAddressModule;
117106
117352
  mockTokenManager;
117107
117353
  graphClient;
117108
117354
  /**
@@ -117286,6 +117532,10 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
117286
117532
  );
117287
117533
  }
117288
117534
  this.contractManager = contractManagerResult.value;
117535
+ this.withdrawalAddressModule = createWithdrawalAddressModule({
117536
+ contractManager: this.contractManager,
117537
+ debug: config.debug
117538
+ });
117289
117539
  this.litOps = new LitOps({
117290
117540
  mode: config.mode || "standalone",
117291
117541
  network: config.litNetwork || DEFAULT_LIT_NETWORK,
@@ -117360,6 +117610,11 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
117360
117610
  );
117361
117611
  }
117362
117612
  const graphHeaders = !serviceMode && config.graphApiKey ? { Authorization: `Bearer ${config.graphApiKey}` } : void 0;
117613
+ if (graphHeaders && typeof window !== "undefined" && typeof window.document !== "undefined") {
117614
+ log.warn(
117615
+ "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."
117616
+ );
117617
+ }
117363
117618
  this.graphClient = new DiamondHandsGraph(
117364
117619
  {
117365
117620
  endpoint: graphEndpoint,
@@ -118171,7 +118426,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
118171
118426
  );
118172
118427
  }
118173
118428
  const chain = this.config.chain || (Number(network2.chainId) === 1 ? "ethereum" : "sepolia");
118174
- const devBitcoinProviderUrl = void 0;
118429
+ const devBitcoinProviderUrl = request.customBitcoinRpcUrl || this.config.bitcoinProviders?.[0]?.url;
118175
118430
  if (this.config.debug) {
118176
118431
  log.info(` Network: ${chain} (chainId: ${network2.chainId})`);
118177
118432
  }
@@ -118217,7 +118472,17 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
118217
118472
  contractAddresses: contracts
118218
118473
  },
118219
118474
  userSignature: auth.signature,
118220
- ...devBitcoinProviderUrl ? { devBitcoinProviderUrl } : {},
118475
+ // lit-ops reads `bitcoinProviderUrl` (request field) and maps it to the
118476
+ // validator's `devBitcoinProviderUrl` jsParam on Hardhat.
118477
+ ...devBitcoinProviderUrl ? { bitcoinProviderUrl: devBitcoinProviderUrl } : {},
118478
+ // Optional override of the mint validator PKP/wallet (e.g. an on-chain-multisig-authorized
118479
+ // validator) — applied to a local copy in lit-ops, never mutating the registry singleton.
118480
+ // When set, authorization is by the on-chain ACTION CID, so the posted code must stay
118481
+ // byte-identical to the registry code (no cache-bust nonce) or the derived CID won't match.
118482
+ ...this.config.mintValidatorOverride ? {
118483
+ validatorOverride: this.config.mintValidatorOverride,
118484
+ disableCacheBust: true
118485
+ } : {},
118221
118486
  rpcUrl: request.rpcUrl || this.config.ethRpcUrl,
118222
118487
  // Pass RPC URL to LIT Action (ngrok for Hardhat)
118223
118488
  ...request.debugOverrides && {
@@ -121233,6 +121498,40 @@ Error data: ${errorData || "none"}`
121233
121498
  this.releaseWriteLock(request.positionId);
121234
121499
  }
121235
121500
  }
121501
+ /**
121502
+ * Access the approved-withdrawal-address allowlist module (self-service
121503
+ * add/remove + reads). The connected wallet manages its OWN addresses; a
121504
+ * newly-added address is only usable after the registry's time-lock delay.
121505
+ */
121506
+ get withdrawalAddresses() {
121507
+ return this.withdrawalAddressModule;
121508
+ }
121509
+ /**
121510
+ * Add a Bitcoin address to the connected wallet's approved-withdrawal allowlist.
121511
+ * Usable only after the registry's delay (default 24h) elapses.
121512
+ */
121513
+ async addApprovedWithdrawalAddress(btcAddress) {
121514
+ return this.withdrawalAddressModule.addAddress(btcAddress);
121515
+ }
121516
+ /** Remove a Bitcoin address from the connected wallet's allowlist (immediate). */
121517
+ async removeApprovedWithdrawalAddress(btcAddress) {
121518
+ return this.withdrawalAddressModule.removeAddress(btcAddress);
121519
+ }
121520
+ /**
121521
+ * Read the connected wallet's (or `user`'s) approved-address entries from the
121522
+ * contract (hashes + timestamps + derived approval state). For human-readable
121523
+ * address strings, query the subgraph `WithdrawalAddressBook`.
121524
+ */
121525
+ async getApprovedWithdrawalAddresses(user) {
121526
+ let target = user;
121527
+ if (!target) {
121528
+ const signerRes = this.contractManager.getSigner();
121529
+ if (!signerRes.success)
121530
+ return signerRes;
121531
+ target = await signerRes.value.getAddress();
121532
+ }
121533
+ return this.withdrawalAddressModule.getEntries(target);
121534
+ }
121236
121535
  /**
121237
121536
  * Withdraw Bitcoin from a position
121238
121537
  *
@@ -121317,6 +121616,48 @@ Error data: ${errorData || "none"}`
121317
121616
  if (this.config.debug) {
121318
121617
  log.info(` Position PKP ID: ${position.pkpId}`);
121319
121618
  }
121619
+ if (this.withdrawalAddressModule.isConfigured()) {
121620
+ const rawStatus = position.status;
121621
+ const isLiquidated = Number(rawStatus) === 5 || String(rawStatus).toUpperCase() === "LIQUIDATED";
121622
+ let controller;
121623
+ if (isLiquidated) {
121624
+ const litValidatorAddr = this.getContractAddressesOrThrow().litActionValidator;
121625
+ const pkpId = position.pkpId;
121626
+ if (litValidatorAddr && pkpId) {
121627
+ try {
121628
+ const litValidator = new Contract(
121629
+ litValidatorAddr,
121630
+ ["function pkpOwners(bytes32) view returns (address)"],
121631
+ this.getProviderOrThrow()
121632
+ );
121633
+ const owner = await litValidator.pkpOwners(
121634
+ pkpId
121635
+ );
121636
+ if (owner && owner !== ZeroAddress) {
121637
+ controller = owner;
121638
+ }
121639
+ } catch {
121640
+ }
121641
+ }
121642
+ } else {
121643
+ controller = position.borrower;
121644
+ if (!controller) {
121645
+ const signerRes = this.contractManager.getSigner();
121646
+ if (signerRes.success) {
121647
+ controller = await signerRes.value.getAddress();
121648
+ }
121649
+ }
121650
+ }
121651
+ if (controller) {
121652
+ const approval = await this.withdrawalAddressModule.assertApprovedForWithdrawal(
121653
+ controller,
121654
+ withdrawalAddress.trim()
121655
+ );
121656
+ if (!approval.success) {
121657
+ return { success: false, error: approval.error.message };
121658
+ }
121659
+ }
121660
+ }
121320
121661
  let pkpPublicKey;
121321
121662
  let pkpEthAddress;
121322
121663
  const pkpCache = this.cacheManager.getCache("pkp-data", {
@@ -122631,6 +122972,78 @@ Error data: ${errorData || "none"}`
122631
122972
  );
122632
122973
  return psm.getAvailableReserves(stablecoinAddress);
122633
122974
  }
122975
+ /**
122976
+ * Execute a PSM stablecoin → UCD swap.
122977
+ * Handles stablecoin approval to the PSM contract if the current allowance is insufficient.
122978
+ *
122979
+ * @param params.stablecoinAddress - ERC-20 address of the stablecoin to swap in
122980
+ * @param params.amountWei - Stablecoin amount in native decimals (bigint)
122981
+ * @param params.minUcdOutWei - Minimum UCD to receive; reverts if below this (1% slippage guard)
122982
+ * @param params.signer - Connected signer for the approval and swap transactions
122983
+ */
122984
+ async psmSwap(params) {
122985
+ const psmAddress = this.config.contractAddresses?.simplePsmV2;
122986
+ if (!psmAddress) {
122987
+ throw new Error(
122988
+ "SimplePSMV2 address not configured \u2014 provide contractAddresses.simplePsmV2"
122989
+ );
122990
+ }
122991
+ const signerAddress = await params.signer.getAddress();
122992
+ const erc20Abi = [
122993
+ "function allowance(address owner, address spender) view returns (uint256)",
122994
+ "function approve(address spender, uint256 amount) returns (bool)"
122995
+ ];
122996
+ const stablecoin = new Contract(params.stablecoinAddress, erc20Abi, params.signer);
122997
+ const allowance = await stablecoin.allowance(signerAddress, psmAddress);
122998
+ if (allowance < params.amountWei) {
122999
+ const approveTx = await stablecoin.approve(psmAddress, MaxUint256);
123000
+ await approveTx.wait();
123001
+ }
123002
+ const psm = SimplePSMV2__factory.connect(psmAddress, params.signer);
123003
+ const tx = await psm.swap(params.stablecoinAddress, params.amountWei, params.minUcdOutWei);
123004
+ const receipt = await tx.wait();
123005
+ if (!receipt)
123006
+ throw new Error("PSM swap transaction receipt unavailable");
123007
+ return { hash: tx.hash, blockNumber: receipt.blockNumber };
123008
+ }
123009
+ /**
123010
+ * Execute a PSM UCD → stablecoin redeem.
123011
+ * Handles UCD approval to UCDController (not PSM) to satisfy the M-4 burn allowance guard:
123012
+ * UCDToken.burn(from, amount) calls _spendAllowance(from, msg.sender=ucdController, amount).
123013
+ *
123014
+ * @param params.stablecoinAddress - ERC-20 address of the stablecoin to receive
123015
+ * @param params.ucdAmountWei - UCD amount to redeem (18 decimals, bigint)
123016
+ * @param params.minStablecoinOutWei - Minimum stablecoin to receive (slippage guard)
123017
+ * @param params.signer - Connected signer
123018
+ */
123019
+ async psmRedeem(params) {
123020
+ const psmAddress = this.config.contractAddresses?.simplePsmV2;
123021
+ const ucdAddress = this.config.contractAddresses?.ucdToken;
123022
+ const ucdControllerAddress = this.config.contractAddresses?.ucdController;
123023
+ if (!psmAddress)
123024
+ throw new Error("SimplePSMV2 address not configured \u2014 provide contractAddresses.simplePsmV2");
123025
+ if (!ucdAddress)
123026
+ throw new Error("UCDToken address not configured \u2014 provide contractAddresses.ucdToken");
123027
+ if (!ucdControllerAddress)
123028
+ throw new Error("UCDController address not configured \u2014 provide contractAddresses.ucdController");
123029
+ const signerAddress = await params.signer.getAddress();
123030
+ const erc20Abi = [
123031
+ "function allowance(address owner, address spender) view returns (uint256)",
123032
+ "function approve(address spender, uint256 amount) returns (bool)"
123033
+ ];
123034
+ const ucdToken = new Contract(ucdAddress, erc20Abi, params.signer);
123035
+ const allowance = await ucdToken.allowance(signerAddress, ucdControllerAddress);
123036
+ if (allowance < params.ucdAmountWei) {
123037
+ const approveTx = await ucdToken.approve(ucdControllerAddress, MaxUint256);
123038
+ await approveTx.wait();
123039
+ }
123040
+ const psm = SimplePSMV2__factory.connect(psmAddress, params.signer);
123041
+ const tx = await psm.redeem(params.stablecoinAddress, params.ucdAmountWei, params.minStablecoinOutWei);
123042
+ const receipt = await tx.wait();
123043
+ if (!receipt)
123044
+ throw new Error("PSM redeem transaction receipt unavailable");
123045
+ return { hash: tx.hash, blockNumber: receipt.blockNumber };
123046
+ }
122634
123047
  /**
122635
123048
  * Wait for the subgraph to index up to (and including) the given block number.
122636
123049
  * Call after on-chain actions (createLoan, mintUCD, etc.) before querying the subgraph.
@@ -123819,6 +124232,7 @@ export {
123819
124232
  UCDConversions,
123820
124233
  VALID_LIT_NETWORKS,
123821
124234
  WeiConversions,
124235
+ WithdrawalAddressModule,
123822
124236
  andThen,
123823
124237
  assertProtocolNotPaused,
123824
124238
  assertSafeServiceEndpoint,
@@ -123833,6 +124247,7 @@ export {
123833
124247
  createLoanQuery,
123834
124248
  createMockTokenManager,
123835
124249
  createPKPManager,
124250
+ createWithdrawalAddressModule,
123836
124251
  DiamondHandsSDK as default,
123837
124252
  failure,
123838
124253
  fetchProtocolPauseStatus,