@gvnrdao/dh-sdk 0.0.327 → 0.0.329

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
@@ -552,6 +552,14 @@ var init_deployment_addresses = __esm({
552
552
  reason: "2026-08 agent-stack release. The mainnet PositionManagerViews at 0x9225647a was deployed as a BARE implementation (EIP-1967 slot 0x00), so upgradeToAndCall reverts UUPSUnauthorizedCallContext \u2014 it could never be upgraded. PositionManager.setViews (added in the same Execute B batch) removed the repoint blocker, so Views was replaced behind a new proxy rather than upgraded. This makes the Pashov F3 renewal debt-ceiling check REACHABLE for the first time: ExceedsMaxLoan (0x499e7985) is present in 0xE68DC096 and absent from 0x9225647a. Views holds no protocol state (8 wiring slots + roles + pause), which is what made replacement safe. The old contract is ABANDONED, not decommissioned \u2014 it stays live and callable as the rollback target for setViews. NOTE: VERSION reads 1.1.1 on both sides; verify by address.",
553
553
  executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
554
554
  block: 25673200
555
+ },
556
+ AgentDelegationRegistry: {
557
+ newImplementation: "0xa9fF405Edd4329fc3159a64F56B37EBD253e4928",
558
+ upgradedAt: "2026-07-31T22:03:35.000Z",
559
+ upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4 (block 25655710)",
560
+ reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
561
+ executeTx: "0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4",
562
+ block: 25655710
555
563
  }
556
564
  },
557
565
  latestEnv: {
@@ -684,9 +692,9 @@ var init_deployment_addresses = __esm({
684
692
  }
685
693
  });
686
694
 
687
- // node_modules/@gvnrdao/dh-lit-actions/pkg-dist/pkg-src/index.js
695
+ // ../../../../../../../../Users/rusty/Development/gvnr/diamond-hands/sdk/node_modules/@gvnrdao/dh-lit-actions/pkg-dist/pkg-src/index.js
688
696
  var require_pkg_src = __commonJS({
689
- "node_modules/@gvnrdao/dh-lit-actions/pkg-dist/pkg-src/index.js"(exports, module) {
697
+ "../../../../../../../../Users/rusty/Development/gvnr/diamond-hands/sdk/node_modules/@gvnrdao/dh-lit-actions/pkg-dist/pkg-src/index.js"(exports, module) {
690
698
  "use strict";
691
699
  var __defProp2 = Object.defineProperty;
692
700
  var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
@@ -1369,7 +1377,7 @@ var require_pkg_src = __commonJS({
1369
1377
  description: "Production Btc Transaction Signer",
1370
1378
  version: "1.1.1",
1371
1379
  deployed: true,
1372
- deployedAt: 1786113907707,
1380
+ deployedAt: 1786465606156,
1373
1381
  size: 67999,
1374
1382
  hash: "83f3644c68819215e05ba8db3225571354a009458fc1437f606df6cb9142d3f9"
1375
1383
  },
@@ -1382,7 +1390,7 @@ var require_pkg_src = __commonJS({
1382
1390
  description: "Production Ucd Mint Validator",
1383
1391
  version: "1.2.1",
1384
1392
  deployed: true,
1385
- deployedAt: 1786113908489,
1393
+ deployedAt: 1786465627201,
1386
1394
  size: 82739,
1387
1395
  hash: "2bdd9aebdaad58a43a4731d5b7284f2531b7a9caaf8caf5719d891c4ed33cb2e",
1388
1396
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
@@ -1400,7 +1408,7 @@ var require_pkg_src = __commonJS({
1400
1408
  description: "Production Process Payment Validator",
1401
1409
  version: "1.2.1",
1402
1410
  deployed: true,
1403
- deployedAt: 1786113909138,
1411
+ deployedAt: 1786465654796,
1404
1412
  size: 78736,
1405
1413
  hash: "17191ecc9c009e0fa5ab52c876330beb2a9a75d30cccb92e7c0c04f169df088b",
1406
1414
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
@@ -1418,7 +1426,7 @@ var require_pkg_src = __commonJS({
1418
1426
  description: "Production Extend Position Validator",
1419
1427
  version: "1.2.1",
1420
1428
  deployed: true,
1421
- deployedAt: 1786113909872,
1429
+ deployedAt: 1786465681874,
1422
1430
  size: 76515,
1423
1431
  hash: "1d4e085335af80f194a663a577876902c83015177e95906a0b461fa93bd5da08",
1424
1432
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
@@ -1428,21 +1436,17 @@ var require_pkg_src = __commonJS({
1428
1436
  }
1429
1437
  },
1430
1438
  btcWithdrawal: {
1431
- cid: "QmZuR3qSBajutXfRd91ffpyFrRMgmaMh7fDEHRiQQF8Ljp",
1439
+ cid: "QmRYVoTTDxk2McvBqxSm9M7YcaBGdTqjnZGPX4Y191DaZh",
1432
1440
  authorizedCidHex: cidToHex(
1433
- "QmZuR3qSBajutXfRd91ffpyFrRMgmaMh7fDEHRiQQF8Ljp"
1441
+ "QmRYVoTTDxk2McvBqxSm9M7YcaBGdTqjnZGPX4Y191DaZh"
1434
1442
  ),
1435
1443
  name: "Btc Withdrawal",
1436
1444
  description: "Production Btc Withdrawal",
1437
- // Monotonic per action, NOT a shared release train — the EIP-1271 rotation
1438
- // stamped its cohort 1.2.1, but this action was already at 1.2.3 from the vout
1439
- // canonicalization fix. Reusing the cohort stamp made a newer CID read as older
1440
- // than the one it replaced, which a rotation ceremony would treat as a rollback.
1441
- version: "1.2.4",
1445
+ version: "1.2.7",
1442
1446
  deployed: true,
1443
- deployedAt: 1786113910531,
1444
- size: 95313,
1445
- hash: "ce12f11e3b5469953bc919586e4f3b8b5d594224b58b799dd9a3b60e3749559c",
1447
+ deployedAt: 1786446046614,
1448
+ size: 97456,
1449
+ hash: "3cae8250861832f91ee3c573abeb50ff27b9acd34148176071cbfbabb359fc91",
1446
1450
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1447
1451
  pkp: {
1448
1452
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -1554,19 +1558,17 @@ var require_pkg_src = __commonJS({
1554
1558
  hash: "03ee5be239c91c735d2c95db89a0d1b77e602cfc18af8eb64b3281fddcd90a72"
1555
1559
  },
1556
1560
  agentModuleExecutor: {
1557
- // Bound to the isolated Sepolia agent group 7 ("DH-Agent-Sepolia"), which
1558
- // holds this action and no PKPs until an agent is minted into it. NOT yet
1559
- // bound on mainnet — the Base `DH-Agent-Mainnet` group is created at rollout.
1560
- cid: "QmVgjGXUuxoGf8XyddW8a7btaazT9yEotpKoBgb65oPvcF",
1561
+ cid: "QmdhC18wF7PFGMQ8aThdPsEVSpuDewA27dFvbA3bG6kVDQ",
1561
1562
  authorizedCidHex: cidToHex(
1562
- "QmVgjGXUuxoGf8XyddW8a7btaazT9yEotpKoBgb65oPvcF"
1563
+ "QmdhC18wF7PFGMQ8aThdPsEVSpuDewA27dFvbA3bG6kVDQ"
1563
1564
  ),
1564
1565
  name: "Agent Module Executor",
1565
- description: "Capability gate for multi-sig Safe agent delegation: binds the agent PKP to the AgentDelegationRegistry record before signing (authorize | execute modes)",
1566
- version: "1.0.0",
1566
+ description: "Production Agent Module Executor",
1567
+ version: "1.1.1",
1567
1568
  deployed: true,
1568
- size: 11785,
1569
- hash: "fa294e164273c2158f9ef11a0ccfd735c343c0e3759fcb4b37e0f8a5d1ab0d29"
1569
+ deployedAt: 1786446108348,
1570
+ size: 11655,
1571
+ hash: "d4e2149f843d6c2699fc61114d54b268ba4ed2c46ebdaee1145e0f101ec2a1ec"
1570
1572
  },
1571
1573
  staleSpendRecoveryValidator: {
1572
1574
  cid: "QmXQWT8V4wjuvH8BbC7xrkYxsVu5AKfvfWcS7jnYfrexYm",
@@ -1595,7 +1597,7 @@ var require_pkg_src = __commonJS({
1595
1597
  description: "Production Btc Utxo Invalidator",
1596
1598
  version: "1.0.0",
1597
1599
  deployed: true,
1598
- deployedAt: 1786113911948,
1600
+ deployedAt: 1786465704240,
1599
1601
  size: 62553,
1600
1602
  hash: "1dcea2b49e545c423195be22e072dc5e3039ed1c95a8490b23505956029f5b33"
1601
1603
  }
@@ -12043,6 +12045,169 @@ function normalizePkpId2(pkpId) {
12043
12045
  }
12044
12046
  return pkpId;
12045
12047
  }
12048
+ function hasLoanEventsFilter(filter) {
12049
+ if (!filter)
12050
+ return false;
12051
+ return filter.eventTypes !== void 0 || filter.fromTimestamp !== void 0 || filter.toTimestamp !== void 0 || filter.fromBlock !== void 0 || filter.toBlock !== void 0 || filter.limit !== void 0 || filter.orderDirection !== void 0;
12052
+ }
12053
+ var WALLET_LOAN_EVENTS_QUERY = `
12054
+ query GetWalletLoanEvents($borrower: Bytes!, $first: Int!, $limit: Int!, $orderDirection: OrderDirection!) {
12055
+ positions(where: { borrower: $borrower }, first: $first, orderBy: id) {
12056
+ id
12057
+ payments(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12058
+ id
12059
+ payer { id }
12060
+ amount
12061
+ type
12062
+ transactionHash
12063
+ timestamp
12064
+ blockNumber
12065
+ logIndex
12066
+ newDebt
12067
+ newCollateralRatio
12068
+ }
12069
+ statusUpdates(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12070
+ id
12071
+ oldStatus
12072
+ newStatus
12073
+ reason
12074
+ timestamp
12075
+ blockNumber
12076
+ transactionHash
12077
+ }
12078
+ liquidation {
12079
+ id
12080
+ liquidator
12081
+ liquidatedAmount
12082
+ collateralSeized
12083
+ transactionHash
12084
+ timestamp
12085
+ blockNumber
12086
+ commitHash
12087
+ commitTimestamp
12088
+ revealDelay
12089
+ }
12090
+ withdrawals(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12091
+ id
12092
+ withdrawalAmount
12093
+ withdrawalAddress
12094
+ networkFee
12095
+ timestamp
12096
+ blockNumber
12097
+ transactionHash
12098
+ logIndex
12099
+ }
12100
+ renewals(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12101
+ id
12102
+ extensionTerm
12103
+ extensionFee
12104
+ newExpiryDate
12105
+ timestamp
12106
+ blockNumber
12107
+ transactionHash
12108
+ logIndex
12109
+ }
12110
+ operationFailures(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12111
+ id
12112
+ operationType
12113
+ reason
12114
+ errorCode
12115
+ amount
12116
+ timestamp
12117
+ blockNumber
12118
+ transactionHash
12119
+ logIndex
12120
+ }
12121
+ mintRequests(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12122
+ id
12123
+ pkpId
12124
+ borrower { id }
12125
+ mintAmount
12126
+ originationFee
12127
+ newDebt
12128
+ newCollateralRatio
12129
+ btcPrice
12130
+ quantumTimestamp
12131
+ opId
12132
+ timestamp
12133
+ blockNumber
12134
+ transactionHash
12135
+ logIndex
12136
+ }
12137
+ burnRequests(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12138
+ id
12139
+ pkpId
12140
+ borrower { id }
12141
+ burnAmount
12142
+ remainingDebt
12143
+ newCollateralRatio
12144
+ opId
12145
+ timestamp
12146
+ blockNumber
12147
+ transactionHash
12148
+ logIndex
12149
+ }
12150
+ mintingFees(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12151
+ id
12152
+ borrower { id }
12153
+ feeAmount
12154
+ mintAmount
12155
+ newDebt
12156
+ btcPrice
12157
+ quantumTimestamp
12158
+ timestamp
12159
+ blockNumber
12160
+ transactionHash
12161
+ logIndex
12162
+ }
12163
+ renewalFees(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12164
+ id
12165
+ borrower { id }
12166
+ feeAmount
12167
+ extensionTerm
12168
+ newExpiryDate
12169
+ timestamp
12170
+ blockNumber
12171
+ transactionHash
12172
+ logIndex
12173
+ }
12174
+ positionCreatedEvents(first: 1, orderBy: timestamp, orderDirection: asc) {
12175
+ id
12176
+ pkpId
12177
+ borrower { id }
12178
+ requestedCollateralRatio
12179
+ selectedTerm
12180
+ expiryAt
12181
+ timestamp
12182
+ blockNumber
12183
+ transactionHash
12184
+ }
12185
+ }
12186
+ ucdmintEvents(where: { position_: { borrower: $borrower } }, first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12187
+ id
12188
+ position { id }
12189
+ amount
12190
+ proof
12191
+ minter { id }
12192
+ isCommunityMint
12193
+ timestamp
12194
+ blockNumber
12195
+ transactionHash
12196
+ }
12197
+ collateralEvents(where: { position_: { borrower: $borrower } }, first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
12198
+ id
12199
+ position { id }
12200
+ eventType
12201
+ networkFee
12202
+ remainingCollateral
12203
+ collateralRatio
12204
+ timestamp
12205
+ blockNumber
12206
+ transactionHash
12207
+ logIndex
12208
+ }
12209
+ }
12210
+ `;
12046
12211
  var DiamondHandsGraph = class {
12047
12212
  client;
12048
12213
  defaultPageSize;
@@ -12148,7 +12313,7 @@ var DiamondHandsGraph = class {
12148
12313
  /**
12149
12314
  * Get user positions from subgraph
12150
12315
  */
12151
- async getUserPositions(userAddress, first, skip, orderBy, orderDirection) {
12316
+ async getUserPositionsOnly(userAddress, first, skip, orderBy, orderDirection) {
12152
12317
  const query = `
12153
12318
  query GetUserPositions($borrower: Bytes!, $first: Int, $skip: Int, $orderBy: Position_orderBy, $orderDirection: OrderDirection) {
12154
12319
  user(id: $borrower) {
@@ -12189,17 +12354,28 @@ var DiamondHandsGraph = class {
12189
12354
  query,
12190
12355
  variables
12191
12356
  );
12192
- const total = await this.getTotalCountPaginated("{ borrower: $borrower }", {
12193
- borrower: userAddress.toLowerCase()
12194
- });
12195
12357
  let positions = [];
12196
12358
  if (result && result.user && Array.isArray(result.user.positions)) {
12197
12359
  positions = result.user.positions.filter((p) => p != null).map((p) => this.transformGraphPositionToLoanData(p));
12198
12360
  }
12199
- return {
12200
- positions,
12201
- total
12202
- };
12361
+ return positions;
12362
+ }
12363
+ /**
12364
+ * Get user positions, plus an accurate total count.
12365
+ *
12366
+ * The count is a SECOND round trip (`getTotalCountPaginated`, which pages to handle
12367
+ * >1000 items). Callers that only need the rows should use `getUserPositionsOnly` and
12368
+ * skip it — the event paths did not, and paid for a count they immediately discarded on
12369
+ * every activity refresh.
12370
+ */
12371
+ async getUserPositions(userAddress, first, skip, orderBy, orderDirection) {
12372
+ const [positions, total] = await Promise.all([
12373
+ this.getUserPositionsOnly(userAddress, first, skip, orderBy, orderDirection),
12374
+ this.getTotalCountPaginated("{ borrower: $borrower }", {
12375
+ borrower: userAddress.toLowerCase()
12376
+ })
12377
+ ]);
12378
+ return { positions, total };
12203
12379
  }
12204
12380
  /**
12205
12381
  * Get user positions with enriched Bitcoin balance data
@@ -13290,6 +13466,16 @@ var DiamondHandsGraph = class {
13290
13466
  orderDirection
13291
13467
  };
13292
13468
  const result = await this.client.execute(query, variables);
13469
+ return this.assembleLoanEvents(positionId, result);
13470
+ }
13471
+ /**
13472
+ * Map one position's raw event payload into `LoanEvents`.
13473
+ *
13474
+ * Extracted verbatim from getLoanEvents so the wallet-collapsed path produces
13475
+ * byte-identical objects by construction rather than by a second implementation
13476
+ * that has to be kept in step by hand.
13477
+ */
13478
+ assembleLoanEvents(positionId, result) {
13293
13479
  const rawCreated = result.positionCreatedEvents?.[0];
13294
13480
  const positionCreated = rawCreated ? {
13295
13481
  id: rawCreated.id,
@@ -13494,7 +13680,22 @@ var DiamondHandsGraph = class {
13494
13680
  * @returns One LoanEvents object per position; empty array if the wallet has none.
13495
13681
  */
13496
13682
  async getWalletLoanEvents(userAddress, filter) {
13497
- const { positions } = await this.getUserPositions(userAddress);
13683
+ if (!hasLoanEventsFilter(filter)) {
13684
+ return this.getWalletLoanEventsCollapsed(userAddress);
13685
+ }
13686
+ return this.getWalletLoanEventsFanout(userAddress, filter);
13687
+ }
13688
+ /**
13689
+ * The per-position path: enumerate the wallet's positions, then one `GetLoanEvents` each.
13690
+ *
13691
+ * Used for filtered calls, and as the completeness fallback when the collapsed document
13692
+ * hits a page limit. Costs `1 + N` requests, which is exactly why it is not the default.
13693
+ */
13694
+ async getWalletLoanEventsFanout(userAddress, filter) {
13695
+ const positions = await this.getUserPositionsOnly(
13696
+ userAddress,
13697
+ THE_GRAPH_MAX_BATCH_SIZE
13698
+ );
13498
13699
  const positionIds = positions.map((p) => p?.id != null ? String(p.id) : "").filter((id) => id.length > 0);
13499
13700
  if (positionIds.length === 0)
13500
13701
  return [];
@@ -13509,6 +13710,81 @@ var DiamondHandsGraph = class {
13509
13710
  }
13510
13711
  return results;
13511
13712
  }
13713
+ /**
13714
+ * The whole wallet's event history in ONE request.
13715
+ *
13716
+ * Replaces `1 + N` round trips (one position enumeration plus one per position) with a
13717
+ * single document. Measured on Sepolia: a wallet holding 44 positions cost 46 requests
13718
+ * per activity refresh against a per-wallet budget of 30/min — this makes it 1.
13719
+ *
13720
+ * Three subgraph facts make it possible, all verified against the deployed schema rather
13721
+ * than assumed:
13722
+ * - ten event collections are `@derivedFrom` on Position, so they nest under a
13723
+ * borrower-filtered `positions(...)`;
13724
+ * - `positionCreatedEvents` is ALSO derived on Position — `getLoanEvents` queries it
13725
+ * top-level, which it never needed to;
13726
+ * - `ucdmintEvents` / `collateralEvents` are not derived and carry no `borrower`
13727
+ * field, but graph-node's nested `position_: { borrower }` filter reaches them.
13728
+ * Without that last one this would be two requests, not one.
13729
+ */
13730
+ async getWalletLoanEventsCollapsed(userAddress) {
13731
+ const borrower = userAddress.toLowerCase();
13732
+ const pageSize = THE_GRAPH_MAX_BATCH_SIZE;
13733
+ const result = await this.client.execute(
13734
+ WALLET_LOAN_EVENTS_QUERY,
13735
+ {
13736
+ borrower,
13737
+ first: pageSize,
13738
+ limit: pageSize,
13739
+ orderDirection: "desc"
13740
+ }
13741
+ );
13742
+ const positions = result.positions || [];
13743
+ const ucdmintEvents = result.ucdmintEvents || [];
13744
+ const collateralEvents = result.collateralEvents || [];
13745
+ const truncated = positions.length >= pageSize || ucdmintEvents.length >= pageSize || collateralEvents.length >= pageSize;
13746
+ if (truncated) {
13747
+ log.warn(
13748
+ "[DiamondHandsGraph] wallet event page limit reached \u2014 falling back to the per-position path to avoid returning a partial history",
13749
+ {
13750
+ borrower,
13751
+ pageSize,
13752
+ positions: positions.length,
13753
+ ucdmintEvents: ucdmintEvents.length,
13754
+ collateralEvents: collateralEvents.length
13755
+ }
13756
+ );
13757
+ return this.getWalletLoanEventsFanout(userAddress);
13758
+ }
13759
+ if (positions.length === 0)
13760
+ return [];
13761
+ const mintsByPosition = /* @__PURE__ */ new Map();
13762
+ for (const m of result.ucdmintEvents || []) {
13763
+ const key = m.position?.id;
13764
+ if (!key)
13765
+ continue;
13766
+ const bucket = mintsByPosition.get(key) || [];
13767
+ bucket.push(m);
13768
+ mintsByPosition.set(key, bucket);
13769
+ }
13770
+ const collateralByPosition = /* @__PURE__ */ new Map();
13771
+ for (const c of result.collateralEvents || []) {
13772
+ const key = c.position?.id;
13773
+ if (!key)
13774
+ continue;
13775
+ const bucket = collateralByPosition.get(key) || [];
13776
+ bucket.push(c);
13777
+ collateralByPosition.set(key, bucket);
13778
+ }
13779
+ return positions.map(
13780
+ (p) => this.assembleLoanEvents(p.id, {
13781
+ position: p,
13782
+ positionCreatedEvents: p.positionCreatedEvents || [],
13783
+ ucdmintEvents: mintsByPosition.get(p.id) || [],
13784
+ collateralEvents: collateralByPosition.get(p.id) || []
13785
+ })
13786
+ );
13787
+ }
13512
13788
  // ============================================================================
13513
13789
  // Protocol-wide Events
13514
13790
  // ============================================================================
@@ -18427,16 +18703,6 @@ var import_dh_lit_actions2 = __toESM(require_pkg_src());
18427
18703
  import { LitOps, broadcastSignedBitcoinTransaction } from "@gvnrdao/dh-lit-ops";
18428
18704
 
18429
18705
  // src/utils/telegram-messaging.utils.ts
18430
- var TelegramBot = null;
18431
- try {
18432
- if (typeof window === "undefined" && typeof global !== "undefined") {
18433
- TelegramBot = __require("node-telegram-bot-api");
18434
- }
18435
- } catch (error) {
18436
- log.warn("Telegram bot API not available", {
18437
- error: error instanceof Error ? error.message : String(error)
18438
- });
18439
- }
18440
18706
  function formatMintMessage(mintAmount, loanId, txHash) {
18441
18707
  return `\u2705 DH SDK: ${mintAmount} UCD was minted for loan id: ${loanId} Tx: https://sepolia.etherscan.io/tx/${txHash}`;
18442
18708
  }
@@ -24436,6 +24702,13 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
24436
24702
  error: "ethRpcUrl required for recoverStaleSpend \u2014 set DiamondHandsSDKConfig.ethRpcUrl or pass rpcUrl"
24437
24703
  };
24438
24704
  }
24705
+ if (!this.config.contractSigner) {
24706
+ return {
24707
+ success: false,
24708
+ failedStep: "config",
24709
+ error: "Contract signer not configured \u2014 recoverStaleSpend submits its own recovery transaction in direct mode. Set DiamondHandsSDKConfig.contractSigner, or use service mode, where the server relays and pays for it."
24710
+ };
24711
+ }
24439
24712
  const sdkBitcoinProviderUrl = this.config.bitcoinProviders?.[0]?.url;
24440
24713
  attRes = await this.litOps.requestStaleSpendRecoveryAttestation({
24441
24714
  chainId,
@@ -487,6 +487,14 @@ var MAINNET_DEPLOYMENT = {
487
487
  reason: "2026-08 agent-stack release. The mainnet PositionManagerViews at 0x9225647a was deployed as a BARE implementation (EIP-1967 slot 0x00), so upgradeToAndCall reverts UUPSUnauthorizedCallContext \u2014 it could never be upgraded. PositionManager.setViews (added in the same Execute B batch) removed the repoint blocker, so Views was replaced behind a new proxy rather than upgraded. This makes the Pashov F3 renewal debt-ceiling check REACHABLE for the first time: ExceedsMaxLoan (0x499e7985) is present in 0xE68DC096 and absent from 0x9225647a. Views holds no protocol state (8 wiring slots + roles + pause), which is what made replacement safe. The old contract is ABANDONED, not decommissioned \u2014 it stays live and callable as the rollback target for setViews. NOTE: VERSION reads 1.1.1 on both sides; verify by address.",
488
488
  executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
489
489
  block: 25673200
490
+ },
491
+ AgentDelegationRegistry: {
492
+ newImplementation: "0xa9fF405Edd4329fc3159a64F56B37EBD253e4928",
493
+ upgradedAt: "2026-07-31T22:03:35.000Z",
494
+ upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4 (block 25655710)",
495
+ reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
496
+ executeTx: "0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4",
497
+ block: 25655710
490
498
  }
491
499
  },
492
500
  latestEnv: {
@@ -460,6 +460,14 @@ var MAINNET_DEPLOYMENT = {
460
460
  reason: "2026-08 agent-stack release. The mainnet PositionManagerViews at 0x9225647a was deployed as a BARE implementation (EIP-1967 slot 0x00), so upgradeToAndCall reverts UUPSUnauthorizedCallContext \u2014 it could never be upgraded. PositionManager.setViews (added in the same Execute B batch) removed the repoint blocker, so Views was replaced behind a new proxy rather than upgraded. This makes the Pashov F3 renewal debt-ceiling check REACHABLE for the first time: ExceedsMaxLoan (0x499e7985) is present in 0xE68DC096 and absent from 0x9225647a. Views holds no protocol state (8 wiring slots + roles + pause), which is what made replacement safe. The old contract is ABANDONED, not decommissioned \u2014 it stays live and callable as the rollback target for setViews. NOTE: VERSION reads 1.1.1 on both sides; verify by address.",
461
461
  executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
462
462
  block: 25673200
463
+ },
464
+ AgentDelegationRegistry: {
465
+ newImplementation: "0xa9fF405Edd4329fc3159a64F56B37EBD253e4928",
466
+ upgradedAt: "2026-07-31T22:03:35.000Z",
467
+ upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4 (block 25655710)",
468
+ reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
469
+ executeTx: "0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4",
470
+ block: 25655710
463
471
  }
464
472
  },
465
473
  latestEnv: {
@@ -1,18 +1,18 @@
1
1
  /**
2
- * Telegram Messaging Utilities
2
+ * Notification Message Formatters
3
3
  *
4
- * Provides functionality to send messages to Telegram chats using the node-telegram-bot-api package
5
- */
6
- /**
7
- * Send a message to a Telegram chat
4
+ * Pure, dependency-free formatters for the protocol lifecycle messages the SDK
5
+ * emits. They are pure string builders: they choose no transport and perform no
6
+ * I/O.
8
7
  *
9
- * @param chatId - Telegram chat ID
10
- * @param chatToken - Telegram bot token
11
- * @param message - Message to send
12
- * @param threadId - Optional thread ID for message threads in groups
13
- * @returns Promise that resolves when message is sent, or rejects on error
8
+ * Dispatch lives elsewhere by design. `DiamondHandsSDK._relayNotification`
9
+ * hands the formatted string to the consumer's `notificationHandler` and, in
10
+ * `service` mode, POSTs it to `lit-ops-server` `/api/lit/notifications/send`;
11
+ * the server owns the bot credentials and talks to `api.telegram.org` directly
12
+ * (`lit-ops-server/src/services/notification.service.ts`). Keeping the token
13
+ * server-side is why no `sendTelegramMessage` belongs here — an in-SDK sender
14
+ * would need the bot token in every consumer's process.
14
15
  */
15
- export declare function sendTelegramMessage(chatId: string, chatToken: string, message: string, threadId?: number): Promise<void>;
16
16
  /**
17
17
  * Format a mint notification message
18
18
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gvnrdao/dh-sdk",
3
- "version": "0.0.327",
3
+ "version": "0.0.329",
4
4
  "description": "TypeScript SDK for Diamond Hands Protocol - Bitcoin-backed lending with LIT Protocol PKPs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -87,8 +87,8 @@
87
87
  },
88
88
  "sideEffects": false,
89
89
  "dependencies": {
90
- "@gvnrdao/dh-lit-actions": "^0.0.320",
91
- "@gvnrdao/dh-lit-ops": "^0.0.312",
90
+ "@gvnrdao/dh-lit-actions": "^0.0.321",
91
+ "@gvnrdao/dh-lit-ops": "^0.0.313",
92
92
  "@noble/hashes": "^1.5.0",
93
93
  "axios": "^1.17.0",
94
94
  "bech32": "^2.0.0",
@@ -106,7 +106,6 @@
106
106
  "@types/crypto-js": "^4.2.2",
107
107
  "@types/jest": "^29.0.0",
108
108
  "@types/node": "^20.0.0",
109
- "@types/node-telegram-bot-api": "^0.64.12",
110
109
  "@typescript-eslint/eslint-plugin": "^6.0.0",
111
110
  "@typescript-eslint/parser": "^6.0.0",
112
111
  "babel-jest": "^29.0.0",
@@ -132,8 +131,5 @@
132
131
  "bugs": {
133
132
  "url": "https://github.com/gvnrdao/diamond-hands/issues"
134
133
  },
135
- "homepage": "https://diamond-hands-protocol.com",
136
- "optionalDependencies": {
137
- "node-telegram-bot-api": "^0.67.0"
138
- }
134
+ "homepage": "https://diamond-hands-protocol.com"
139
135
  }