@gvnrdao/dh-sdk 0.0.342 → 0.0.344

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
@@ -94,7 +94,6 @@ var init_deployment_addresses = __esm({
94
94
  PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
95
95
  FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
96
96
  BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe",
97
- CarryAgentRegistry: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
98
97
  AgentDelegationRegistry: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
99
98
  DHAgentDelegate: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF",
100
99
  AgentModuleFactory: "0x1Fd3aCa2C030Cf77ce28Af9694D3Bb3034ACa2E5"
@@ -143,11 +142,11 @@ var init_deployment_addresses = __esm({
143
142
  reason: "Shared upgrade script: AdminModule implementation update"
144
143
  },
145
144
  PositionManagerViews: {
146
- previousImplementation: "0x1EB2B1d058006ACd9033E01e846D73eDE686b620",
147
- newImplementation: "0xA455B542cFb36AF8451fc420dB89e590E5c87cef",
148
- upgradedAt: "2026-07-03T20:11:25.817Z",
149
- upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
150
- reason: "Shared upgrade script: PositionManagerViews implementation update"
145
+ previousImplementation: "0xA455B542cFb36AF8451fc420dB89e590E5c87cef",
146
+ newImplementation: "0x8cEB3F1c07fDB3301f55b96a5B9aDb33C8d36Da3",
147
+ upgradedAt: "2026-10-02T17:04:25.853Z",
148
+ upgradedBy: "0x0f8f23674cc90Ef7107930a4437341fD8B460362",
149
+ reason: "1.1.2: getBackingVaults (PoR backing set) + implementation lock (constructor)"
151
150
  },
152
151
  TestPositionManager: {
153
152
  previousImplementation: "0x0B46Ee1a9C6b42559758B7FF78294Cd867BB08f8",
@@ -364,8 +363,6 @@ var init_deployment_addresses = __esm({
364
363
  OPERATION_AUTHORIZATION_REGISTRY_IMPL: "0xe0D981B60351f0f8fFDA2b50C8180Fb37CeF3883",
365
364
  BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe",
366
365
  BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_IMPL: "0x76E0a2c9d89562fD7c50b5f554d7fa25957e39Db",
367
- CARRY_AGENT_REGISTRY: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
368
- CARRY_AGENT_REGISTRY_IMPL: "0x1b11a3D5e46F3672E643c997f0d569DFf0b64a01",
369
366
  AGENT_DELEGATION_REGISTRY: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
370
367
  AGENT_DELEGATION_REGISTRY_IMPL: "0xE931E4b9ceF2A48Ac7D57192da4B523756cFC310",
371
368
  DH_AGENT_DELEGATE: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF"
@@ -397,7 +394,6 @@ var init_deployment_addresses = __esm({
397
394
  PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
398
395
  FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
399
396
  BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe",
400
- CarryAgentRegistry: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
401
397
  AgentDelegationRegistry: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
402
398
  DHAgentDelegate: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF",
403
399
  AgentModuleFactory: "0x1Fd3aCa2C030Cf77ce28Af9694D3Bb3034ACa2E5"
@@ -1374,113 +1370,113 @@ var require_pkg_src = __commonJS({
1374
1370
  deployedAt: 1784569687492,
1375
1371
  size: 4140,
1376
1372
  hash: "4c0d65bf1f33cdac22a78fd8c4764319cc3fe00650e0fe7fa8a6090d9a318a7b",
1377
- validatorWalletAddress: "0x82db9f515957aa380b596c6ea2bd30cef181f236",
1373
+ validatorWalletAddress: "0xefb258d455a31d061bbeb3de3d2143bdfcb67a6c",
1378
1374
  pkp: {
1379
1375
  publicKey: "0x04ec0e3acc40884e3f366ca469d08899eb640ad5259fa196b0238075086208a9f8732a3175704f35f0bcc28e07406cfb24c254efd1e7355640577330f0d2dd755f",
1380
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1376
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1381
1377
  }
1382
1378
  },
1383
1379
  btcTransactionSigner: {
1384
- cid: "QmVi1BYdxvCX3QUhXwPtP6FjWMzqSPtXzrS54YsXjTgjYf",
1380
+ cid: "QmULkz7hwwqsyLwY23U14dnartdVuSNMrykt69PaNiAq7U",
1385
1381
  authorizedCidHex: cidToHex(
1386
- "QmVi1BYdxvCX3QUhXwPtP6FjWMzqSPtXzrS54YsXjTgjYf"
1382
+ "QmULkz7hwwqsyLwY23U14dnartdVuSNMrykt69PaNiAq7U"
1387
1383
  ),
1388
1384
  name: "Btc Transaction Signer",
1389
1385
  description: "Production Btc Transaction Signer",
1390
1386
  version: "1.1.1",
1391
1387
  deployed: true,
1392
- deployedAt: 1787923905597,
1393
- size: 70646,
1394
- hash: "37c3bb72a660c8275d92e1b73f9482742d86b64789480b9246304c0ca1bab47a"
1388
+ deployedAt: 1790246185256,
1389
+ size: 73313,
1390
+ hash: "d8b6bc646ba33fee7d46c8e9b281de776081ea6f182f56fd15d4c52aaf3dd030"
1395
1391
  },
1396
1392
  ucdMintValidator: {
1397
- cid: "QmUWR5fLiyimLT9TPXpYx3HgwNwkvR6MxjZ7hdeYCFodbc",
1393
+ cid: "QmcxVSn9saEPGBS6mqPhNefgW83V2qeZjjXbhwYLP373xe",
1398
1394
  authorizedCidHex: cidToHex(
1399
- "QmUWR5fLiyimLT9TPXpYx3HgwNwkvR6MxjZ7hdeYCFodbc"
1395
+ "QmcxVSn9saEPGBS6mqPhNefgW83V2qeZjjXbhwYLP373xe"
1400
1396
  ),
1401
1397
  name: "Ucd Mint Validator",
1402
1398
  description: "Production Ucd Mint Validator",
1403
- version: "1.2.1",
1399
+ version: "1.3.0",
1404
1400
  deployed: true,
1405
- deployedAt: 1787923919527,
1406
- size: 86197,
1407
- hash: "c2d80939746cc37f65ef2f63c6a3215b929214a63f10c78144e1f5c98320dabf",
1408
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1401
+ deployedAt: 1790246219868,
1402
+ size: 90022,
1403
+ hash: "65e8cb778c2b767ae6eb37cb5db7b4c5a3f2468d508463c847c83c1b6825fadd",
1404
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1409
1405
  pkp: {
1410
1406
  publicKey: "0x041ab17cd91fc5c0b761eea6092d032807561b621b82c488826776e04a9158d61ba64d809a4729f0501289d980732cb06d8dfd06999dd9c8efd2f495dad78b31bb",
1411
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1407
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1412
1408
  }
1413
1409
  },
1414
1410
  processPaymentValidator: {
1415
- cid: "QmXmXuMRAjMLdgKGyTf9KQdGwYrDp8DxkiF44TvSXDf7wF",
1411
+ cid: "QmWFbxJkfxhCtES4wrePWQkYtjhtrP1tohvn9d1r9N5Hd8",
1416
1412
  authorizedCidHex: cidToHex(
1417
- "QmXmXuMRAjMLdgKGyTf9KQdGwYrDp8DxkiF44TvSXDf7wF"
1413
+ "QmWFbxJkfxhCtES4wrePWQkYtjhtrP1tohvn9d1r9N5Hd8"
1418
1414
  ),
1419
1415
  name: "Process Payment Validator",
1420
1416
  description: "Production Process Payment Validator",
1421
1417
  version: "1.2.1",
1422
1418
  deployed: true,
1423
- deployedAt: 1787923987153,
1424
- size: 82217,
1425
- hash: "13defa19614215ab3b1fe88955d69e530d13a09475396af932fe0e213637da2f",
1426
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1419
+ deployedAt: 1790246225795,
1420
+ size: 85107,
1421
+ hash: "25ecf952c4c44c40b0920b92d57906e7010ed9a38e2ba41ccdee6d3377c2b596",
1422
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1427
1423
  pkp: {
1428
1424
  publicKey: "0x04cfccb9b6c7addc79469c0e9fafebef4c70801302c62cdb26b610723a9b8527d23f98a40158c7340d83fd0e62d02b5ec74c12f7a86d98e8c6973b4811110f19ad",
1429
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1425
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1430
1426
  }
1431
1427
  },
1432
1428
  extendPositionValidator: {
1433
- cid: "QmU8h99EEVEsQkxroXiYqLsKZw9gNjE6N5CcTpE9aUc12m",
1429
+ cid: "QmZ3g7g5DkgU1gEYpFjprQf3sctUHtGjNQVYezw2bnPGEX",
1434
1430
  authorizedCidHex: cidToHex(
1435
- "QmU8h99EEVEsQkxroXiYqLsKZw9gNjE6N5CcTpE9aUc12m"
1431
+ "QmZ3g7g5DkgU1gEYpFjprQf3sctUHtGjNQVYezw2bnPGEX"
1436
1432
  ),
1437
1433
  name: "Extend Position Validator",
1438
1434
  description: "Production Extend Position Validator",
1439
1435
  version: "1.2.1",
1440
1436
  deployed: true,
1441
- deployedAt: 1787923999294,
1442
- size: 79975,
1443
- hash: "31c1aaf883ef22f37681ddb0a4a949be5c05304b6aef178989475a2da935ef9a",
1444
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1437
+ deployedAt: 1790246231975,
1438
+ size: 82853,
1439
+ hash: "25d4887b7f646649db2bb7f2bfb77d039db83228a6c454377ca26c779b0903cc",
1440
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1445
1441
  pkp: {
1446
1442
  publicKey: "0x04e52338f6a0c3362800f1a94c4c8f08be5030dde0fa217388c53d1c1a4790f4443c9f2886b2d2d8f4b75a9a156e9b028011b1a1cf7648da0e556aa980ec692836",
1447
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1443
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1448
1444
  }
1449
1445
  },
1450
1446
  btcWithdrawal: {
1451
- cid: "QmZQWET9pzrVD4gwQuSzYZmqa24JrUNtnnGFDd513sxMCY",
1447
+ cid: "QmbRaaMQr1jCctDGe8mPADsUz1rkb4frT1YqSKroiXjzyP",
1452
1448
  authorizedCidHex: cidToHex(
1453
- "QmZQWET9pzrVD4gwQuSzYZmqa24JrUNtnnGFDd513sxMCY"
1449
+ "QmbRaaMQr1jCctDGe8mPADsUz1rkb4frT1YqSKroiXjzyP"
1454
1450
  ),
1455
1451
  name: "Btc Withdrawal",
1456
1452
  description: "Production Btc Withdrawal",
1457
1453
  version: "1.2.7",
1458
1454
  deployed: true,
1459
- deployedAt: 1787924017769,
1460
- size: 100069,
1461
- hash: "4f8e27414e4da235e63d6ae1325c63f3d2fb956464515a21aa007a99935f0f13",
1462
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1455
+ deployedAt: 1790246239599,
1456
+ size: 101228,
1457
+ hash: "2ed25eca6cc80a43061b7ad119737af48158fdb61d59f10cd06cea51b607f112",
1458
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1463
1459
  pkp: {
1464
1460
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
1465
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1461
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1466
1462
  }
1467
1463
  },
1468
1464
  liquidationValidator: {
1469
- cid: "Qme6aGADhiszkQbZL977E6nmBacd2PEB7K9Hs8puVrscNx",
1465
+ cid: "QmTs2w8gfAwWZLbzJZg2CZmiLhVXS5kbMgaj42Zuxfodpb",
1470
1466
  authorizedCidHex: cidToHex(
1471
- "Qme6aGADhiszkQbZL977E6nmBacd2PEB7K9Hs8puVrscNx"
1467
+ "QmTs2w8gfAwWZLbzJZg2CZmiLhVXS5kbMgaj42Zuxfodpb"
1472
1468
  ),
1473
1469
  name: "Liquidation Validator",
1474
1470
  description: "Production Liquidation Validator",
1475
1471
  version: "1.2.1",
1476
1472
  deployed: true,
1477
- deployedAt: 1785173262533,
1478
- size: 66846,
1479
- hash: "b35ee7706d733d625faa4dbe37f73c8e20f0c1befa897cd7875e827de52003de",
1480
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1473
+ deployedAt: 1790246247904,
1474
+ size: 70308,
1475
+ hash: "582ccf0ec7f715195e20fdc885996743cb42125b64173424e360ee63db62bbd8",
1476
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1481
1477
  pkp: {
1482
1478
  publicKey: "0x041a241de58976c13e3d7ca5a18e494f7330151e3818706135d50176e78ffb673e58b11f0b67a87c73fade6c6b27d6e7a7377ea9f4c10bf31880f1d725f18cc6f8",
1483
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1479
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1484
1480
  }
1485
1481
  },
1486
1482
  priceOracle: {
@@ -1495,28 +1491,28 @@ var require_pkg_src = __commonJS({
1495
1491
  deployedAt: 1781116663270,
1496
1492
  size: 8695,
1497
1493
  hash: "ba20ade60a7fa5acd80dadfafa179c507388cfe6ce48a22a672d70b317ffcc74",
1498
- validatorWalletAddress: "0x82db9f515957aa380b596c6ea2bd30cef181f236",
1494
+ validatorWalletAddress: "0xefb258d455a31d061bbeb3de3d2143bdfcb67a6c",
1499
1495
  pkp: {
1500
1496
  publicKey: "0x043beaa1da47875601a8d6f430b1438ee2d4732eefd06e5c63a474bbdaf9e7df1797b1b951e041b627c2bf839788164825324c9cbd1e2d6f740fdd4bff69b1900b",
1501
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1497
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1502
1498
  }
1503
1499
  },
1504
1500
  loanVaultBtcBalance: {
1505
- cid: "QmaeQoHYvcMYobNbu9hQavGDudi8AXoW9tg3YHrvy1g2A4",
1501
+ cid: "QmZ27xCzuoaAhWxRsMPsUQkp45a8WPBb21uhxwchw3LG5W",
1506
1502
  authorizedCidHex: cidToHex(
1507
- "QmaeQoHYvcMYobNbu9hQavGDudi8AXoW9tg3YHrvy1g2A4"
1503
+ "QmZ27xCzuoaAhWxRsMPsUQkp45a8WPBb21uhxwchw3LG5W"
1508
1504
  ),
1509
1505
  name: "Loan Vault Btc Balance",
1510
1506
  description: "Production Loan Vault Btc Balance",
1511
1507
  version: "1.2.1",
1512
1508
  deployed: true,
1513
- deployedAt: 1785173271802,
1514
- size: 56800,
1515
- hash: "a059133214e6ba0a73d655a15600c4b33e361fb340c98f8eecaf8ab7b95aaf83",
1516
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1509
+ deployedAt: 1790179961079,
1510
+ size: 60046,
1511
+ hash: "922e86c0a667fe0c0945771f84aa6b9fe08be9c96dd2f73a9c5cb257d24e22b0",
1512
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1517
1513
  pkp: {
1518
1514
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
1519
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1515
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1520
1516
  }
1521
1517
  },
1522
1518
  // btc-address-balance (Option B) — address-only signed total balance via
@@ -1526,21 +1522,21 @@ var require_pkg_src = __commonJS({
1526
1522
  // Requires BitcoinProviderRegistry.addAllowedCid(chainId, keccak256(utf8(cid)))
1527
1523
  // on each target chain (the action decrypts registry slots). No OAR entry.
1528
1524
  btcAddressBalance: {
1529
- cid: "QmUXUtU9r1HhQVYgkXPN5s19SKXanhn4pMsCtFEP3GK4Kj",
1525
+ cid: "QmVVjB6zCBiXFKffhQPYUAZhj7TXduuvcrPqKtHa3DMXhN",
1530
1526
  authorizedCidHex: cidToHex(
1531
- "QmUXUtU9r1HhQVYgkXPN5s19SKXanhn4pMsCtFEP3GK4Kj"
1527
+ "QmVVjB6zCBiXFKffhQPYUAZhj7TXduuvcrPqKtHa3DMXhN"
1532
1528
  ),
1533
1529
  name: "Btc Address Balance",
1534
1530
  description: "Address-only signed total BTC balance via registry consensus (no positionId, no price)",
1535
1531
  version: "0.2.1",
1536
1532
  deployed: true,
1537
- deployedAt: 1785173280221,
1538
- size: 27309,
1539
- hash: "f0d08938713d9d89a56a3a386cacbc2b57afd5ad367ea82d827d40e1bfc70989",
1540
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1533
+ deployedAt: 1790179971315,
1534
+ size: 30295,
1535
+ hash: "2c67d9cfa4d50e835fbb28ae50e80217ceb2be3bb862c89290aadf43fdc739c9",
1536
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1541
1537
  pkp: {
1542
1538
  publicKey: "0x0498cbb31facfa26e3ec83ccdabfe4fe341ca0282e0c3cb81da7113723b9726e1e49efa92165cc3faa66ced4454cea56dbab12267852d6525a55d7c4f128b912cd",
1543
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1539
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1544
1540
  }
1545
1541
  },
1546
1542
  alwaysSigner: {
@@ -1570,48 +1566,74 @@ var require_pkg_src = __commonJS({
1570
1566
  hash: "03ee5be239c91c735d2c95db89a0d1b77e602cfc18af8eb64b3281fddcd90a72"
1571
1567
  },
1572
1568
  agentModuleExecutor: {
1573
- cid: "QmcD65vuremot5fsHVgp9JBAmei6gAaEtm5mdtLP7Yt9Kf",
1569
+ cid: "QmSwPPvQhT7UhcuVA2m3UxGhVj5WqMpDvYNKU1228QLFsX",
1574
1570
  authorizedCidHex: cidToHex(
1575
- "QmcD65vuremot5fsHVgp9JBAmei6gAaEtm5mdtLP7Yt9Kf"
1571
+ "QmSwPPvQhT7UhcuVA2m3UxGhVj5WqMpDvYNKU1228QLFsX"
1576
1572
  ),
1577
1573
  name: "Agent Module Executor",
1578
1574
  description: "Production Agent Module Executor",
1579
1575
  version: "1.1.1",
1580
1576
  deployed: true,
1581
- deployedAt: 1787924032013,
1582
- size: 13878,
1583
- hash: "a7f0204700912e26e5a354bee13a1242a2baa218643b3bb22d28481f67f9baf4"
1577
+ deployedAt: 1790179978959,
1578
+ size: 14688,
1579
+ hash: "8edb9b12c784c8d7d153cce97235584c24665a788767ae68713dce91109ab35e"
1584
1580
  },
1585
1581
  staleSpendRecoveryValidator: {
1586
- cid: "QmNuwo4PT4AikAmhMdZgPWCb2mJDwWa9TnUqrqvofjbrT8",
1582
+ cid: "Qmarj59zdSSgivkimryrdvnyZqH5YpTimKj1LivXNBHmNz",
1587
1583
  authorizedCidHex: cidToHex(
1588
- "QmNuwo4PT4AikAmhMdZgPWCb2mJDwWa9TnUqrqvofjbrT8"
1584
+ "Qmarj59zdSSgivkimryrdvnyZqH5YpTimKj1LivXNBHmNz"
1589
1585
  ),
1590
1586
  name: "Stale Spend Recovery Validator",
1591
1587
  description: "Production Stale Spend Recovery Validator",
1592
1588
  version: "1.1.2",
1593
1589
  deployed: true,
1594
- deployedAt: 1787924048772,
1595
- size: 41424,
1596
- hash: "3c5f028d2bef4344768462993616d45e30d9d44ef126e04d6eb579821d57d99c",
1597
- validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1590
+ deployedAt: 1790246256280,
1591
+ size: 48143,
1592
+ hash: "ec9236bcbe0af24d3e1844791fc8fe37371bbecd8ce95d02e13f7c6e1fc7d94c",
1593
+ validatorWalletAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C",
1598
1594
  pkp: {
1599
1595
  publicKey: "0x046da0ad6da7dd4a0063cbeac6f2bdb6a9889c2178b23470833356a8ee5630f7f0eee0db348d9d9aaaadd23eccf0063c8f68ee5e446abe30b882bf1de4c932bc21",
1600
- ethAddress: "0xc7e1588Db94Bbe92Ab209B833235144Fc5b97607"
1596
+ ethAddress: "0xEfb258D455a31d061Bbeb3DE3D2143BdFCB67a6C"
1601
1597
  }
1602
1598
  },
1603
1599
  btcUtxoInvalidator: {
1604
- cid: "QmaNGeWut7EiGwW4zUc2sFSt7RY5NWFgxYboyG333TwrJf",
1600
+ cid: "QmbS44bGcmKYF64Cu35qzsk9sxiU4Umde8Z3q24ZnEbQvX",
1605
1601
  authorizedCidHex: cidToHex(
1606
- "QmaNGeWut7EiGwW4zUc2sFSt7RY5NWFgxYboyG333TwrJf"
1602
+ "QmbS44bGcmKYF64Cu35qzsk9sxiU4Umde8Z3q24ZnEbQvX"
1607
1603
  ),
1608
1604
  name: "Btc Utxo Invalidator",
1609
1605
  description: "Production Btc Utxo Invalidator",
1610
1606
  version: "1.0.0",
1611
1607
  deployed: true,
1612
- deployedAt: 1787924133241,
1613
- size: 66026,
1614
- hash: "603bc50920d7f1dee77086f2c518d9e2922ab3858a419d3fbea8221ea3a6d9e9"
1608
+ deployedAt: 1790246264563,
1609
+ size: 69219,
1610
+ hash: "bda048d8cd6b5a39c2774bcf1320e82d1eea935c2a521006fb8b887e13b6dd8d"
1611
+ },
1612
+ carryCollateralAttestation: {
1613
+ cid: "QmYWULmXD9S5AmTdQqWqoZ28ctsZQNcXkAgre9G2Xo9dh8",
1614
+ authorizedCidHex: cidToHex(
1615
+ "QmYWULmXD9S5AmTdQqWqoZ28ctsZQNcXkAgre9G2Xo9dh8"
1616
+ ),
1617
+ name: "Carry Collateral Attestation",
1618
+ description: "LoanCarryVault collateral attestation (borrower, BTC vault, confirmed BTC)",
1619
+ version: "1.0.0",
1620
+ deployed: true,
1621
+ deployedAt: 1790927734070,
1622
+ size: 21156,
1623
+ hash: "05b177e0bb36b0483db4a42d33c1bbbf47eb9ef34ae278459397d51a7f8957ff"
1624
+ },
1625
+ carryFundingAttestation: {
1626
+ cid: "QmWhox3xUZMNR5NpPZ9WLSPC5GoW4ms88GanVRKr8uuS3W",
1627
+ authorizedCidHex: cidToHex(
1628
+ "QmWhox3xUZMNR5NpPZ9WLSPC5GoW4ms88GanVRKr8uuS3W"
1629
+ ),
1630
+ name: "Carry Funding Attestation",
1631
+ description: "LoanCarryVault funding attestation (Hyperliquid BTC windowed hourly average)",
1632
+ version: "1.0.0",
1633
+ deployed: true,
1634
+ deployedAt: 1790925699980,
1635
+ size: 7193,
1636
+ hash: "4944ada61610cf64b32e33b5be62087088dcf5e821040c69e67942e643ce74c9"
1615
1637
  }
1616
1638
  };
1617
1639
  function getDeploymentsForNetwork(network) {
@@ -2379,7 +2401,10 @@ ${errorReport}`);
2379
2401
  BTCSpendAuthorizer: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
2380
2402
  BitcoinProviderRegistry: "0x4ab3Fb96e02893Ed6FAa61bad1918390c8DbbFFC",
2381
2403
  LITActionValidator: "0xD2c5d59c2CC5c409AC65ce0A817236aeC6869512",
2382
- PositionDelegateRegistry: "0xf0aa2678aD4F60f49e8F7725089B5E86B7F8FE4C"
2404
+ PositionDelegateRegistry: "0xf0aa2678aD4F60f49e8F7725089B5E86B7F8FE4C",
2405
+ TermManagerModule: "0xDB99CdF883ffa38acD099bC39F8d1f4508c9239E",
2406
+ UCDController: "0x4b4f8063048bCD59D469219E3f07C6aaDF4f6157",
2407
+ LiquidationManagerModule: "0x74B28695352E7bf736D6c9F76ccb7B4439477De9"
2383
2408
  },
2384
2409
  11155111: {
2385
2410
  PositionManager: "0x68e0507D982AEBF1D1C1Af8FBbd842327e2deeFF",
@@ -2387,7 +2412,10 @@ ${errorReport}`);
2387
2412
  BTCSpendAuthorizer: "0xd7E9Eb5eE53f1d9ee55Dc162bBC7486bE437B6bD",
2388
2413
  BitcoinProviderRegistry: "0xbfA0c48B070D0a9A9CD27469AeacFD2d4261cEE2",
2389
2414
  LITActionValidator: "0x54eECd7C90F8A8fac27749Ba30BbE8AFBAccc856",
2390
- PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9"
2415
+ PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
2416
+ TermManagerModule: "0x94Adc6F9558368B1482197584f1fc7133Ecf835b",
2417
+ UCDController: "0x360Bde4e489ee94E26601B206932De09EE60FF04",
2418
+ LiquidationManagerModule: "0xC4AB00f39e7ceD812F5C67058C9fa44e15d40e76"
2391
2419
  }
2392
2420
  };
2393
2421
  function getPinnedContractAddresses(chainId) {
@@ -2573,10 +2601,10 @@ ${errorReport}`);
2573
2601
  };
2574
2602
  }
2575
2603
  const ratioBigInt = collateralValueUsd * UCD_TOKEN_DECIMALS * 10000n / ucdDebt;
2576
- const collateralRatioBps = Number(ratioBigInt);
2604
+ const collateralRatioBps2 = Number(ratioBigInt);
2577
2605
  return {
2578
2606
  collateralValueUsd,
2579
- collateralRatioBps
2607
+ collateralRatioBps: collateralRatioBps2
2580
2608
  };
2581
2609
  }
2582
2610
  function hasSufficientCollateralForDebt(collateralValueUsd, currentDebt, additionalDebt, requiredRatioBps) {
@@ -3430,6 +3458,17 @@ ${auth.clientId}`;
3430
3458
  );
3431
3459
  }
3432
3460
  }
3461
+ var TIP_READ_FAILURE_PREFIX = "Bitcoin tip-height read failed";
3462
+ var BitcoinTipUnreadableError = class extends Error {
3463
+ constructor(message) {
3464
+ super(message);
3465
+ this.isBitcoinTipUnreadable = true;
3466
+ this.name = "BitcoinTipUnreadableError";
3467
+ }
3468
+ };
3469
+ function isBitcoinTipUnreadableError(error) {
3470
+ return typeof error === "object" && error !== null && error.isBitcoinTipUnreadable === true;
3471
+ }
3433
3472
  var BitcoinDataProvider = class {
3434
3473
  constructor(config) {
3435
3474
  this.config = config;
@@ -3881,27 +3920,12 @@ ${auth.clientId}`;
3881
3920
  if (!data.status.confirmed || !data.status.block_height) {
3882
3921
  return { txid: data.txid ?? txid, confirmations: 0 };
3883
3922
  }
3884
- try {
3885
- const tipResp = await fetch(
3886
- `${this.config.providerUrl}/blocks/tip/height`,
3887
- { signal: controller.signal, headers: await this.withAuth() }
3888
- );
3889
- if (!tipResp.ok) {
3890
- return { txid: data.txid ?? txid, confirmations: 1 };
3891
- }
3892
- const tipBody = (await tipResp.text()).trim();
3893
- const tipHeight = Number.parseInt(tipBody, 10);
3894
- if (!Number.isFinite(tipHeight) || tipHeight <= 0) {
3895
- return { txid: data.txid ?? txid, confirmations: 1 };
3896
- }
3897
- const depth = tipHeight - data.status.block_height + 1;
3898
- return {
3899
- txid: data.txid ?? txid,
3900
- confirmations: depth > 0 ? depth : 0
3901
- };
3902
- } catch {
3903
- return { txid: data.txid ?? txid, confirmations: 1 };
3904
- }
3923
+ const tipHeight = await this.fetchTipHeight(controller.signal);
3924
+ const depth = tipHeight - data.status.block_height + 1;
3925
+ return {
3926
+ txid: data.txid ?? txid,
3927
+ confirmations: depth > 0 ? depth : 0
3928
+ };
3905
3929
  }
3906
3930
  return null;
3907
3931
  } catch (error) {
@@ -3909,12 +3933,55 @@ ${auth.clientId}`;
3909
3933
  if (isAbortError(error)) {
3910
3934
  throw new Error(`Request timeout after ${this.timeout}ms`);
3911
3935
  }
3936
+ if (isBitcoinTipUnreadableError(error)) {
3937
+ throw error;
3938
+ }
3912
3939
  if (getUnknownErrorMessage(error).includes("404")) {
3913
3940
  return null;
3914
3941
  }
3915
3942
  throw error;
3916
3943
  }
3917
3944
  }
3945
+ /**
3946
+ * Current chain tip height from THIS provider — or throw.
3947
+ *
3948
+ * Every exit is a throw naming the provider and the precise failure, because
3949
+ * the only alternative is inventing a confirmation depth (see the call site).
3950
+ * The single `try` exists solely to attach that name to a transport-level
3951
+ * rejection (DNS, TLS, connection reset, abort); it re-throws the cause
3952
+ * verbatim inside the message and never substitutes a value — authorized for
3953
+ * this case by the Batch 2 plan, §C2.
3954
+ *
3955
+ * @param signal - The caller's AbortSignal, so this read shares the same
3956
+ * timeout budget as the transaction fetch it serves.
3957
+ */
3958
+ async fetchTipHeight(signal) {
3959
+ const endpoint = `${this.config.providerUrl}/blocks/tip/height`;
3960
+ let tipResp;
3961
+ try {
3962
+ tipResp = await fetch(endpoint, {
3963
+ signal,
3964
+ headers: await this.withAuth()
3965
+ });
3966
+ } catch (error) {
3967
+ throw new BitcoinTipUnreadableError(
3968
+ `${TIP_READ_FAILURE_PREFIX}: GET ${endpoint} threw \u2014 ${getUnknownErrorMessage(error)}`
3969
+ );
3970
+ }
3971
+ if (!tipResp.ok) {
3972
+ throw new BitcoinTipUnreadableError(
3973
+ `${TIP_READ_FAILURE_PREFIX}: GET ${endpoint} \u2192 ${tipResp.status} ${tipResp.statusText}`
3974
+ );
3975
+ }
3976
+ const tipBody = (await tipResp.text()).trim();
3977
+ const tipHeight = Number.parseInt(tipBody, 10);
3978
+ if (!Number.isFinite(tipHeight) || tipHeight <= 0) {
3979
+ throw new BitcoinTipUnreadableError(
3980
+ `${TIP_READ_FAILURE_PREFIX}: GET ${endpoint} returned an unusable tip height "${tipBody.slice(0, 64)}"`
3981
+ );
3982
+ }
3983
+ return tipHeight;
3984
+ }
3918
3985
  /**
3919
3986
  * Get outputs (vouts) of a Bitcoin transaction
3920
3987
  *
@@ -4552,10 +4619,13 @@ ${auth.clientId}`;
4552
4619
  * only on unanimity. The confirmed-balance consensus the validators run
4553
4620
  * covers `chain_stats` only, so without this the primary provider alone
4554
4621
  * could fabricate an unconfirmed UTXO plus a self-consistent parent proof
4555
- * and inflate the signed balance. Any provider failure or verdict
4556
- * disagreement THROWS (fail-closed) — exclusion on a suppressed proof
4557
- * would deflate the balance and open a wrongful-liquidation window, so
4558
- * neither direction may proceed without agreement.
4622
+ * and inflate the signed balance. Any verdict disagreement THROWS
4623
+ * (fail-closed) — exclusion on a suppressed proof would deflate the balance
4624
+ * and open a wrongful-liquidation window, so neither direction may proceed
4625
+ * without agreement. A provider that cannot state the chain tip — and only
4626
+ * that failure — is dropped from the quorum rather than aborting the read (it
4627
+ * never counts as agreeing), and falling below `minConsensusProviders`
4628
+ * survivors throws — see `verifyParentIsSelfSpendConsensus`.
4559
4629
  *
4560
4630
  * The same per-provider `/tx` fetch also returns the parent's outputs, and
4561
4631
  * every provider must corroborate each claimed UTXO (index, vault address,
@@ -4650,10 +4720,26 @@ ${auth.clientId}`;
4650
4720
  }
4651
4721
  /**
4652
4722
  * Run the self-spend proof against every configured provider and require
4653
- * unanimity. Fail-closed: a provider request failure or a verdict
4654
- * disagreement throws and aborts the balance calculation — see
4723
+ * unanimity AMONG THE PROVIDERS THAT ANSWERED. Fail-closed on disagreement:
4724
+ * a verdict mismatch throws and aborts the balance calculation — see
4655
4725
  * classifySelfChange for why exclusion is not a safe fallback here.
4656
4726
  *
4727
+ * Quorum semantics (2026-09-23, plan C2). ONE failure class is tolerated: a
4728
+ * provider that could not state the chain tip (`BitcoinTipUnreadableError`).
4729
+ * It is ABSENT from the quorum — never counted as agreeing, never allowed to
4730
+ * decide the verdict — and the policy floor, not "at least one", decides when
4731
+ * that absence is fatal: below `minConsensusProviders` surviving readings
4732
+ * there is no cross-check left to trust, and the read fails loudly naming
4733
+ * every provider that dropped out.
4734
+ *
4735
+ * Why only that class. `getTransaction` now throws on an unreadable tip
4736
+ * instead of fabricating `confirmations: 1`; without this carve-out one flaky
4737
+ * `/blocks/tip/height` endpoint would take every balance and spend path down
4738
+ * with it. Every OTHER failure remains fatal, as before: a provider that
4739
+ * answers "I have never seen that transaction" is making a claim about the
4740
+ * chain rather than suffering an outage, and that shape is precisely the
4741
+ * fabricated-UTXO signature the fail-closed rule exists to catch.
4742
+ *
4657
4743
  * When the parent IS a unanimous self-spend, every provider's view of the
4658
4744
  * parent's OUTPUTS must additionally corroborate the primary's claimed
4659
4745
  * UTXOs (index exists, pays the vault, exact value). Without this, a
@@ -4678,32 +4764,52 @@ ${auth.clientId}`;
4678
4764
  )
4679
4765
  )
4680
4766
  );
4681
- const failures = settled.map((r, i) => ({ r, name: providerName(i) })).filter(
4682
- (x) => x.r.status === "rejected"
4683
- ).map(
4684
- ({ r, name }) => `${name} \u2192 ${r.reason?.message ?? String(r.reason)}`
4685
- );
4767
+ const answered = [];
4768
+ const absences = [];
4769
+ const failures = [];
4770
+ settled.forEach((result, i) => {
4771
+ if (result.status === "fulfilled") {
4772
+ answered.push({ index: i, evaluation: result.value });
4773
+ return;
4774
+ }
4775
+ const described = `${providerName(i)} \u2192 ${result.reason?.message ?? String(result.reason)}`;
4776
+ if (isBitcoinTipUnreadableError(result.reason)) {
4777
+ absences.push(described);
4778
+ return;
4779
+ }
4780
+ failures.push(described);
4781
+ });
4686
4782
  if (failures.length > 0) {
4687
4783
  throw new Error(
4688
4784
  `Self-change classification failed for tx ${parentTxid} on ${failures.length}/${providerConfigs.length} provider(s): ${failures.join("; ")}`
4689
4785
  );
4690
4786
  }
4691
- const evaluations = settled.map(
4692
- (r) => r.value
4693
- );
4694
- const votes = evaluations.map((e) => e.selfSpend);
4695
- const disagreements = votes.map((vote, i) => ({ vote, name: providerName(i) })).filter((x) => x.vote !== votes[0]).map(
4696
- (x) => `${providerName(0)}=${votes[0]} vs ${x.name}=${x.vote}`
4787
+ const floor = Math.max(1, this.minConsensusProviders);
4788
+ if (answered.length < floor) {
4789
+ throw new Error(
4790
+ `Self-change classification for tx ${parentTxid}: only ${answered.length}/${providerConfigs.length} provider(s) could state a confirmation depth, below this chain's floor of ${floor}. Unreadable tips: ${absences.join("; ")}`
4791
+ );
4792
+ }
4793
+ if (absences.length > 0) {
4794
+ litDebugLog(
4795
+ `[VaultBalance] self-change: tx ${parentTxid} classified on a reduced quorum \u2014 ${answered.length}/${providerConfigs.length} provider(s) answered (floor ${floor}); dropped for an unreadable chain tip: ${absences.join("; ")}`
4796
+ );
4797
+ }
4798
+ const first = answered[0];
4799
+ const disagreements = answered.slice(1).filter((a) => a.evaluation.selfSpend !== first.evaluation.selfSpend).map(
4800
+ (a) => `${providerName(first.index)}=${first.evaluation.selfSpend} vs ${providerName(a.index)}=${a.evaluation.selfSpend}`
4697
4801
  );
4698
4802
  if (disagreements.length > 0) {
4699
4803
  throw new Error(
4700
4804
  `Self-change consensus mismatch for tx ${parentTxid}: ${disagreements.join("; ")}. A provider may be compromised or out of sync; refusing to sign.`
4701
4805
  );
4702
4806
  }
4703
- if (!votes[0]) {
4807
+ if (!first.evaluation.selfSpend) {
4704
4808
  return false;
4705
4809
  }
4706
- const outputMismatches = evaluations.map((e, i) => e.outputMismatch ? `${providerName(i)} \u2192 ${e.outputMismatch}` : null).filter((m) => m !== null);
4810
+ const outputMismatches = answered.map(
4811
+ (a) => a.evaluation.outputMismatch ? `${providerName(a.index)} \u2192 ${a.evaluation.outputMismatch}` : null
4812
+ ).filter((m) => m !== null);
4707
4813
  if (outputMismatches.length > 0) {
4708
4814
  throw new Error(
4709
4815
  `Self-change output claim mismatch for tx ${parentTxid}: ${outputMismatches.join("; ")}. The reported UTXO set contradicts the parent transaction; refusing to sign.`
@@ -4946,16 +5052,6 @@ ${auth.clientId}`;
4946
5052
  minConfirmations
4947
5053
  );
4948
5054
  const authorizedSpends = await this.getAuthorizedSpendsFromContract(positionId);
4949
- for (const spend of authorizedSpends) {
4950
- const utxoStillExists = utxoSet.utxos.some(
4951
- (utxo) => utxo.txid === spend.txid && utxo.vout === spend.vout
4952
- );
4953
- if (utxoStillExists) {
4954
- throw new Error(
4955
- `Authorized UTXO ${spend.txid}:${spend.vout} not yet spent. Transaction was authorized in smart contract but not signed and broadcasted to Bitcoin network. Complete the transaction by signing and broadcasting it.`
4956
- );
4957
- }
4958
- }
4959
5055
  const authorizedBalance = authorizedSpends.reduce(
4960
5056
  (sum, spend) => sum + spend.satoshis,
4961
5057
  0n
@@ -5251,7 +5347,13 @@ ${auth.clientId}`;
5251
5347
  allowDevSinglePriceProvider: false,
5252
5348
  minBitcoinBalanceConfirmations: 1,
5253
5349
  minBitcoinSpendConfirmations: 1,
5254
- minConsensusProviders: 1
5350
+ // 2 since 2026-09-23. It was 1 because Sepolia ran a single faucet provider
5351
+ // "by design", so the consensus floor was documented as a mainnet-only
5352
+ // guarantee. The registry now holds two, and leaving the floor at 1 meant
5353
+ // Sepolia could never exercise the multi-provider agreement the stale-spend
5354
+ // and balance paths rely on — the one environment where that logic is
5355
+ // supposed to be proved before mainnet.
5356
+ minConsensusProviders: 2
5255
5357
  },
5256
5358
  [
5257
5359
  "ethereum"
@@ -5562,7 +5664,6 @@ function getSepoliaConfig() {
5562
5664
  feeRecipientRegistry: SEPOLIA_CONTRACTS.FeeRecipientRegistry || "",
5563
5665
  positionDelegateRegistry: SEPOLIA_CONTRACTS.PositionDelegateRegistry || "",
5564
5666
  bitcoinWithdrawalAddressRegistry: SEPOLIA_CONTRACTS.BitcoinWithdrawalAddressRegistry || "",
5565
- carryAgentRegistry: SEPOLIA_CONTRACTS.CarryAgentRegistry || "",
5566
5667
  agentDelegationRegistry: SEPOLIA_CONTRACTS.AgentDelegationRegistry || "",
5567
5668
  dhAgentDelegate: SEPOLIA_CONTRACTS.DHAgentDelegate || "",
5568
5669
  agentModuleFactory: SEPOLIA_CONTRACTS.AgentModuleFactory || ""
@@ -5616,7 +5717,6 @@ function getMainnetConfig() {
5616
5717
  feeRecipientRegistry: MAINNET_CONTRACTS.FeeRecipientRegistry || "",
5617
5718
  positionDelegateRegistry: MAINNET_CONTRACTS.PositionDelegateRegistry || "",
5618
5719
  bitcoinWithdrawalAddressRegistry: MAINNET_CONTRACTS.BitcoinWithdrawalAddressRegistry || "",
5619
- carryAgentRegistry: MAINNET_CONTRACTS.CarryAgentRegistry || "",
5620
5720
  agentDelegationRegistry: MAINNET_CONTRACTS.AgentDelegationRegistry || "",
5621
5721
  dhAgentDelegate: MAINNET_CONTRACTS.DHAgentDelegate || "",
5622
5722
  // Empty on mainnet until the factory is deployed there — the ceremony is Sepolia-only.
@@ -6816,7 +6916,54 @@ async function resolveAuthorizationInput(provider, signer, ctx) {
6816
6916
  return { timestamp: result.timestamp, signature: result.signature };
6817
6917
  }
6818
6918
 
6919
+ // src/utils/btc-dust.utils.ts
6920
+ var BECH32_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
6921
+ function segwitProgramShape(address) {
6922
+ const lower2 = address.trim().toLowerCase();
6923
+ if (!/^(bc1|tb1|bcrt1)/.test(lower2))
6924
+ return null;
6925
+ const sep = lower2.lastIndexOf("1");
6926
+ const data = lower2.slice(sep + 1);
6927
+ if (data.length < 8)
6928
+ return null;
6929
+ const version = BECH32_CHARSET.indexOf(data[0]);
6930
+ if (version < 0)
6931
+ return null;
6932
+ const programChars = data.length - 1 - 6;
6933
+ return { version, programBytes: Math.floor(programChars * 5 / 8) };
6934
+ }
6935
+ function dustLimitForAddress(address) {
6936
+ const shape = segwitProgramShape(address);
6937
+ if (shape === null)
6938
+ return 546;
6939
+ if (shape.version === 0 && shape.programBytes === 20)
6940
+ return 294;
6941
+ if (shape.version === 0 && shape.programBytes === 32)
6942
+ return 330;
6943
+ if (shape.version === 1 && shape.programBytes === 32)
6944
+ return 330;
6945
+ return 546;
6946
+ }
6947
+ function destinationDustShortfall(targetAmount, networkFee, destination) {
6948
+ const limit = dustLimitForAddress(destination);
6949
+ return targetAmount - networkFee < limit ? limit : null;
6950
+ }
6951
+
6819
6952
  // src/utils/loan-helpers.utils.ts
6953
+ function calculateMintFee(params) {
6954
+ const { mintAmount, mintTimestamp, originationFeeBps, previousExpiryAt, selectedTerm, totalTerm } = params;
6955
+ let mintFee = mintAmount * BigInt(originationFeeBps) / 10000n;
6956
+ if (previousExpiryAt > 0 && mintTimestamp < previousExpiryAt) {
6957
+ const tailSeconds = BigInt(previousExpiryAt) - BigInt(mintTimestamp);
6958
+ const originalTermMonths = totalTerm - selectedTerm;
6959
+ const originalTermSeconds = BigInt(
6960
+ originalTermMonths === 12 ? 365 * 86400 : originalTermMonths * 30 * 86400
6961
+ );
6962
+ const tailFee = tailSeconds * BigInt(originationFeeBps) * mintAmount / (10000n * originalTermSeconds);
6963
+ mintFee = mintFee + tailFee;
6964
+ }
6965
+ return mintFee;
6966
+ }
6820
6967
  function baseMintFeeWei(mintAmountWei, originationFeeBps) {
6821
6968
  if (mintAmountWei < 0n)
6822
6969
  throw new Error("baseMintFeeWei: mintAmountWei cannot be negative");
@@ -6835,20 +6982,34 @@ function debtAfterMintExceedsLoanCap(params) {
6835
6982
  }
6836
6983
  return currentDebtWei + mintAmountWei + mintFeeWei > maxLoanWei;
6837
6984
  }
6838
- function maxPrincipalWithinLoanCap(params) {
6839
- const { maxLoanWei, currentDebtWei, originationFeeBps } = params;
6840
- if (maxLoanWei < 0n || currentDebtWei < 0n) {
6841
- throw new Error("maxPrincipalWithinLoanCap: amounts cannot be negative");
6985
+ function collateralRatioBps(sats, price8, debtWei) {
6986
+ if (sats < 0n || price8 < 0n) {
6987
+ throw new Error("collateralRatioBps: sats and price cannot be negative");
6842
6988
  }
6843
- if (!Number.isInteger(originationFeeBps) || originationFeeBps < 0 || originationFeeBps > 1e4) {
6844
- throw new Error(
6845
- `maxPrincipalWithinLoanCap: originationFeeBps must be an integer in [0, 10000] (got ${String(originationFeeBps)})`
6846
- );
6989
+ if (debtWei <= 0n) {
6990
+ throw new Error("collateralRatioBps: debt must be positive");
6847
6991
  }
6848
- const room = maxLoanWei - currentDebtWei;
6849
- if (room <= 0n)
6850
- return 0n;
6851
- return room * 10000n / (10000n + BigInt(originationFeeBps));
6992
+ return sats * price8 * 100n * 10000n / debtWei;
6993
+ }
6994
+ function collateralRatioPercentString(sats, price8, debtWei) {
6995
+ const bps = collateralRatioBps(sats, price8, debtWei);
6996
+ return `${bps / 100n}.${(bps % 100n).toString().padStart(2, "0")}`;
6997
+ }
6998
+ function maxPrincipalForFee(room, fee) {
6999
+ if (room < 0n)
7000
+ throw new Error("maxPrincipalForFee: room cannot be negative");
7001
+ if (fee(0n) !== 0n)
7002
+ throw new Error("maxPrincipalForFee: fee(0) must be 0");
7003
+ let lo = 0n;
7004
+ let hi = room;
7005
+ while (lo < hi) {
7006
+ const mid = (lo + hi + 1n) / 2n;
7007
+ if (mid + fee(mid) <= room)
7008
+ lo = mid;
7009
+ else
7010
+ hi = mid - 1n;
7011
+ }
7012
+ return lo;
6852
7013
  }
6853
7014
 
6854
7015
  // src/utils/eip712-login.ts
@@ -19155,9 +19316,17 @@ async function mintAgentPkp(params) {
19155
19316
  }
19156
19317
  var AGENT_STATUS = { None: 0, Active: 1, Revoked: 2 };
19157
19318
  function planAgentBinding(params) {
19158
- const { isActive, record, nowSeconds } = params;
19319
+ const { isActive, paused, record, nowSeconds } = params;
19320
+ if (typeof paused !== "boolean") {
19321
+ throw new Error("planAgentBinding: `paused` must be read from the registry (boolean required)");
19322
+ }
19159
19323
  if (isActive)
19160
19324
  return { kind: "reuse", agent: record.agent };
19325
+ if (paused) {
19326
+ throw new Error(
19327
+ "AgentDelegationRegistry is paused \u2014 agent delegation cannot be changed until it is unpaused."
19328
+ );
19329
+ }
19161
19330
  const status = Number(record.status);
19162
19331
  if (status === AGENT_STATUS.None || status === AGENT_STATUS.Revoked) {
19163
19332
  return { kind: "register" };
@@ -19167,7 +19336,7 @@ function planAgentBinding(params) {
19167
19336
  }
19168
19337
  if (Number(record.validUntil) > nowSeconds) {
19169
19338
  throw new Error(
19170
- "AgentDelegationRegistry reports an unexpired agent as inactive \u2014 the registry is paused. Agent delegation cannot be changed until it is unpaused."
19339
+ "AgentDelegationRegistry returned an inconsistent read (an unexpired, unpaused Active agent reported inactive); retry."
19171
19340
  );
19172
19341
  }
19173
19342
  return { kind: "rotate" };
@@ -20369,7 +20538,7 @@ function normalizeBigNumberish(value) {
20369
20538
  }
20370
20539
  return value;
20371
20540
  }
20372
- if (typeof value === "object" && value !== null && "toString" in value && typeof value.toString === "function") {
20541
+ if (typeof value === "object" && value !== null && "toString" in value && typeof value.toString === "function" && value.toString !== Object.prototype.toString) {
20373
20542
  const result = value.toString();
20374
20543
  if (typeof result === "object" && result !== null && "_hex" in result) {
20375
20544
  const resultObj = result;
@@ -21782,12 +21951,21 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
21782
21951
  maxLoanWei: maxLoanValueWei
21783
21952
  })) {
21784
21953
  const debtAfterWei = currentDebtWei + requestAmountWei + baseFeeWei;
21954
+ const suggestionStamp = calculateNextQuantumTimestamp();
21955
+ const room = maxLoanValueWei > currentDebtWei ? maxLoanValueWei - currentDebtWei : 0n;
21785
21956
  const maxPrincipalUcd = Number(
21786
- maxPrincipalWithinLoanCap({
21787
- maxLoanWei: maxLoanValueWei,
21788
- currentDebtWei,
21789
- originationFeeBps: positionTerm.originationFeeBps
21790
- }) / BigInt(10 ** 18)
21957
+ maxPrincipalForFee(
21958
+ room,
21959
+ (principal) => calculateMintFee({
21960
+ mintAmount: principal,
21961
+ mintTimestamp: suggestionStamp,
21962
+ originationFeeBps: positionTerm.originationFeeBps,
21963
+ expiryAt: Number(position2.expiryAt),
21964
+ previousExpiryAt: Number(position2.previousExpiryAt),
21965
+ selectedTerm: Number(position2.selectedTerm),
21966
+ totalTerm: Number(position2.totalTerm)
21967
+ })
21968
+ ) / BigInt(10 ** 18)
21791
21969
  );
21792
21970
  return {
21793
21971
  success: false,
@@ -22865,11 +23043,7 @@ Message: ${causeMessage}${quantumContext}${loanCapDiagnostics}${mintDebtDiagnost
22865
23043
  const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
22866
23044
  const btcPrice2 = litActionResult.btcPrice || "0";
22867
23045
  const btcVaultBalance = litActionResult.btcAmountSats || positionDetails.btcVaultBalance || "0";
22868
- const usdPricePerBTC = Number(btcPrice2) / 1e8;
22869
- const btcAmount = Number(btcVaultBalance) / 1e8;
22870
- const btcValueUSD = btcAmount * usdPricePerBTC;
22871
- const debtUSD = Number(debt) / 1e18;
22872
- const ratio = debtUSD > 0 ? (btcValueUSD / debtUSD * 100).toFixed(2) : "0.00";
23046
+ const ratio = BigInt(debt) > 0n ? collateralRatioPercentString(BigInt(btcVaultBalance), BigInt(btcPrice2), BigInt(debt)) : "0.00";
22873
23047
  const message = formatLiquidationSkippedMessage(
22874
23048
  request.positionId,
22875
23049
  ratio,
@@ -23358,14 +23532,15 @@ Message: ${causeMessage}${quantumContext}${loanCapDiagnostics}${mintDebtDiagnost
23358
23532
  }
23359
23533
  const debt = positionDetails.debt || positionDetails.ucdDebt || "0";
23360
23534
  const btcPrice2 = litActionResult.btcPrice || "0";
23361
- const ratio = debt !== "0" ? (Number(positionDetails.btcVaultBalance || "0") * Number(btcPrice2) / Number(debt) * 100 / 1e8).toFixed(2) : "0.00";
23535
+ const btcVaultBalance = litActionResult.btcAmountSats || positionDetails.btcVaultBalance || "0";
23536
+ const ratio = BigInt(debt) > 0n ? collateralRatioPercentString(BigInt(btcVaultBalance), BigInt(btcPrice2), BigInt(debt)) : "0.00";
23362
23537
  const message = formatLiquidationSuccessMessage(
23363
23538
  request.positionId,
23364
23539
  ratio,
23365
23540
  `${liquidationThreshold / 100}`,
23366
23541
  // Convert to percentage
23367
23542
  positionDetails.btcVault || "unknown",
23368
- positionDetails.btcVaultBalance || "0",
23543
+ btcVaultBalance,
23369
23544
  debt,
23370
23545
  btcPrice2
23371
23546
  );
@@ -25838,6 +26013,17 @@ Message: ${causeMessage}${quantumContext}${loanCapDiagnostics}${mintDebtDiagnost
25838
26013
  error: `networkFee=${request.networkFee} is \u2265 50% of targetAmount=${request.targetAmount}. Refusing to broadcast \u2014 real Bitcoin fees are typically <1% of value.`
25839
26014
  };
25840
26015
  }
26016
+ const destinationDustLimit = destinationDustShortfall(
26017
+ request.targetAmount,
26018
+ request.networkFee,
26019
+ request.destination
26020
+ );
26021
+ if (destinationDustLimit !== null) {
26022
+ return {
26023
+ success: false,
26024
+ error: `Destination would receive ${request.targetAmount - request.networkFee} sats (targetAmount=${request.targetAmount} \u2212 networkFee=${request.networkFee}), below the ${destinationDustLimit}-sat dust limit for ${request.destination}; the transaction would not relay.`
26025
+ };
26026
+ }
25841
26027
  const [txid, voutStr] = request.utxoIdentifier.split(":");
25842
26028
  const vout = parseInt(voutStr || "0", 10);
25843
26029
  if (!txid || isNaN(vout)) {
@@ -27310,8 +27496,9 @@ Message: ${causeMessage}${quantumContext}${loanCapDiagnostics}${mintDebtDiagnost
27310
27496
  const user = await signer.getAddress();
27311
27497
  const registry = AgentDelegationRegistry__factory.connect(addr, signer);
27312
27498
  let agentAddress;
27313
- const [isActive, record, latestBlock] = await Promise.all([
27499
+ const [isActive, paused, record, latestBlock] = await Promise.all([
27314
27500
  registry.isAgentActive(user),
27501
+ registry.paused(),
27315
27502
  registry.agentOf(user),
27316
27503
  this.getProviderOrThrow().getBlock("latest")
27317
27504
  ]);
@@ -27322,7 +27509,7 @@ Message: ${causeMessage}${quantumContext}${loanCapDiagnostics}${mintDebtDiagnost
27322
27509
  severity: "HIGH" /* HIGH */
27323
27510
  });
27324
27511
  }
27325
- const plan = planAgentBinding({ isActive, record, nowSeconds: latestBlock.timestamp });
27512
+ const plan = planAgentBinding({ isActive, paused, record, nowSeconds: latestBlock.timestamp });
27326
27513
  if (plan.kind === "reuse") {
27327
27514
  agentAddress = plan.agent;
27328
27515
  } else {