@gvnrdao/dh-sdk 0.0.332 → 0.0.334

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
@@ -1111,6 +1111,9 @@ var require_pkg_src = __commonJS({
1111
1111
  });
1112
1112
  var index_exports = {};
1113
1113
  __export2(index_exports, {
1114
+ BORROWER_AUTHORIZATION_ENCODE_TYPES: () => BORROWER_AUTHORIZATION_ENCODE_TYPES,
1115
+ BORROWER_AUTHORIZATION_FIELDS: () => BORROWER_AUTHORIZATION_FIELDS,
1116
+ BORROWER_AUTHORIZATION_PRIMARY_TYPES: () => BORROWER_AUTHORIZATION_PRIMARY_TYPES,
1114
1117
  CHIPOTLE_DEPLOYMENTS: () => CHIPOTLE_DEPLOYMENTS,
1115
1118
  DEFAULT_CACHE_CONFIG: () => DEFAULT_CACHE_CONFIG,
1116
1119
  DEFAULT_DEBUG_CONFIG: () => DEFAULT_DEBUG_CONFIG,
@@ -1123,6 +1126,8 @@ var require_pkg_src = __commonJS({
1123
1126
  PerformanceTracker: () => PerformanceTracker,
1124
1127
  RetryStrategy: () => RetryStrategy,
1125
1128
  analyzeError: () => analyzeError,
1129
+ borrowerAuthorizationTypes: () => borrowerAuthorizationTypes,
1130
+ buildBorrowerAuthorizationDomain: () => buildBorrowerAuthorizationDomain,
1126
1131
  calculateDelay: () => calculateDelay,
1127
1132
  cidToHex: () => cidToHex,
1128
1133
  classifyError: () => classifyError,
@@ -1369,30 +1374,30 @@ var require_pkg_src = __commonJS({
1369
1374
  }
1370
1375
  },
1371
1376
  btcTransactionSigner: {
1372
- cid: "QmakWzTce8NH1Jkgv1xwg83Bg9WmF2UG1Mq76pDYDSwwUp",
1377
+ cid: "QmVi1BYdxvCX3QUhXwPtP6FjWMzqSPtXzrS54YsXjTgjYf",
1373
1378
  authorizedCidHex: cidToHex(
1374
- "QmakWzTce8NH1Jkgv1xwg83Bg9WmF2UG1Mq76pDYDSwwUp"
1379
+ "QmVi1BYdxvCX3QUhXwPtP6FjWMzqSPtXzrS54YsXjTgjYf"
1375
1380
  ),
1376
1381
  name: "Btc Transaction Signer",
1377
1382
  description: "Production Btc Transaction Signer",
1378
1383
  version: "1.1.1",
1379
1384
  deployed: true,
1380
- deployedAt: 1786465606156,
1381
- size: 67999,
1382
- hash: "83f3644c68819215e05ba8db3225571354a009458fc1437f606df6cb9142d3f9"
1385
+ deployedAt: 1787923905597,
1386
+ size: 70646,
1387
+ hash: "37c3bb72a660c8275d92e1b73f9482742d86b64789480b9246304c0ca1bab47a"
1383
1388
  },
1384
1389
  ucdMintValidator: {
1385
- cid: "Qmd8jgKRceLvf5aoTtwdXG2JqMoBK5cRJwrvEtQkgvbFbx",
1390
+ cid: "QmUWR5fLiyimLT9TPXpYx3HgwNwkvR6MxjZ7hdeYCFodbc",
1386
1391
  authorizedCidHex: cidToHex(
1387
- "Qmd8jgKRceLvf5aoTtwdXG2JqMoBK5cRJwrvEtQkgvbFbx"
1392
+ "QmUWR5fLiyimLT9TPXpYx3HgwNwkvR6MxjZ7hdeYCFodbc"
1388
1393
  ),
1389
1394
  name: "Ucd Mint Validator",
1390
1395
  description: "Production Ucd Mint Validator",
1391
1396
  version: "1.2.1",
1392
1397
  deployed: true,
1393
- deployedAt: 1786465627201,
1394
- size: 82739,
1395
- hash: "2bdd9aebdaad58a43a4731d5b7284f2531b7a9caaf8caf5719d891c4ed33cb2e",
1398
+ deployedAt: 1787923919527,
1399
+ size: 86197,
1400
+ hash: "c2d80939746cc37f65ef2f63c6a3215b929214a63f10c78144e1f5c98320dabf",
1396
1401
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1397
1402
  pkp: {
1398
1403
  publicKey: "0x041ab17cd91fc5c0b761eea6092d032807561b621b82c488826776e04a9158d61ba64d809a4729f0501289d980732cb06d8dfd06999dd9c8efd2f495dad78b31bb",
@@ -1400,17 +1405,17 @@ var require_pkg_src = __commonJS({
1400
1405
  }
1401
1406
  },
1402
1407
  processPaymentValidator: {
1403
- cid: "QmNXVdysXDhCaQ1uNE2Vgjbuzy6yUEnnVgHzmDfNKXMU6z",
1408
+ cid: "QmXmXuMRAjMLdgKGyTf9KQdGwYrDp8DxkiF44TvSXDf7wF",
1404
1409
  authorizedCidHex: cidToHex(
1405
- "QmNXVdysXDhCaQ1uNE2Vgjbuzy6yUEnnVgHzmDfNKXMU6z"
1410
+ "QmXmXuMRAjMLdgKGyTf9KQdGwYrDp8DxkiF44TvSXDf7wF"
1406
1411
  ),
1407
1412
  name: "Process Payment Validator",
1408
1413
  description: "Production Process Payment Validator",
1409
1414
  version: "1.2.1",
1410
1415
  deployed: true,
1411
- deployedAt: 1786465654796,
1412
- size: 78736,
1413
- hash: "17191ecc9c009e0fa5ab52c876330beb2a9a75d30cccb92e7c0c04f169df088b",
1416
+ deployedAt: 1787923987153,
1417
+ size: 82217,
1418
+ hash: "13defa19614215ab3b1fe88955d69e530d13a09475396af932fe0e213637da2f",
1414
1419
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1415
1420
  pkp: {
1416
1421
  publicKey: "0x04cfccb9b6c7addc79469c0e9fafebef4c70801302c62cdb26b610723a9b8527d23f98a40158c7340d83fd0e62d02b5ec74c12f7a86d98e8c6973b4811110f19ad",
@@ -1418,17 +1423,17 @@ var require_pkg_src = __commonJS({
1418
1423
  }
1419
1424
  },
1420
1425
  extendPositionValidator: {
1421
- cid: "QmYwBsyrhGfHWyRKx549G4tKHxsBLAuRUHcecigeUCkFav",
1426
+ cid: "QmU8h99EEVEsQkxroXiYqLsKZw9gNjE6N5CcTpE9aUc12m",
1422
1427
  authorizedCidHex: cidToHex(
1423
- "QmYwBsyrhGfHWyRKx549G4tKHxsBLAuRUHcecigeUCkFav"
1428
+ "QmU8h99EEVEsQkxroXiYqLsKZw9gNjE6N5CcTpE9aUc12m"
1424
1429
  ),
1425
1430
  name: "Extend Position Validator",
1426
1431
  description: "Production Extend Position Validator",
1427
1432
  version: "1.2.1",
1428
1433
  deployed: true,
1429
- deployedAt: 1786465681874,
1430
- size: 76515,
1431
- hash: "1d4e085335af80f194a663a577876902c83015177e95906a0b461fa93bd5da08",
1434
+ deployedAt: 1787923999294,
1435
+ size: 79975,
1436
+ hash: "31c1aaf883ef22f37681ddb0a4a949be5c05304b6aef178989475a2da935ef9a",
1432
1437
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1433
1438
  pkp: {
1434
1439
  publicKey: "0x04e52338f6a0c3362800f1a94c4c8f08be5030dde0fa217388c53d1c1a4790f4443c9f2886b2d2d8f4b75a9a156e9b028011b1a1cf7648da0e556aa980ec692836",
@@ -1436,17 +1441,17 @@ var require_pkg_src = __commonJS({
1436
1441
  }
1437
1442
  },
1438
1443
  btcWithdrawal: {
1439
- cid: "QmRYVoTTDxk2McvBqxSm9M7YcaBGdTqjnZGPX4Y191DaZh",
1444
+ cid: "QmZQWET9pzrVD4gwQuSzYZmqa24JrUNtnnGFDd513sxMCY",
1440
1445
  authorizedCidHex: cidToHex(
1441
- "QmRYVoTTDxk2McvBqxSm9M7YcaBGdTqjnZGPX4Y191DaZh"
1446
+ "QmZQWET9pzrVD4gwQuSzYZmqa24JrUNtnnGFDd513sxMCY"
1442
1447
  ),
1443
1448
  name: "Btc Withdrawal",
1444
1449
  description: "Production Btc Withdrawal",
1445
1450
  version: "1.2.7",
1446
1451
  deployed: true,
1447
- deployedAt: 1786446046614,
1448
- size: 97456,
1449
- hash: "3cae8250861832f91ee3c573abeb50ff27b9acd34148176071cbfbabb359fc91",
1452
+ deployedAt: 1787924017769,
1453
+ size: 100069,
1454
+ hash: "4f8e27414e4da235e63d6ae1325c63f3d2fb956464515a21aa007a99935f0f13",
1450
1455
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1451
1456
  pkp: {
1452
1457
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -1558,30 +1563,30 @@ var require_pkg_src = __commonJS({
1558
1563
  hash: "03ee5be239c91c735d2c95db89a0d1b77e602cfc18af8eb64b3281fddcd90a72"
1559
1564
  },
1560
1565
  agentModuleExecutor: {
1561
- cid: "QmdhC18wF7PFGMQ8aThdPsEVSpuDewA27dFvbA3bG6kVDQ",
1566
+ cid: "QmcD65vuremot5fsHVgp9JBAmei6gAaEtm5mdtLP7Yt9Kf",
1562
1567
  authorizedCidHex: cidToHex(
1563
- "QmdhC18wF7PFGMQ8aThdPsEVSpuDewA27dFvbA3bG6kVDQ"
1568
+ "QmcD65vuremot5fsHVgp9JBAmei6gAaEtm5mdtLP7Yt9Kf"
1564
1569
  ),
1565
1570
  name: "Agent Module Executor",
1566
1571
  description: "Production Agent Module Executor",
1567
1572
  version: "1.1.1",
1568
1573
  deployed: true,
1569
- deployedAt: 1786446108348,
1570
- size: 11655,
1571
- hash: "d4e2149f843d6c2699fc61114d54b268ba4ed2c46ebdaee1145e0f101ec2a1ec"
1574
+ deployedAt: 1787924032013,
1575
+ size: 13878,
1576
+ hash: "a7f0204700912e26e5a354bee13a1242a2baa218643b3bb22d28481f67f9baf4"
1572
1577
  },
1573
1578
  staleSpendRecoveryValidator: {
1574
- cid: "QmXQWT8V4wjuvH8BbC7xrkYxsVu5AKfvfWcS7jnYfrexYm",
1579
+ cid: "QmNuwo4PT4AikAmhMdZgPWCb2mJDwWa9TnUqrqvofjbrT8",
1575
1580
  authorizedCidHex: cidToHex(
1576
- "QmXQWT8V4wjuvH8BbC7xrkYxsVu5AKfvfWcS7jnYfrexYm"
1581
+ "QmNuwo4PT4AikAmhMdZgPWCb2mJDwWa9TnUqrqvofjbrT8"
1577
1582
  ),
1578
1583
  name: "Stale Spend Recovery Validator",
1579
1584
  description: "Production Stale Spend Recovery Validator",
1580
1585
  version: "1.1.2",
1581
1586
  deployed: true,
1582
- deployedAt: 1785173285829,
1583
- size: 37108,
1584
- hash: "04de5fc5b6f5131dc1544e3d3d187a1f9ef9616ffd12483d119f9102b3671791",
1587
+ deployedAt: 1787924048772,
1588
+ size: 41424,
1589
+ hash: "3c5f028d2bef4344768462993616d45e30d9d44ef126e04d6eb579821d57d99c",
1585
1590
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1586
1591
  pkp: {
1587
1592
  publicKey: "0x046da0ad6da7dd4a0063cbeac6f2bdb6a9889c2178b23470833356a8ee5630f7f0eee0db348d9d9aaaadd23eccf0063c8f68ee5e446abe30b882bf1de4c932bc21",
@@ -1589,17 +1594,17 @@ var require_pkg_src = __commonJS({
1589
1594
  }
1590
1595
  },
1591
1596
  btcUtxoInvalidator: {
1592
- cid: "Qmf4Ze8yhnQhHbnX5RPgJrC7Jw1aA3gbpfpd52kFg7fd1m",
1597
+ cid: "QmaNGeWut7EiGwW4zUc2sFSt7RY5NWFgxYboyG333TwrJf",
1593
1598
  authorizedCidHex: cidToHex(
1594
- "Qmf4Ze8yhnQhHbnX5RPgJrC7Jw1aA3gbpfpd52kFg7fd1m"
1599
+ "QmaNGeWut7EiGwW4zUc2sFSt7RY5NWFgxYboyG333TwrJf"
1595
1600
  ),
1596
1601
  name: "Btc Utxo Invalidator",
1597
1602
  description: "Production Btc Utxo Invalidator",
1598
1603
  version: "1.0.0",
1599
1604
  deployed: true,
1600
- deployedAt: 1786465704240,
1601
- size: 62553,
1602
- hash: "1dcea2b49e545c423195be22e072dc5e3039ed1c95a8490b23505956029f5b33"
1605
+ deployedAt: 1787924133241,
1606
+ size: 66026,
1607
+ hash: "603bc50920d7f1dee77086f2c518d9e2922ab3858a419d3fbea8221ea3a6d9e9"
1603
1608
  }
1604
1609
  };
1605
1610
  function getDeploymentsForNetwork(network) {
@@ -2360,6 +2365,101 @@ ${errorReport}`);
2360
2365
  var SECONDS_PER_DAY = 86400;
2361
2366
  var DAYS_PER_MONTH = 30;
2362
2367
  var LIT_ACTION_ETH_RPC_TIMEOUT_MS = 8e3;
2368
+ var PINNED_CONTRACT_ADDRESSES = {
2369
+ 1: {
2370
+ PositionManager: "0x12A1836e56139ccaD8722B89519d84233efc224B",
2371
+ LoanOperationsManagerModule: "0x2561974A40F1AEed1251d0A090A83cF8536FB9E9",
2372
+ BTCSpendAuthorizer: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
2373
+ BitcoinProviderRegistry: "0x4ab3Fb96e02893Ed6FAa61bad1918390c8DbbFFC",
2374
+ LITActionValidator: "0xD2c5d59c2CC5c409AC65ce0A817236aeC6869512",
2375
+ PositionDelegateRegistry: "0xf0aa2678aD4F60f49e8F7725089B5E86B7F8FE4C"
2376
+ },
2377
+ 11155111: {
2378
+ PositionManager: "0x68e0507D982AEBF1D1C1Af8FBbd842327e2deeFF",
2379
+ LoanOperationsManagerModule: "0x3e05e760a87715207b7F4e8fD35EF7559BcA72C0",
2380
+ BTCSpendAuthorizer: "0xd7E9Eb5eE53f1d9ee55Dc162bBC7486bE437B6bD",
2381
+ BitcoinProviderRegistry: "0xbfA0c48B070D0a9A9CD27469AeacFD2d4261cEE2",
2382
+ LITActionValidator: "0x54eECd7C90F8A8fac27749Ba30BbE8AFBAccc856",
2383
+ PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9"
2384
+ }
2385
+ };
2386
+ function getPinnedContractAddresses(chainId) {
2387
+ return PINNED_CONTRACT_ADDRESSES[chainId] ?? null;
2388
+ }
2389
+ var PROTOCOL_EIP712_DOMAIN_NAME = "DiamondHands.Protocol";
2390
+ var PROTOCOL_EIP712_DOMAIN_VERSION = "1";
2391
+ var BORROWER_AUTHORIZATION_PRIMARY_TYPES = {
2392
+ MINT: "MintRequest",
2393
+ REPAY: "RepayRequest",
2394
+ RENEW: "RenewRequest",
2395
+ WITHDRAW: "WithdrawRequest"
2396
+ };
2397
+ var BORROWER_AUTHORIZATION_FIELDS = {
2398
+ MintRequest: [
2399
+ { name: "positionId", type: "bytes32" },
2400
+ { name: "mintAmount", type: "uint256" },
2401
+ { name: "quantumTimestamp", type: "uint256" }
2402
+ ],
2403
+ RepayRequest: [
2404
+ { name: "positionId", type: "bytes32" },
2405
+ { name: "paymentAmount", type: "uint256" },
2406
+ { name: "quantumTimestamp", type: "uint256" }
2407
+ ],
2408
+ RenewRequest: [
2409
+ { name: "positionId", type: "bytes32" },
2410
+ { name: "selectedTerm", type: "uint256" },
2411
+ { name: "quantumTimestamp", type: "uint256" }
2412
+ ],
2413
+ WithdrawRequest: [
2414
+ { name: "positionId", type: "bytes32" },
2415
+ { name: "totalDeduction", type: "uint256" },
2416
+ { name: "withdrawalAddress", type: "string" },
2417
+ { name: "quantumTimestamp", type: "uint256" }
2418
+ ]
2419
+ };
2420
+ var BORROWER_AUTHORIZATION_ENCODE_TYPES = {
2421
+ MintRequest: "MintRequest(bytes32 positionId,uint256 mintAmount,uint256 quantumTimestamp)",
2422
+ RepayRequest: "RepayRequest(bytes32 positionId,uint256 paymentAmount,uint256 quantumTimestamp)",
2423
+ RenewRequest: "RenewRequest(bytes32 positionId,uint256 selectedTerm,uint256 quantumTimestamp)",
2424
+ WithdrawRequest: "WithdrawRequest(bytes32 positionId,uint256 totalDeduction,string withdrawalAddress,uint256 quantumTimestamp)"
2425
+ };
2426
+ function borrowerAuthorizationTypes(primaryType) {
2427
+ const fields = BORROWER_AUTHORIZATION_FIELDS[primaryType];
2428
+ if (!fields) {
2429
+ throw new Error(
2430
+ `Unknown borrower authorization primary type "${primaryType}"; expected one of ${Object.keys(BORROWER_AUTHORIZATION_FIELDS).join(", ")}`
2431
+ );
2432
+ }
2433
+ return { [primaryType]: fields.map((field) => ({ ...field })) };
2434
+ }
2435
+ function buildBorrowerAuthorizationDomain(chainId, verifyingContractOverride) {
2436
+ if (!Number.isInteger(chainId) || chainId <= 0) {
2437
+ throw new Error(
2438
+ `Borrower authorization domain requires a positive integer chainId, got ${String(chainId)}`
2439
+ );
2440
+ }
2441
+ const pinned = getPinnedContractAddresses(chainId);
2442
+ const pinnedLom = pinned?.LoanOperationsManagerModule;
2443
+ if (pinnedLom && verifyingContractOverride) {
2444
+ if (pinnedLom.toLowerCase() !== verifyingContractOverride.toLowerCase()) {
2445
+ throw new Error(
2446
+ `Refusing a caller-supplied verifyingContract that contradicts the pin for chainId ${chainId}: caller ${verifyingContractOverride}, pinned ${pinnedLom}`
2447
+ );
2448
+ }
2449
+ }
2450
+ const verifyingContract = pinnedLom ?? verifyingContractOverride;
2451
+ if (!verifyingContract) {
2452
+ throw new Error(
2453
+ `No pinned LoanOperationsManagerModule for chainId ${chainId} and no verifyingContract supplied; refusing to build a borrower authorization domain without one`
2454
+ );
2455
+ }
2456
+ return {
2457
+ name: PROTOCOL_EIP712_DOMAIN_NAME,
2458
+ version: PROTOCOL_EIP712_DOMAIN_VERSION,
2459
+ chainId,
2460
+ verifyingContract
2461
+ };
2462
+ }
2363
2463
  var EVMChain = /* @__PURE__ */ ((EVMChain3) => {
2364
2464
  EVMChain3["SEPOLIA"] = "sepolia";
2365
2465
  EVMChain3["ETHEREUM"] = "ethereum";
@@ -4170,11 +4270,11 @@ ${auth.clientId}`;
4170
4270
  );
4171
4271
  const prices = await Promise.race([fetchAll, timeoutPromise]);
4172
4272
  const sorted = [...prices].sort((a, b) => a - b);
4173
- let median;
4273
+ let median2;
4174
4274
  if (this.devSingleProvider) {
4175
- median = sorted[0];
4275
+ median2 = sorted[0];
4176
4276
  } else {
4177
- median = sorted[1];
4277
+ median2 = sorted[1];
4178
4278
  const spread = (sorted[2] - sorted[0]) / sorted[0];
4179
4279
  if (spread > PRICE_ORACLE_TOLERANCE) {
4180
4280
  const names = this.sources.map((s) => s.name).join(", ");
@@ -4184,10 +4284,10 @@ ${auth.clientId}`;
4184
4284
  );
4185
4285
  }
4186
4286
  }
4187
- const priceCents = Math.round(median * 100);
4287
+ const priceCents = Math.round(median2 * 100);
4188
4288
  const priceWith8Decimals = BigInt(priceCents) * 1000000n;
4189
4289
  const totalElapsed = Date.now() - startTime;
4190
- console.log(`[Price Oracle] Median price: $${median.toLocaleString()} \u2014 total time: ${totalElapsed}ms`);
4290
+ console.log(`[Price Oracle] Median price: $${median2.toLocaleString()} \u2014 total time: ${totalElapsed}ms`);
4191
4291
  console.log(`[Price Oracle] Price with 8 decimals: ${priceWith8Decimals}`);
4192
4292
  return priceWith8Decimals;
4193
4293
  }
@@ -5654,7 +5754,7 @@ var init_network_configs = __esm({
5654
5754
  });
5655
5755
 
5656
5756
  // src/modules/diamond-hands-sdk.ts
5657
- import { Contract as Contract9, Interface as Interface5, JsonRpcProvider, AbiCoder as AbiCoder2, keccak256 as keccak2566, solidityPackedKeccak256 as solidityPackedKeccak2565, toUtf8Bytes as toUtf8Bytes6, getBytes as getBytes5, zeroPadValue as zeroPadValue5, toBeHex as toBeHex2, parseEther, formatEther, formatUnits, computeAddress, Signature, ZeroHash, ZeroAddress as ZeroAddress3, MaxUint256 } from "ethers";
5757
+ import { Contract as Contract9, Interface as Interface5, JsonRpcProvider, AbiCoder as AbiCoder2, keccak256 as keccak2565, solidityPackedKeccak256 as solidityPackedKeccak2564, toUtf8Bytes as toUtf8Bytes5, getBytes as getBytes4, zeroPadValue as zeroPadValue5, toBeHex as toBeHex2, parseEther, formatEther, formatUnits, computeAddress, Signature, ZeroHash, ZeroAddress as ZeroAddress3, MaxUint256 } from "ethers";
5658
5758
 
5659
5759
  // src/types/result.ts
5660
5760
  function success(value) {
@@ -6037,33 +6137,94 @@ var SDKError = class _SDKError extends Error {
6037
6137
  };
6038
6138
 
6039
6139
  // src/utils/chunks/eip1559-broadcast.utils.ts
6040
- import { parseUnits } from "ethers";
6140
+ import {
6141
+ getBigInt,
6142
+ parseUnits,
6143
+ toQuantity
6144
+ } from "ethers";
6041
6145
  var MINT_UCD_GAS_CEILING = BigInt(13e5);
6042
6146
  var WITHDRAW_BTC_GAS_CEILING = BigInt(3e6);
6043
6147
  var MAKE_PAYMENT_GAS_CEILING = BigInt(1e6);
6044
6148
  var EXTEND_POSITION_GAS_CEILING = BigInt(1e6);
6045
6149
  var LIQUIDATION_COMMIT_GAS_CEILING = BigInt(1e6);
6046
6150
  var LIQUIDATION_REVEAL_GAS_CEILING = BigInt(2e6);
6047
- async function resolveEip1559FeeFields(provider) {
6048
- const feeData = await provider.getFeeData();
6049
- let maxFeePerGas = feeData.maxFeePerGas ?? void 0;
6050
- let maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? void 0;
6051
- if (!maxFeePerGas || !maxPriorityFeePerGas) {
6052
- const gasPrice = (await provider.getFeeData()).gasPrice ?? parseUnits("1", "gwei");
6053
- maxFeePerGas = maxFeePerGas || gasPrice * 2n;
6054
- maxPriorityFeePerGas = maxPriorityFeePerGas || parseUnits("1.5", "gwei");
6055
- }
6056
- if (maxFeePerGas < maxPriorityFeePerGas) {
6057
- maxFeePerGas = maxPriorityFeePerGas;
6151
+ var PRIORITY_FEE_FLOOR_WEI = parseUnits("0.1", "gwei");
6152
+ var PRIORITY_FEE_CAP_WEI = parseUnits("3", "gwei");
6153
+ var FEE_HISTORY_BLOCK_COUNT = 20;
6154
+ var FEE_HISTORY_REWARD_PERCENTILE = 75;
6155
+ function isJsonRpcSendable(provider) {
6156
+ return typeof provider.send === "function";
6157
+ }
6158
+ function parseFeeHistory(raw) {
6159
+ if (typeof raw !== "object" || raw === null) {
6160
+ throw new Error(`eth_feeHistory returned a non-object result: ${JSON.stringify(raw)}`);
6161
+ }
6162
+ const { baseFeePerGas, reward } = raw;
6163
+ if (!Array.isArray(baseFeePerGas) || baseFeePerGas.length === 0) {
6164
+ throw new Error(
6165
+ `eth_feeHistory returned no baseFeePerGas \u2014 the RPC does not support EIP-1559 fee history: ${JSON.stringify(raw)}`
6166
+ );
6167
+ }
6168
+ if (!Array.isArray(reward) || reward.length === 0) {
6169
+ throw new Error(
6170
+ `eth_feeHistory returned no reward percentiles \u2014 the RPC ignored the rewardPercentiles argument: ${JSON.stringify(raw)}`
6171
+ );
6172
+ }
6173
+ const nextBaseFee = getBigInt(baseFeePerGas[baseFeePerGas.length - 1], "baseFeePerGas");
6174
+ const tips = reward.map((perBlock, i) => {
6175
+ if (!Array.isArray(perBlock) || perBlock.length === 0) {
6176
+ throw new Error(`eth_feeHistory reward row ${i} is empty: ${JSON.stringify(raw)}`);
6177
+ }
6178
+ return getBigInt(perBlock[0], `reward[${i}]`);
6179
+ });
6180
+ return { nextBaseFee, tips };
6181
+ }
6182
+ function median(values) {
6183
+ const sorted = [...values].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
6184
+ const mid = sorted.length >> 1;
6185
+ const hi = sorted[mid];
6186
+ if (hi === void 0) {
6187
+ throw new Error("median: no values");
6188
+ }
6189
+ if (sorted.length % 2 === 1)
6190
+ return hi;
6191
+ const lo = sorted[mid - 1];
6192
+ if (lo === void 0) {
6193
+ throw new Error("median: no values");
6194
+ }
6195
+ return (lo + hi) / 2n;
6196
+ }
6197
+ function clamp(value, floor, cap) {
6198
+ if (value < floor)
6199
+ return floor;
6200
+ if (value > cap)
6201
+ return cap;
6202
+ return value;
6203
+ }
6204
+ async function resolveEip1559FeeFields(feeProvider) {
6205
+ if (!isJsonRpcSendable(feeProvider)) {
6206
+ throw new Error(
6207
+ "resolveEip1559FeeFields: feeProvider must be a JSON-RPC provider exposing send() (the SDK read provider), not a wallet BrowserProvider \u2014 eth_feeHistory is required"
6208
+ );
6058
6209
  }
6210
+ const history = parseFeeHistory(
6211
+ await feeProvider.send("eth_feeHistory", [
6212
+ toQuantity(FEE_HISTORY_BLOCK_COUNT),
6213
+ "latest",
6214
+ [FEE_HISTORY_REWARD_PERCENTILE]
6215
+ ])
6216
+ );
6217
+ const marketTip = median(history.tips);
6218
+ const maxPriorityFeePerGas = clamp(marketTip, PRIORITY_FEE_FLOOR_WEI, PRIORITY_FEE_CAP_WEI);
6219
+ const maxFeePerGas = history.nextBaseFee * 2n + maxPriorityFeePerGas;
6059
6220
  return { maxFeePerGas, maxPriorityFeePerGas };
6060
6221
  }
6061
6222
  async function sendEip1559Transaction(params) {
6062
- const { signer, to, data, gasLimit } = params;
6223
+ const { signer, feeProvider, to, data, gasLimit } = params;
6063
6224
  if (!signer.provider) {
6064
6225
  throw new Error("Signer must have a provider attached");
6065
6226
  }
6066
- const fees = await resolveEip1559FeeFields(signer.provider);
6227
+ const fees = await resolveEip1559FeeFields(feeProvider);
6067
6228
  return signer.sendTransaction({
6068
6229
  to,
6069
6230
  data,
@@ -6265,6 +6426,80 @@ async function awaitSafeSubmissionWindowOnChain(signatureQuantum, chainNow, slee
6265
6426
  return { waited: waitedSeconds > 0, waitedSeconds };
6266
6427
  }
6267
6428
 
6429
+ // src/utils/borrower-authorization-712.ts
6430
+ init_deployment_addresses();
6431
+ import { TypedDataEncoder } from "ethers";
6432
+ var BORROWER_AUTHORIZATION_712_DOMAIN_NAME = "DiamondHands.Protocol";
6433
+ var BORROWER_AUTHORIZATION_712_DOMAIN_VERSION = "1";
6434
+ var BORROWER_AUTHORIZATION_712_FIELDS = {
6435
+ MintRequest: [
6436
+ { name: "positionId", type: "bytes32" },
6437
+ { name: "mintAmount", type: "uint256" },
6438
+ { name: "quantumTimestamp", type: "uint256" }
6439
+ ],
6440
+ RepayRequest: [
6441
+ { name: "positionId", type: "bytes32" },
6442
+ { name: "paymentAmount", type: "uint256" },
6443
+ { name: "quantumTimestamp", type: "uint256" }
6444
+ ],
6445
+ RenewRequest: [
6446
+ { name: "positionId", type: "bytes32" },
6447
+ { name: "selectedTerm", type: "uint256" },
6448
+ { name: "quantumTimestamp", type: "uint256" }
6449
+ ],
6450
+ WithdrawRequest: [
6451
+ { name: "positionId", type: "bytes32" },
6452
+ { name: "totalDeduction", type: "uint256" },
6453
+ { name: "withdrawalAddress", type: "string" },
6454
+ { name: "quantumTimestamp", type: "uint256" }
6455
+ ]
6456
+ };
6457
+ function borrowerAuthorization712Types(primaryType) {
6458
+ const fields = BORROWER_AUTHORIZATION_712_FIELDS[primaryType];
6459
+ if (!fields) {
6460
+ throw new Error(
6461
+ `Unknown borrower authorization primary type "${primaryType}"; expected one of ` + Object.keys(BORROWER_AUTHORIZATION_712_FIELDS).join(", ")
6462
+ );
6463
+ }
6464
+ return { [primaryType]: fields.map((field) => ({ ...field })) };
6465
+ }
6466
+ function buildBorrowerAuthorization712Domain(chainId) {
6467
+ if (!Number.isInteger(chainId) || chainId <= 0) {
6468
+ throw new Error(
6469
+ `Borrower authorization domain requires a positive integer chainId, got ${String(chainId)}`
6470
+ );
6471
+ }
6472
+ const deployment = Object.values(ALL_DEPLOYMENTS).find(
6473
+ (d) => d.chainId === chainId
6474
+ );
6475
+ const verifyingContract = deployment?.contracts?.LoanOperationsManagerModule;
6476
+ if (!verifyingContract) {
6477
+ throw new Error(
6478
+ `No LoanOperationsManagerModule deployment known for chainId ${chainId}; refusing to build a borrower authorization domain without one`
6479
+ );
6480
+ }
6481
+ return {
6482
+ name: BORROWER_AUTHORIZATION_712_DOMAIN_NAME,
6483
+ version: BORROWER_AUTHORIZATION_712_DOMAIN_VERSION,
6484
+ chainId,
6485
+ verifyingContract
6486
+ };
6487
+ }
6488
+ async function signBorrowerAuthorization712(signer, primaryType, chainId, message) {
6489
+ const signTypedData = signer.signTypedData;
6490
+ if (typeof signTypedData !== "function") {
6491
+ throw new Error(
6492
+ `Signer has no signTypedData \u2014 cannot produce an EIP-712 ${primaryType}. Wallets without typed-data support must supply the signature via an authorizationProvider instead of a connected signer.`
6493
+ );
6494
+ }
6495
+ return signTypedData.call(
6496
+ signer,
6497
+ buildBorrowerAuthorization712Domain(chainId),
6498
+ borrowerAuthorization712Types(primaryType),
6499
+ message
6500
+ );
6501
+ }
6502
+
6268
6503
  // src/utils/mint-authorization.utils.ts
6269
6504
  var PKP_NFT_ABI = [
6270
6505
  "function getPubkey(uint256 tokenId) external view returns (bytes memory)"
@@ -6278,29 +6513,11 @@ async function generateMintAuthorization(positionId, amount, chainId, signerOrPr
6278
6513
  const signer = signerOrPrecomputed;
6279
6514
  const timestamp = calculateNextQuantumTimestamp();
6280
6515
  const action = "mint-ucd";
6281
- const actionHash = keccak256(toUtf8Bytes(action));
6282
- const types = [
6283
- "bytes32",
6284
- // positionId
6285
- "uint256",
6286
- // timestamp
6287
- "uint256",
6288
- // chainId
6289
- "uint256",
6290
- // amount
6291
- "bytes32"
6292
- // actionHash
6293
- ];
6294
- const values = [
6516
+ const signature = await signBorrowerAuthorization712(signer, "MintRequest", chainId, {
6295
6517
  positionId,
6296
- timestamp,
6297
- chainId,
6298
- amount.toString(),
6299
- actionHash
6300
- ];
6301
- const messageHash = solidityPackedKeccak256(types, values);
6302
- const messageHashBytes = getBytes(messageHash);
6303
- const signature = await signer.signMessage(messageHashBytes);
6518
+ mintAmount: amount.toString(),
6519
+ quantumTimestamp: timestamp
6520
+ });
6304
6521
  return {
6305
6522
  positionId,
6306
6523
  timestamp,
@@ -6337,44 +6554,17 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signerO
6337
6554
  throw new Error(`timestamp must be a number, got ${typeof timestamp}`);
6338
6555
  }
6339
6556
  const action = "make-payment";
6340
- const actionHash = keccak256(toUtf8Bytes(action));
6341
- if (typeof actionHash !== "string") {
6342
- throw new Error(`actionHash must be a string, got ${typeof actionHash}`);
6343
- }
6344
- const types = [
6345
- "bytes32",
6346
- // positionId
6347
- "uint256",
6348
- // timestamp
6349
- "uint256",
6350
- // chainId
6351
- "uint256",
6352
- // amount
6353
- "bytes32"
6354
- // actionHash
6355
- ];
6356
6557
  const amountStr = amount.toString();
6357
- if (typeof amountStr !== "string") {
6358
- throw new Error(
6359
- `amount.toString() must return a string, got ${typeof amountStr}`
6360
- );
6361
- }
6362
- const values = [positionId, timestamp, chainId, amountStr, actionHash];
6363
- for (let i = 0; i < values.length; i++) {
6364
- if (typeof values[i] === "object" && values[i] !== null) {
6365
- throw new Error(
6366
- `Value at index ${i} is an object: ${JSON.stringify(values[i])}`
6367
- );
6368
- }
6369
- }
6370
- const messageHash = solidityPackedKeccak256(types, values);
6371
- const messageHashBytes = getBytes(messageHash);
6372
- const signature = await signer.signMessage(messageHashBytes);
6558
+ const signature = await signBorrowerAuthorization712(signer, "RepayRequest", chainId, {
6559
+ positionId,
6560
+ paymentAmount: amountStr,
6561
+ quantumTimestamp: timestamp
6562
+ });
6373
6563
  return {
6374
6564
  positionId,
6375
6565
  timestamp,
6376
6566
  chainId,
6377
- amount: amount.toString(),
6567
+ amount: amountStr,
6378
6568
  action,
6379
6569
  signature
6380
6570
  };
@@ -6461,32 +6651,12 @@ async function generateWithdrawAuthorization(positionId, amount, chainId, signer
6461
6651
  const signer = signerOrPrecomputed;
6462
6652
  const timestamp = calculateNextQuantumTimestamp();
6463
6653
  const action = "withdraw-btc";
6464
- const actionHash = keccak256(toUtf8Bytes(action));
6465
- const types = [
6466
- "bytes32",
6467
- // positionId
6468
- "uint256",
6469
- // timestamp
6470
- "uint256",
6471
- // chainId
6472
- "uint256",
6473
- // amount (in satoshis)
6474
- "string",
6475
- // destinationAddress (Bitcoin address)
6476
- "bytes32"
6477
- // actionHash
6478
- ];
6479
- const values = [
6654
+ const signature = await signBorrowerAuthorization712(signer, "WithdrawRequest", chainId, {
6480
6655
  positionId,
6481
- timestamp,
6482
- chainId,
6483
- amount.toString(),
6484
- destinationAddress,
6485
- actionHash
6486
- ];
6487
- const messageHash = solidityPackedKeccak256(types, values);
6488
- const messageHashBytes = getBytes(messageHash);
6489
- const signature = await signer.signMessage(messageHashBytes);
6656
+ totalDeduction: amount.toString(),
6657
+ withdrawalAddress: destinationAddress,
6658
+ quantumTimestamp: timestamp
6659
+ });
6490
6660
  return {
6491
6661
  positionId,
6492
6662
  timestamp,
@@ -6528,7 +6698,6 @@ async function generateBalanceConfirmationAuthorization(positionId, chainId, sig
6528
6698
  }
6529
6699
 
6530
6700
  // src/utils/extend-authorization.utils.ts
6531
- import { keccak256 as keccak2562, toUtf8Bytes as toUtf8Bytes2, solidityPackedKeccak256 as solidityPackedKeccak2562, getBytes as getBytes2 } from "ethers";
6532
6701
  async function generateExtendAuthorization(positionId, newTerm, chainId, signerOrPrecomputed) {
6533
6702
  if (typeof signerOrPrecomputed === "object" && "signature" in signerOrPrecomputed && !("signMessage" in signerOrPrecomputed)) {
6534
6703
  const { timestamp: timestamp2, signature: signature2 } = signerOrPrecomputed;
@@ -6538,29 +6707,11 @@ async function generateExtendAuthorization(positionId, newTerm, chainId, signerO
6538
6707
  const signer = signerOrPrecomputed;
6539
6708
  const timestamp = calculateNextQuantumTimestamp();
6540
6709
  const action = "extend-position";
6541
- const actionHash = keccak2562(toUtf8Bytes2(action));
6542
- const types = [
6543
- "bytes32",
6544
- // positionId
6545
- "uint256",
6546
- // timestamp
6547
- "uint256",
6548
- // chainId
6549
- "uint256",
6550
- // newTerm (extension term in months)
6551
- "bytes32"
6552
- // actionHash
6553
- ];
6554
- const values = [
6710
+ const signature = await signBorrowerAuthorization712(signer, "RenewRequest", chainId, {
6555
6711
  positionId,
6556
- timestamp,
6557
- chainId,
6558
- newTerm,
6559
- actionHash
6560
- ];
6561
- const messageHash = solidityPackedKeccak2562(types, values);
6562
- const messageHashBytes = getBytes2(messageHash);
6563
- const signature = await signer.signMessage(messageHashBytes);
6712
+ selectedTerm: newTerm,
6713
+ quantumTimestamp: timestamp
6714
+ });
6564
6715
  return {
6565
6716
  positionId,
6566
6717
  timestamp,
@@ -7501,10 +7652,10 @@ async function reconcileAuthorizedSpend(spend, esploraBaseUrl, httpGetJson = def
7501
7652
 
7502
7653
  // src/utils/stale-spend-invalidate-message.ts
7503
7654
  import {
7504
- keccak256 as keccak2563,
7505
- toUtf8Bytes as toUtf8Bytes3,
7506
- solidityPackedKeccak256 as solidityPackedKeccak2563,
7507
- getBytes as getBytes3,
7655
+ keccak256 as keccak2562,
7656
+ toUtf8Bytes as toUtf8Bytes2,
7657
+ solidityPackedKeccak256 as solidityPackedKeccak2562,
7658
+ getBytes as getBytes2,
7508
7659
  zeroPadValue
7509
7660
  } from "ethers";
7510
7661
  var RECOVERY_INVALIDATE_ACTION = "btc-utxo-invalidator";
@@ -7515,8 +7666,8 @@ function buildInvalidateMessageHash(params) {
7515
7666
  params.positionId.startsWith("0x") ? params.positionId : `0x${params.positionId}`,
7516
7667
  32
7517
7668
  );
7518
- const actionHash = keccak2563(toUtf8Bytes3(RECOVERY_INVALIDATE_ACTION));
7519
- return solidityPackedKeccak2563(
7669
+ const actionHash = keccak2562(toUtf8Bytes2(RECOVERY_INVALIDATE_ACTION));
7670
+ return solidityPackedKeccak2562(
7520
7671
  [
7521
7672
  "bytes32",
7522
7673
  // positionId
@@ -7562,7 +7713,7 @@ async function buildInvalidateStaleSpendEnvelope(params) {
7562
7713
  utxoTxid,
7563
7714
  utxoVout
7564
7715
  });
7565
- const signature = await signer.signMessage(getBytes3(messageHash));
7716
+ const signature = await signer.signMessage(getBytes2(messageHash));
7566
7717
  const borrowerAddress = await signer.getAddress();
7567
7718
  return {
7568
7719
  positionId,
@@ -7577,7 +7728,7 @@ async function buildInvalidateStaleSpendEnvelope(params) {
7577
7728
  }
7578
7729
 
7579
7730
  // src/utils/btc-withdrawal-message.ts
7580
- import { keccak256 as keccak2564, toUtf8Bytes as toUtf8Bytes4, solidityPackedKeccak256 as solidityPackedKeccak2564, getBytes as getBytes4, zeroPadValue as zeroPadValue2 } from "ethers";
7731
+ import { keccak256 as keccak2563, toUtf8Bytes as toUtf8Bytes3, solidityPackedKeccak256 as solidityPackedKeccak2563, getBytes as getBytes3, zeroPadValue as zeroPadValue2 } from "ethers";
7581
7732
  var QUANTUM_SECONDS2 = 60;
7582
7733
  var QUANTUM_SAFE_THRESHOLD2 = 40;
7583
7734
  function hashBtcInputSet(utxos) {
@@ -7608,7 +7759,7 @@ function hashBtcInputSet(utxos) {
7608
7759
  seen.add(key);
7609
7760
  }
7610
7761
  const canonical = normalized.sort((a, b) => a.txid < b.txid ? -1 : a.txid > b.txid ? 1 : a.vout - b.vout).map((u) => `${u.txid}:${u.vout}:${u.value}`).join("|");
7611
- return keccak2564(toUtf8Bytes4(canonical));
7762
+ return keccak2563(toUtf8Bytes3(canonical));
7612
7763
  }
7613
7764
  async function buildBtcExecuteEnvelope(params) {
7614
7765
  const {
@@ -7653,15 +7804,15 @@ async function buildBtcExecuteEnvelope(params) {
7653
7804
  } else {
7654
7805
  timestamp = currentQuantumStart;
7655
7806
  }
7656
- const actionHash = keccak2564(
7657
- toUtf8Bytes4("execute-btc-withdrawal")
7807
+ const actionHash = keccak2563(
7808
+ toUtf8Bytes3("execute-btc-withdrawal")
7658
7809
  );
7659
7810
  const utxoIdentifier = `${txid}:${vout}`;
7660
7811
  const positionIdBytes32 = zeroPadValue2(
7661
7812
  positionId.startsWith("0x") ? positionId : `0x${positionId}`,
7662
7813
  32
7663
7814
  );
7664
- const messageHash = solidityPackedKeccak2564(
7815
+ const messageHash = solidityPackedKeccak2563(
7665
7816
  [
7666
7817
  "bytes32",
7667
7818
  // positionId
@@ -7694,7 +7845,7 @@ async function buildBtcExecuteEnvelope(params) {
7694
7845
  actionHash
7695
7846
  ]
7696
7847
  );
7697
- const userSignature = await signer.signMessage(getBytes4(messageHash));
7848
+ const userSignature = await signer.signMessage(getBytes3(messageHash));
7698
7849
  const borrowerAddress = await signer.getAddress();
7699
7850
  return {
7700
7851
  positionId,
@@ -10795,7 +10946,8 @@ function createLoanQuery(config) {
10795
10946
  }
10796
10947
 
10797
10948
  // src/modules/withdrawal-address/withdrawal-address.module.ts
10798
- import { keccak256 as keccak2565, toUtf8Bytes as toUtf8Bytes5, ZeroAddress as ZeroAddress2 } from "ethers";
10949
+ import { keccak256 as keccak2564, toUtf8Bytes as toUtf8Bytes4, ZeroAddress as ZeroAddress2 } from "ethers";
10950
+ var STATIC_CALL_DIAGNOSTIC_TIMEOUT_MS = 5e3;
10799
10951
  var WithdrawalAddressModule = class {
10800
10952
  config;
10801
10953
  graphClient;
@@ -10830,7 +10982,7 @@ var WithdrawalAddressModule = class {
10830
10982
  }
10831
10983
  /** keccak256 of the canonicalized address — matches the on-chain key. */
10832
10984
  static addressHash(btcAddress) {
10833
- return keccak2565(toUtf8Bytes5(normalizeBitcoinAddress(btcAddress)));
10985
+ return keccak2564(toUtf8Bytes4(normalizeBitcoinAddress(btcAddress)));
10834
10986
  }
10835
10987
  /**
10836
10988
  * Add a Bitcoin address to the caller's allowlist. It becomes usable only
@@ -10840,13 +10992,17 @@ var WithdrawalAddressModule = class {
10840
10992
  const reg = this.getRegistry();
10841
10993
  if (!reg.success)
10842
10994
  return reg;
10995
+ const normalized = normalizeBitcoinAddress(btcAddress);
10843
10996
  try {
10844
- const tx = await reg.value.addAddress(
10845
- normalizeBitcoinAddress(btcAddress)
10846
- );
10997
+ const tx = await reg.value.addAddress(normalized);
10847
10998
  return success(tx);
10848
10999
  } catch (error) {
10849
- return this.txFailure("addAddress", error, btcAddress);
11000
+ return this.txFailure(
11001
+ "addAddress",
11002
+ error,
11003
+ btcAddress,
11004
+ await this.staticCallDiagnostic(reg.value, "addAddress", normalized)
11005
+ );
10850
11006
  }
10851
11007
  }
10852
11008
  /** Remove a Bitcoin address from the caller's allowlist (effective immediately). */
@@ -10854,13 +11010,17 @@ var WithdrawalAddressModule = class {
10854
11010
  const reg = this.getRegistry();
10855
11011
  if (!reg.success)
10856
11012
  return reg;
11013
+ const normalized = normalizeBitcoinAddress(btcAddress);
10857
11014
  try {
10858
- const tx = await reg.value.removeAddress(
10859
- normalizeBitcoinAddress(btcAddress)
10860
- );
11015
+ const tx = await reg.value.removeAddress(normalized);
10861
11016
  return success(tx);
10862
11017
  } catch (error) {
10863
- return this.txFailure("removeAddress", error, btcAddress);
11018
+ return this.txFailure(
11019
+ "removeAddress",
11020
+ error,
11021
+ btcAddress,
11022
+ await this.staticCallDiagnostic(reg.value, "removeAddress", normalized)
11023
+ );
10864
11024
  }
10865
11025
  }
10866
11026
  /**
@@ -10956,16 +11116,59 @@ var WithdrawalAddressModule = class {
10956
11116
  }
10957
11117
  return success(void 0);
10958
11118
  }
10959
- txFailure(op, error, context) {
11119
+ /**
11120
+ * Ask the node for the reason a failed write did not carry.
11121
+ *
11122
+ * A failing `eth_estimateGas` frequently answers with NOTHING to decode — ethers renders that
11123
+ * as `missing revert data ... data=null, reason=null, revert=null`, which names no cause and
11124
+ * cannot distinguish "the contract rejected this" from "the RPC hiccuped". An `eth_call` of the
11125
+ * same calldata usually does carry the revert reason or custom-error selector, so this runs one
11126
+ * and folds the answer into the reported error.
11127
+ *
11128
+ * Three deliberate properties:
11129
+ *
11130
+ * 1. It runs ONLY after the write has already failed. Gating the write on a static call would
11131
+ * let a flaky endpoint — precisely the condition this exists to diagnose — block an add that
11132
+ * would otherwise have succeeded.
11133
+ * 2. It costs NO extra signature. `staticCall` is `eth_call`: a node read, never a wallet prompt.
11134
+ * 3. It can never throw. A diagnostic that escapes would replace the real cause with itself.
11135
+ * (The `try/catch` here is the authorized exception to CLAUDE.md's forbidden-patterns rule;
11136
+ * it swallows nothing — every branch returns text that is reported alongside the original.)
11137
+ *
11138
+ * A static call that SUCCEEDS is itself a finding: the contract accepts this call, so the
11139
+ * failure lay outside contract logic (RPC, gas, or nonce).
11140
+ */
11141
+ async staticCallDiagnostic(registry, op, normalizedAddress) {
11142
+ try {
11143
+ await Promise.race([
11144
+ registry[op].staticCall(normalizedAddress),
11145
+ // The failure being diagnosed is often an unresponsive endpoint, so the diagnostic must
11146
+ // not inherit that hang — the user is waiting on this error message.
11147
+ new Promise(
11148
+ (_, reject) => setTimeout(
11149
+ () => reject(new Error("static call timed out after 5s")),
11150
+ STATIC_CALL_DIAGNOSTIC_TIMEOUT_MS
11151
+ )
11152
+ )
11153
+ ]);
11154
+ return "static call SUCCEEDED \u2014 the contract accepts this call, so the failure was not contract logic (RPC, gas, or nonce)";
11155
+ } catch (diagnostic) {
11156
+ const code = typeof diagnostic === "object" && diagnostic !== null ? diagnostic.code : void 0;
11157
+ const msg = diagnostic instanceof Error ? diagnostic.message : String(diagnostic);
11158
+ return typeof code === "string" ? `static call reverted [${code}]: ${msg}` : `static call failed: ${msg}`;
11159
+ }
11160
+ }
11161
+ txFailure(op, error, context, diagnostic) {
10960
11162
  const msg = error instanceof Error ? error.message : String(error);
11163
+ const detail = diagnostic ? `${msg} \u2014 ${diagnostic}` : msg;
10961
11164
  return failure(
10962
11165
  new SDKError({
10963
11166
  code: `SDK_WITHDRAWAL_REGISTRY_${op.toUpperCase()}_FAILED`,
10964
- message: `WithdrawalAddressRegistry.${op} failed: ${msg}`,
11167
+ message: `WithdrawalAddressRegistry.${op} failed: ${detail}`,
10965
11168
  category: "CONTRACT" /* CONTRACT */,
10966
11169
  severity: "MEDIUM" /* MEDIUM */,
10967
11170
  originalError: error instanceof Error ? error : new Error(String(error)),
10968
- context: { op, context }
11171
+ context: { op, context, diagnostic }
10969
11172
  })
10970
11173
  );
10971
11174
  }
@@ -12056,6 +12259,47 @@ function normalizePkpId2(pkpId) {
12056
12259
  }
12057
12260
  return pkpId;
12058
12261
  }
12262
+ function applyLoanEventsFilter(events, opts) {
12263
+ const { wantsEvent, fromTimestamp, toTimestamp, fromBlock, toBlock, limit } = opts;
12264
+ const inBounds = (e) => {
12265
+ const ts = e?.timestamp;
12266
+ const bn = e?.blockNumber;
12267
+ try {
12268
+ if (fromTimestamp !== void 0 && ts !== void 0 && BigInt(ts) < BigInt(fromTimestamp))
12269
+ return false;
12270
+ if (toTimestamp !== void 0 && ts !== void 0 && BigInt(ts) > BigInt(toTimestamp))
12271
+ return false;
12272
+ if (fromBlock !== void 0 && bn !== void 0 && BigInt(bn) < BigInt(fromBlock))
12273
+ return false;
12274
+ if (toBlock !== void 0 && bn !== void 0 && BigInt(bn) > BigInt(toBlock))
12275
+ return false;
12276
+ } catch {
12277
+ return true;
12278
+ }
12279
+ return true;
12280
+ };
12281
+ const narrow = (list, kind) => wantsEvent(kind) ? (list ?? []).filter(inBounds).slice(0, limit) : [];
12282
+ const single = (value, kind) => value && wantsEvent(kind) && inBounds(value) ? value : void 0;
12283
+ const filtered = {
12284
+ ...events,
12285
+ positionCreated: single(events.positionCreated, "positionCreated"),
12286
+ payments: narrow(events.payments, "payment"),
12287
+ statusUpdates: narrow(events.statusUpdates, "status"),
12288
+ liquidation: single(events.liquidation, "liquidation"),
12289
+ mints: narrow(events.mints, "mint"),
12290
+ withdrawals: narrow(events.withdrawals, "withdrawal"),
12291
+ renewals: narrow(events.renewals, "renewal"),
12292
+ operationFailures: narrow(events.operationFailures, "operationFailure"),
12293
+ mintRequests: narrow(events.mintRequests, "mintRequest"),
12294
+ burnRequests: narrow(events.burnRequests, "burnRequest"),
12295
+ collateralEvents: narrow(events.collateralEvents, "collateralEvent"),
12296
+ mintingFees: narrow(events.mintingFees, "mintingFee"),
12297
+ renewalFees: narrow(events.renewalFees, "renewalFee"),
12298
+ totalEvents: 0
12299
+ };
12300
+ filtered.totalEvents = (filtered.positionCreated ? 1 : 0) + (filtered.liquidation ? 1 : 0) + filtered.payments.length + filtered.statusUpdates.length + filtered.mints.length + filtered.withdrawals.length + filtered.renewals.length + filtered.operationFailures.length + filtered.mintRequests.length + filtered.burnRequests.length + filtered.collateralEvents.length + filtered.mintingFees.length + filtered.renewalFees.length;
12301
+ return filtered;
12302
+ }
12059
12303
  function hasLoanEventsFilter(filter) {
12060
12304
  if (!filter)
12061
12305
  return false;
@@ -13212,32 +13456,24 @@ var DiamondHandsGraph = class {
13212
13456
  limit = 1e3,
13213
13457
  orderDirection = "desc"
13214
13458
  } = filter || {};
13459
+ const wantsEvent = (kind) => !eventTypes || eventTypes.includes(kind);
13460
+ const hasBounds = fromTimestamp !== void 0 || toTimestamp !== void 0 || fromBlock !== void 0 || toBlock !== void 0;
13461
+ const pageSize = hasBounds ? THE_GRAPH_MAX_BATCH_SIZE : limit;
13462
+ const buildPositionWhereClause = () => `where: { position: "${positionId.toLowerCase()}" }`;
13215
13463
  const shouldQuery = {
13216
- positionCreated: !eventTypes || eventTypes.includes("positionCreated"),
13217
- payment: !eventTypes || eventTypes.includes("payment"),
13218
- status: !eventTypes || eventTypes.includes("status"),
13219
- liquidation: !eventTypes || eventTypes.includes("liquidation"),
13220
- mint: !eventTypes || eventTypes.includes("mint"),
13221
- withdrawal: !eventTypes || eventTypes.includes("withdrawal"),
13222
- renewal: !eventTypes || eventTypes.includes("renewal"),
13223
- operationFailure: !eventTypes || eventTypes.includes("operationFailure"),
13224
- mintRequest: !eventTypes || eventTypes.includes("mintRequest"),
13225
- burnRequest: !eventTypes || eventTypes.includes("burnRequest"),
13226
- collateralEvent: !eventTypes || eventTypes.includes("collateralEvent"),
13227
- mintingFee: !eventTypes || eventTypes.includes("mintingFee"),
13228
- renewalFee: !eventTypes || eventTypes.includes("renewalFee")
13229
- };
13230
- const buildPositionWhereClause = () => {
13231
- const conditions = [`position: "${positionId.toLowerCase()}"`];
13232
- if (fromTimestamp)
13233
- conditions.push(`timestamp_gte: "${fromTimestamp}"`);
13234
- if (toTimestamp)
13235
- conditions.push(`timestamp_lte: "${toTimestamp}"`);
13236
- if (fromBlock)
13237
- conditions.push(`blockNumber_gte: "${fromBlock}"`);
13238
- if (toBlock)
13239
- conditions.push(`blockNumber_lte: "${toBlock}"`);
13240
- return `where: { ${conditions.join(", ")} }`;
13464
+ positionCreated: true,
13465
+ payment: true,
13466
+ status: true,
13467
+ liquidation: true,
13468
+ mint: true,
13469
+ withdrawal: true,
13470
+ renewal: true,
13471
+ operationFailure: true,
13472
+ mintRequest: true,
13473
+ burnRequest: true,
13474
+ collateralEvent: true,
13475
+ mintingFee: true,
13476
+ renewalFee: true
13241
13477
  };
13242
13478
  const query = `
13243
13479
  query GetLoanEvents($positionId: Bytes!, $limit: Int!, $orderDirection: OrderDirection!) {
@@ -13473,11 +13709,41 @@ var DiamondHandsGraph = class {
13473
13709
  `;
13474
13710
  const variables = {
13475
13711
  positionId: positionId.toLowerCase(),
13476
- limit,
13712
+ limit: pageSize,
13477
13713
  orderDirection
13478
13714
  };
13479
13715
  const result = await this.client.execute(query, variables);
13480
- return this.assembleLoanEvents(positionId, result);
13716
+ if (hasBounds) {
13717
+ const collections = [
13718
+ ["payments", result.position?.payments],
13719
+ ["statusUpdates", result.position?.statusUpdates],
13720
+ ["withdrawals", result.position?.withdrawals],
13721
+ ["renewals", result.position?.renewals],
13722
+ ["operationFailures", result.position?.operationFailures],
13723
+ ["mintRequests", result.position?.mintRequests],
13724
+ ["burnRequests", result.position?.burnRequests],
13725
+ ["mintingFees", result.position?.mintingFees],
13726
+ ["renewalFees", result.position?.renewalFees],
13727
+ ["mints", result.ucdmintEvents],
13728
+ ["collateralEvents", result.collateralEvents]
13729
+ ];
13730
+ const saturated = collections.filter(([, list]) => (list?.length ?? 0) >= pageSize).map(([name]) => name);
13731
+ if (saturated.length > 0) {
13732
+ log.warn(
13733
+ "[DiamondHandsGraph] bounded getLoanEvents page saturated \u2014 the filtered history may be incomplete",
13734
+ { positionId, pageSize, saturated }
13735
+ );
13736
+ }
13737
+ }
13738
+ const assembled = this.assembleLoanEvents(positionId, result);
13739
+ return applyLoanEventsFilter(assembled, {
13740
+ wantsEvent,
13741
+ fromTimestamp,
13742
+ toTimestamp,
13743
+ fromBlock,
13744
+ toBlock,
13745
+ limit
13746
+ });
13481
13747
  }
13482
13748
  /**
13483
13749
  * Map one position's raw event payload into `LoanEvents`.
@@ -20560,8 +20826,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
20560
20826
  throw new Error(`Position not found: ${request.positionId}`);
20561
20827
  }
20562
20828
  const currentDebt = position.ucdDebt.toString();
20563
- const ucdDebtHash = keccak2566(AbiCoder2.defaultAbiCoder().encode(["uint256"], [currentDebt]));
20564
- const contractHash = keccak2566(AbiCoder2.defaultAbiCoder().encode(
20829
+ const ucdDebtHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(["uint256"], [currentDebt]));
20830
+ const contractHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(
20565
20831
  ["address", "address", "address", "address"],
20566
20832
  [
20567
20833
  positionManagerAddress,
@@ -20638,7 +20904,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
20638
20904
  const currentPosition = await positionCore["getPositionDetails"](
20639
20905
  positionIdBytes32
20640
20906
  );
20641
- const currentDebtHash = keccak2566(
20907
+ const currentDebtHash = keccak2565(
20642
20908
  AbiCoder2.defaultAbiCoder().encode(
20643
20909
  ["uint256"],
20644
20910
  [currentPosition.ucdDebt]
@@ -20929,6 +21195,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
20929
21195
  }
20930
21196
  const tx = await sendEip1559Transaction({
20931
21197
  signer,
21198
+ feeProvider: this.getProviderOrThrow(),
20932
21199
  to: positionManagerAddress,
20933
21200
  data: mintCalldata,
20934
21201
  gasLimit: MINT_UCD_GAS_CEILING
@@ -22150,6 +22417,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
22150
22417
  }
22151
22418
  const tx = await sendEip1559Transaction({
22152
22419
  signer: extendSigner,
22420
+ feeProvider: this.getProviderOrThrow(),
22153
22421
  to: extendTo,
22154
22422
  data: extendCalldata,
22155
22423
  gasLimit: EXTEND_POSITION_GAS_CEILING
@@ -23078,6 +23346,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
23078
23346
  }
23079
23347
  const tx = await sendEip1559Transaction({
23080
23348
  signer: paymentSigner,
23349
+ feeProvider: this.getProviderOrThrow(),
23081
23350
  to: paymentContractAddress,
23082
23351
  data: paymentCalldata,
23083
23352
  gasLimit: MAKE_PAYMENT_GAS_CEILING
@@ -23843,6 +24112,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
23843
24112
  });
23844
24113
  tx = await sendEip1559Transaction({
23845
24114
  signer: withdrawSigner,
24115
+ feeProvider: this.getProviderOrThrow(),
23846
24116
  to: positionManagerAddress,
23847
24117
  data: withdrawCalldata,
23848
24118
  gasLimit: WITHDRAW_BTC_GAS_CEILING
@@ -24550,7 +24820,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
24550
24820
  targetAddress: spend.targetAddress,
24551
24821
  targetAmount: Number(spend.targetAmount),
24552
24822
  authorizedAt: Number(spend.authorizedAt),
24553
- utxoKey: solidityPackedKeccak2565(
24823
+ utxoKey: solidityPackedKeccak2564(
24554
24824
  ["string", "uint32"],
24555
24825
  [spend.txid, Number(spend.vout)]
24556
24826
  )
@@ -25558,9 +25828,9 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
25558
25828
  to: registryAddress,
25559
25829
  data: iface.encodeFunctionData("getLoanGrant", [pid])
25560
25830
  });
25561
- if (getBytes5(data).length < 96) {
25831
+ if (getBytes4(data).length < 96) {
25562
25832
  throw new SDKError({
25563
- message: `AgentDelegationRegistry at ${registryAddress} returned ${getBytes5(data).length} bytes for getLoanGrant(bytes32) \u2014 expected at least 96. Wrong address, or a registry version this SDK does not support.`,
25833
+ message: `AgentDelegationRegistry at ${registryAddress} returned ${getBytes4(data).length} bytes for getLoanGrant(bytes32) \u2014 expected at least 96. Wrong address, or a registry version this SDK does not support.`,
25564
25834
  category: "CONTRACT" /* CONTRACT */,
25565
25835
  severity: "HIGH" /* HIGH */
25566
25836
  });
@@ -25569,7 +25839,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
25569
25839
  "getLoanGrant",
25570
25840
  data
25571
25841
  );
25572
- const raw = getBytes5(data);
25842
+ const raw = getBytes4(data);
25573
25843
  const withdrawScopeSupported = raw.length >= 128;
25574
25844
  const minWithdrawRatioBps = withdrawScopeSupported ? Number(
25575
25845
  AbiCoder2.defaultAbiCoder().decode(["uint32"], raw.slice(96, 128))[0]
@@ -26758,8 +27028,8 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
26758
27028
  const MIN_REVEAL_DELAY = 60;
26759
27029
  const MAX_RANDOM_DELAY = 240;
26760
27030
  const entropyInput = positionId + quantumTimestamp.toString();
26761
- const hash = keccak2566(
26762
- toUtf8Bytes6(entropyInput)
27031
+ const hash = keccak2565(
27032
+ toUtf8Bytes5(entropyInput)
26763
27033
  );
26764
27034
  const randomValue = BigInt(hash);
26765
27035
  const randomDelay = Number(randomValue % BigInt(MAX_RANDOM_DELAY));
@@ -26784,12 +27054,12 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
26784
27054
  const rawPositionId = /^0x/i.test(params.positionId.trim()) ? params.positionId.trim().slice(2) : params.positionId.trim();
26785
27055
  const canonicalPositionId = "0x" + rawPositionId.padStart(64, "0").toLowerCase();
26786
27056
  const intentTimestamp = Math.floor(Date.now() / 1e3);
26787
- const intentActionHash = keccak2566(toUtf8Bytes6("liquidate-position"));
26788
- const intentHash = solidityPackedKeccak2565(
27057
+ const intentActionHash = keccak2565(toUtf8Bytes5("liquidate-position"));
27058
+ const intentHash = solidityPackedKeccak2564(
26789
27059
  ["bytes32", "uint256", "uint256", "address", "bytes32"],
26790
27060
  [canonicalPositionId, intentTimestamp, chainId, intentSigner, intentActionHash]
26791
27061
  );
26792
- const intentSignature = await signer.signMessage(getBytes5(intentHash));
27062
+ const intentSignature = await signer.signMessage(getBytes4(intentHash));
26793
27063
  const response = await fetch(endpoint, {
26794
27064
  method: "POST",
26795
27065
  headers: { "Content-Type": "application/json" },
@@ -26841,7 +27111,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
26841
27111
  const vrfSeedRaw = await lmResult.value["vrfSeeds"](positionId);
26842
27112
  const vrfSeed = BigInt(vrfSeedRaw.toString());
26843
27113
  if (vrfSeed !== 0n) {
26844
- const finalEntropy = solidityPackedKeccak2565(
27114
+ const finalEntropy = solidityPackedKeccak2564(
26845
27115
  ["uint256", "uint256", "bytes32"],
26846
27116
  [vrfSeed, BigInt(quantumTimestamp.toString()), positionId]
26847
27117
  );