@gvnrdao/dh-sdk 0.0.328 → 0.0.330
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/browser/dist/browser.js +1 -1
- package/dist/deployments.js +8 -0
- package/dist/deployments.mjs +8 -0
- package/dist/graphs/diamond-hands.d.ts +210 -0
- package/dist/index.js +291 -19
- package/dist/index.mjs +291 -19
- package/dist/safe-delegation.js +8 -0
- package/dist/safe-delegation.mjs +8 -0
- package/dist/utils/telegram-messaging.utils.d.ts +11 -11
- package/package.json +3 -7
package/dist/deployments.js
CHANGED
|
@@ -521,6 +521,14 @@ var MAINNET_DEPLOYMENT = {
|
|
|
521
521
|
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.",
|
|
522
522
|
executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
|
|
523
523
|
block: 25673200
|
|
524
|
+
},
|
|
525
|
+
AgentDelegationRegistry: {
|
|
526
|
+
newImplementation: "0xa9fF405Edd4329fc3159a64F56B37EBD253e4928",
|
|
527
|
+
upgradedAt: "2026-07-31T22:03:35.000Z",
|
|
528
|
+
upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4 (block 25655710)",
|
|
529
|
+
reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
|
|
530
|
+
executeTx: "0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4",
|
|
531
|
+
block: 25655710
|
|
524
532
|
}
|
|
525
533
|
},
|
|
526
534
|
latestEnv: {
|
package/dist/deployments.mjs
CHANGED
|
@@ -488,6 +488,14 @@ var MAINNET_DEPLOYMENT = {
|
|
|
488
488
|
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.",
|
|
489
489
|
executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
|
|
490
490
|
block: 25673200
|
|
491
|
+
},
|
|
492
|
+
AgentDelegationRegistry: {
|
|
493
|
+
newImplementation: "0xa9fF405Edd4329fc3159a64F56B37EBD253e4928",
|
|
494
|
+
upgradedAt: "2026-07-31T22:03:35.000Z",
|
|
495
|
+
upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4 (block 25655710)",
|
|
496
|
+
reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
|
|
497
|
+
executeTx: "0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4",
|
|
498
|
+
block: 25655710
|
|
491
499
|
}
|
|
492
500
|
},
|
|
493
501
|
latestEnv: {
|
|
@@ -86,6 +86,174 @@ export interface UserRateLimitData {
|
|
|
86
86
|
nextResetBlock: string;
|
|
87
87
|
lastUpdated: string;
|
|
88
88
|
}
|
|
89
|
+
export interface LoanEventsQueryResponse {
|
|
90
|
+
position: {
|
|
91
|
+
id: string;
|
|
92
|
+
payments?: Array<{
|
|
93
|
+
id: string;
|
|
94
|
+
payer: {
|
|
95
|
+
id: string;
|
|
96
|
+
};
|
|
97
|
+
amount: string;
|
|
98
|
+
type: string;
|
|
99
|
+
transactionHash: string;
|
|
100
|
+
timestamp: string;
|
|
101
|
+
blockNumber: string;
|
|
102
|
+
logIndex: string;
|
|
103
|
+
newDebt: string;
|
|
104
|
+
newCollateralRatio: string;
|
|
105
|
+
}>;
|
|
106
|
+
statusUpdates?: Array<{
|
|
107
|
+
id: string;
|
|
108
|
+
oldStatus: string;
|
|
109
|
+
newStatus: string;
|
|
110
|
+
reason?: string;
|
|
111
|
+
timestamp: string;
|
|
112
|
+
blockNumber: string;
|
|
113
|
+
transactionHash: string;
|
|
114
|
+
}>;
|
|
115
|
+
liquidation?: {
|
|
116
|
+
id: string;
|
|
117
|
+
liquidator: string;
|
|
118
|
+
liquidatedAmount: string;
|
|
119
|
+
collateralSeized: string;
|
|
120
|
+
transactionHash: string;
|
|
121
|
+
timestamp: string;
|
|
122
|
+
blockNumber: string;
|
|
123
|
+
commitHash?: string;
|
|
124
|
+
commitTimestamp?: string;
|
|
125
|
+
revealDelay?: string;
|
|
126
|
+
};
|
|
127
|
+
withdrawals?: Array<{
|
|
128
|
+
id: string;
|
|
129
|
+
withdrawalAmount: string;
|
|
130
|
+
withdrawalAddress: string;
|
|
131
|
+
networkFee?: string;
|
|
132
|
+
timestamp: string;
|
|
133
|
+
blockNumber: string;
|
|
134
|
+
transactionHash: string;
|
|
135
|
+
logIndex: string;
|
|
136
|
+
}>;
|
|
137
|
+
renewals?: Array<{
|
|
138
|
+
id: string;
|
|
139
|
+
extensionTerm: string;
|
|
140
|
+
extensionFee: string;
|
|
141
|
+
newExpiryDate: string;
|
|
142
|
+
timestamp: string;
|
|
143
|
+
blockNumber: string;
|
|
144
|
+
transactionHash: string;
|
|
145
|
+
logIndex: string;
|
|
146
|
+
}>;
|
|
147
|
+
operationFailures?: Array<{
|
|
148
|
+
id: string;
|
|
149
|
+
operationType: string;
|
|
150
|
+
reason: string;
|
|
151
|
+
errorCode?: string;
|
|
152
|
+
amount?: string;
|
|
153
|
+
timestamp: string;
|
|
154
|
+
blockNumber: string;
|
|
155
|
+
transactionHash: string;
|
|
156
|
+
logIndex: string;
|
|
157
|
+
}>;
|
|
158
|
+
mintRequests?: Array<{
|
|
159
|
+
id: string;
|
|
160
|
+
pkpId: string;
|
|
161
|
+
borrower: {
|
|
162
|
+
id: string;
|
|
163
|
+
};
|
|
164
|
+
mintAmount: string;
|
|
165
|
+
originationFee: string;
|
|
166
|
+
newDebt: string;
|
|
167
|
+
newCollateralRatio: string;
|
|
168
|
+
btcPrice: string;
|
|
169
|
+
quantumTimestamp: string;
|
|
170
|
+
opId: string;
|
|
171
|
+
timestamp: string;
|
|
172
|
+
blockNumber: string;
|
|
173
|
+
transactionHash: string;
|
|
174
|
+
logIndex: string;
|
|
175
|
+
}>;
|
|
176
|
+
burnRequests?: Array<{
|
|
177
|
+
id: string;
|
|
178
|
+
pkpId: string;
|
|
179
|
+
borrower: {
|
|
180
|
+
id: string;
|
|
181
|
+
};
|
|
182
|
+
burnAmount: string;
|
|
183
|
+
remainingDebt: string;
|
|
184
|
+
newCollateralRatio: string;
|
|
185
|
+
opId: string;
|
|
186
|
+
timestamp: string;
|
|
187
|
+
blockNumber: string;
|
|
188
|
+
transactionHash: string;
|
|
189
|
+
logIndex: string;
|
|
190
|
+
}>;
|
|
191
|
+
mintingFees?: Array<{
|
|
192
|
+
id: string;
|
|
193
|
+
borrower: {
|
|
194
|
+
id: string;
|
|
195
|
+
};
|
|
196
|
+
feeAmount: string;
|
|
197
|
+
mintAmount: string;
|
|
198
|
+
newDebt: string;
|
|
199
|
+
btcPrice: string;
|
|
200
|
+
quantumTimestamp: string;
|
|
201
|
+
timestamp: string;
|
|
202
|
+
blockNumber: string;
|
|
203
|
+
transactionHash: string;
|
|
204
|
+
logIndex: string;
|
|
205
|
+
}>;
|
|
206
|
+
renewalFees?: Array<{
|
|
207
|
+
id: string;
|
|
208
|
+
borrower: {
|
|
209
|
+
id: string;
|
|
210
|
+
};
|
|
211
|
+
feeAmount: string;
|
|
212
|
+
extensionTerm: string;
|
|
213
|
+
newExpiryDate: string;
|
|
214
|
+
timestamp: string;
|
|
215
|
+
blockNumber: string;
|
|
216
|
+
transactionHash: string;
|
|
217
|
+
logIndex: string;
|
|
218
|
+
}>;
|
|
219
|
+
};
|
|
220
|
+
positionCreatedEvents?: Array<{
|
|
221
|
+
id: string;
|
|
222
|
+
pkpId: string;
|
|
223
|
+
borrower: {
|
|
224
|
+
id: string;
|
|
225
|
+
};
|
|
226
|
+
requestedCollateralRatio: string;
|
|
227
|
+
selectedTerm: string;
|
|
228
|
+
expiryAt: string;
|
|
229
|
+
timestamp: string;
|
|
230
|
+
blockNumber: string;
|
|
231
|
+
transactionHash: string;
|
|
232
|
+
}>;
|
|
233
|
+
ucdmintEvents?: Array<{
|
|
234
|
+
id: string;
|
|
235
|
+
amount: string;
|
|
236
|
+
proof: string;
|
|
237
|
+
minter: {
|
|
238
|
+
id: string;
|
|
239
|
+
};
|
|
240
|
+
isCommunityMint: boolean;
|
|
241
|
+
timestamp: string;
|
|
242
|
+
blockNumber: string;
|
|
243
|
+
transactionHash: string;
|
|
244
|
+
}>;
|
|
245
|
+
collateralEvents?: Array<{
|
|
246
|
+
id: string;
|
|
247
|
+
eventType: string;
|
|
248
|
+
networkFee?: string;
|
|
249
|
+
remainingCollateral?: string;
|
|
250
|
+
collateralRatio?: string;
|
|
251
|
+
timestamp: string;
|
|
252
|
+
blockNumber: string;
|
|
253
|
+
transactionHash: string;
|
|
254
|
+
logIndex: string;
|
|
255
|
+
}>;
|
|
256
|
+
}
|
|
89
257
|
export declare class DiamondHandsGraph {
|
|
90
258
|
private client;
|
|
91
259
|
private defaultPageSize;
|
|
@@ -115,6 +283,15 @@ export declare class DiamondHandsGraph {
|
|
|
115
283
|
/**
|
|
116
284
|
* Get user positions from subgraph
|
|
117
285
|
*/
|
|
286
|
+
private getUserPositionsOnly;
|
|
287
|
+
/**
|
|
288
|
+
* Get user positions, plus an accurate total count.
|
|
289
|
+
*
|
|
290
|
+
* The count is a SECOND round trip (`getTotalCountPaginated`, which pages to handle
|
|
291
|
+
* >1000 items). Callers that only need the rows should use `getUserPositionsOnly` and
|
|
292
|
+
* skip it — the event paths did not, and paid for a count they immediately discarded on
|
|
293
|
+
* every activity refresh.
|
|
294
|
+
*/
|
|
118
295
|
getUserPositions(userAddress: string, first?: number, skip?: number, orderBy?: string, orderDirection?: string): Promise<{
|
|
119
296
|
positions: LoanData[];
|
|
120
297
|
total: number;
|
|
@@ -262,6 +439,14 @@ export declare class DiamondHandsGraph {
|
|
|
262
439
|
* @returns Complete event history for the position
|
|
263
440
|
*/
|
|
264
441
|
getLoanEvents(positionId: string, filter?: LoanEventsFilter): Promise<LoanEvents>;
|
|
442
|
+
/**
|
|
443
|
+
* Map one position's raw event payload into `LoanEvents`.
|
|
444
|
+
*
|
|
445
|
+
* Extracted verbatim from getLoanEvents so the wallet-collapsed path produces
|
|
446
|
+
* byte-identical objects by construction rather than by a second implementation
|
|
447
|
+
* that has to be kept in step by hand.
|
|
448
|
+
*/
|
|
449
|
+
private assembleLoanEvents;
|
|
265
450
|
/**
|
|
266
451
|
* Get the full loan-event history for every position owned by a wallet.
|
|
267
452
|
*
|
|
@@ -280,6 +465,31 @@ export declare class DiamondHandsGraph {
|
|
|
280
465
|
* @returns One LoanEvents object per position; empty array if the wallet has none.
|
|
281
466
|
*/
|
|
282
467
|
getWalletLoanEvents(userAddress: string, filter?: LoanEventsFilter): Promise<LoanEvents[]>;
|
|
468
|
+
/**
|
|
469
|
+
* The per-position path: enumerate the wallet's positions, then one `GetLoanEvents` each.
|
|
470
|
+
*
|
|
471
|
+
* Used for filtered calls, and as the completeness fallback when the collapsed document
|
|
472
|
+
* hits a page limit. Costs `1 + N` requests, which is exactly why it is not the default.
|
|
473
|
+
*/
|
|
474
|
+
private getWalletLoanEventsFanout;
|
|
475
|
+
/**
|
|
476
|
+
* The whole wallet's event history in ONE request.
|
|
477
|
+
*
|
|
478
|
+
* Replaces `1 + N` round trips (one position enumeration plus one per position) with a
|
|
479
|
+
* single document. Measured on Sepolia: a wallet holding 44 positions cost 46 requests
|
|
480
|
+
* per activity refresh against a per-wallet budget of 30/min — this makes it 1.
|
|
481
|
+
*
|
|
482
|
+
* Three subgraph facts make it possible, all verified against the deployed schema rather
|
|
483
|
+
* than assumed:
|
|
484
|
+
* - ten event collections are `@derivedFrom` on Position, so they nest under a
|
|
485
|
+
* borrower-filtered `positions(...)`;
|
|
486
|
+
* - `positionCreatedEvents` is ALSO derived on Position — `getLoanEvents` queries it
|
|
487
|
+
* top-level, which it never needed to;
|
|
488
|
+
* - `ucdmintEvents` / `collateralEvents` are not derived and carry no `borrower`
|
|
489
|
+
* field, but graph-node's nested `position_: { borrower }` filter reaches them.
|
|
490
|
+
* Without that last one this would be two requests, not one.
|
|
491
|
+
*/
|
|
492
|
+
private getWalletLoanEventsCollapsed;
|
|
283
493
|
/**
|
|
284
494
|
* Retrieve events across the full protocol, optionally narrowed to a position.
|
|
285
495
|
* Returns a merged, sorted discriminated-union timeline suitable for explorers.
|
package/dist/index.js
CHANGED
|
@@ -546,6 +546,14 @@ var init_deployment_addresses = __esm({
|
|
|
546
546
|
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.",
|
|
547
547
|
executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
|
|
548
548
|
block: 25673200
|
|
549
|
+
},
|
|
550
|
+
AgentDelegationRegistry: {
|
|
551
|
+
newImplementation: "0xa9fF405Edd4329fc3159a64F56B37EBD253e4928",
|
|
552
|
+
upgradedAt: "2026-07-31T22:03:35.000Z",
|
|
553
|
+
upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4 (block 25655710)",
|
|
554
|
+
reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
|
|
555
|
+
executeTx: "0x8fed0ab7eee3aaaa3792a35b40b0ef74bd09cfb1a175934afd846bee546048d4",
|
|
556
|
+
block: 25655710
|
|
549
557
|
}
|
|
550
558
|
},
|
|
551
559
|
latestEnv: {
|
|
@@ -12120,6 +12128,169 @@ function normalizePkpId2(pkpId) {
|
|
|
12120
12128
|
}
|
|
12121
12129
|
return pkpId;
|
|
12122
12130
|
}
|
|
12131
|
+
function hasLoanEventsFilter(filter) {
|
|
12132
|
+
if (!filter)
|
|
12133
|
+
return false;
|
|
12134
|
+
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;
|
|
12135
|
+
}
|
|
12136
|
+
var WALLET_LOAN_EVENTS_QUERY = `
|
|
12137
|
+
query GetWalletLoanEvents($borrower: Bytes!, $first: Int!, $limit: Int!, $orderDirection: OrderDirection!) {
|
|
12138
|
+
positions(where: { borrower: $borrower }, first: $first, orderBy: id) {
|
|
12139
|
+
id
|
|
12140
|
+
payments(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12141
|
+
id
|
|
12142
|
+
payer { id }
|
|
12143
|
+
amount
|
|
12144
|
+
type
|
|
12145
|
+
transactionHash
|
|
12146
|
+
timestamp
|
|
12147
|
+
blockNumber
|
|
12148
|
+
logIndex
|
|
12149
|
+
newDebt
|
|
12150
|
+
newCollateralRatio
|
|
12151
|
+
}
|
|
12152
|
+
statusUpdates(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12153
|
+
id
|
|
12154
|
+
oldStatus
|
|
12155
|
+
newStatus
|
|
12156
|
+
reason
|
|
12157
|
+
timestamp
|
|
12158
|
+
blockNumber
|
|
12159
|
+
transactionHash
|
|
12160
|
+
}
|
|
12161
|
+
liquidation {
|
|
12162
|
+
id
|
|
12163
|
+
liquidator
|
|
12164
|
+
liquidatedAmount
|
|
12165
|
+
collateralSeized
|
|
12166
|
+
transactionHash
|
|
12167
|
+
timestamp
|
|
12168
|
+
blockNumber
|
|
12169
|
+
commitHash
|
|
12170
|
+
commitTimestamp
|
|
12171
|
+
revealDelay
|
|
12172
|
+
}
|
|
12173
|
+
withdrawals(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12174
|
+
id
|
|
12175
|
+
withdrawalAmount
|
|
12176
|
+
withdrawalAddress
|
|
12177
|
+
networkFee
|
|
12178
|
+
timestamp
|
|
12179
|
+
blockNumber
|
|
12180
|
+
transactionHash
|
|
12181
|
+
logIndex
|
|
12182
|
+
}
|
|
12183
|
+
renewals(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12184
|
+
id
|
|
12185
|
+
extensionTerm
|
|
12186
|
+
extensionFee
|
|
12187
|
+
newExpiryDate
|
|
12188
|
+
timestamp
|
|
12189
|
+
blockNumber
|
|
12190
|
+
transactionHash
|
|
12191
|
+
logIndex
|
|
12192
|
+
}
|
|
12193
|
+
operationFailures(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12194
|
+
id
|
|
12195
|
+
operationType
|
|
12196
|
+
reason
|
|
12197
|
+
errorCode
|
|
12198
|
+
amount
|
|
12199
|
+
timestamp
|
|
12200
|
+
blockNumber
|
|
12201
|
+
transactionHash
|
|
12202
|
+
logIndex
|
|
12203
|
+
}
|
|
12204
|
+
mintRequests(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12205
|
+
id
|
|
12206
|
+
pkpId
|
|
12207
|
+
borrower { id }
|
|
12208
|
+
mintAmount
|
|
12209
|
+
originationFee
|
|
12210
|
+
newDebt
|
|
12211
|
+
newCollateralRatio
|
|
12212
|
+
btcPrice
|
|
12213
|
+
quantumTimestamp
|
|
12214
|
+
opId
|
|
12215
|
+
timestamp
|
|
12216
|
+
blockNumber
|
|
12217
|
+
transactionHash
|
|
12218
|
+
logIndex
|
|
12219
|
+
}
|
|
12220
|
+
burnRequests(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12221
|
+
id
|
|
12222
|
+
pkpId
|
|
12223
|
+
borrower { id }
|
|
12224
|
+
burnAmount
|
|
12225
|
+
remainingDebt
|
|
12226
|
+
newCollateralRatio
|
|
12227
|
+
opId
|
|
12228
|
+
timestamp
|
|
12229
|
+
blockNumber
|
|
12230
|
+
transactionHash
|
|
12231
|
+
logIndex
|
|
12232
|
+
}
|
|
12233
|
+
mintingFees(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12234
|
+
id
|
|
12235
|
+
borrower { id }
|
|
12236
|
+
feeAmount
|
|
12237
|
+
mintAmount
|
|
12238
|
+
newDebt
|
|
12239
|
+
btcPrice
|
|
12240
|
+
quantumTimestamp
|
|
12241
|
+
timestamp
|
|
12242
|
+
blockNumber
|
|
12243
|
+
transactionHash
|
|
12244
|
+
logIndex
|
|
12245
|
+
}
|
|
12246
|
+
renewalFees(first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12247
|
+
id
|
|
12248
|
+
borrower { id }
|
|
12249
|
+
feeAmount
|
|
12250
|
+
extensionTerm
|
|
12251
|
+
newExpiryDate
|
|
12252
|
+
timestamp
|
|
12253
|
+
blockNumber
|
|
12254
|
+
transactionHash
|
|
12255
|
+
logIndex
|
|
12256
|
+
}
|
|
12257
|
+
positionCreatedEvents(first: 1, orderBy: timestamp, orderDirection: asc) {
|
|
12258
|
+
id
|
|
12259
|
+
pkpId
|
|
12260
|
+
borrower { id }
|
|
12261
|
+
requestedCollateralRatio
|
|
12262
|
+
selectedTerm
|
|
12263
|
+
expiryAt
|
|
12264
|
+
timestamp
|
|
12265
|
+
blockNumber
|
|
12266
|
+
transactionHash
|
|
12267
|
+
}
|
|
12268
|
+
}
|
|
12269
|
+
ucdmintEvents(where: { position_: { borrower: $borrower } }, first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12270
|
+
id
|
|
12271
|
+
position { id }
|
|
12272
|
+
amount
|
|
12273
|
+
proof
|
|
12274
|
+
minter { id }
|
|
12275
|
+
isCommunityMint
|
|
12276
|
+
timestamp
|
|
12277
|
+
blockNumber
|
|
12278
|
+
transactionHash
|
|
12279
|
+
}
|
|
12280
|
+
collateralEvents(where: { position_: { borrower: $borrower } }, first: $limit, orderBy: timestamp, orderDirection: $orderDirection) {
|
|
12281
|
+
id
|
|
12282
|
+
position { id }
|
|
12283
|
+
eventType
|
|
12284
|
+
networkFee
|
|
12285
|
+
remainingCollateral
|
|
12286
|
+
collateralRatio
|
|
12287
|
+
timestamp
|
|
12288
|
+
blockNumber
|
|
12289
|
+
transactionHash
|
|
12290
|
+
logIndex
|
|
12291
|
+
}
|
|
12292
|
+
}
|
|
12293
|
+
`;
|
|
12123
12294
|
var DiamondHandsGraph = class {
|
|
12124
12295
|
client;
|
|
12125
12296
|
defaultPageSize;
|
|
@@ -12225,7 +12396,7 @@ var DiamondHandsGraph = class {
|
|
|
12225
12396
|
/**
|
|
12226
12397
|
* Get user positions from subgraph
|
|
12227
12398
|
*/
|
|
12228
|
-
async
|
|
12399
|
+
async getUserPositionsOnly(userAddress, first, skip, orderBy, orderDirection) {
|
|
12229
12400
|
const query = `
|
|
12230
12401
|
query GetUserPositions($borrower: Bytes!, $first: Int, $skip: Int, $orderBy: Position_orderBy, $orderDirection: OrderDirection) {
|
|
12231
12402
|
user(id: $borrower) {
|
|
@@ -12266,17 +12437,28 @@ var DiamondHandsGraph = class {
|
|
|
12266
12437
|
query,
|
|
12267
12438
|
variables
|
|
12268
12439
|
);
|
|
12269
|
-
const total = await this.getTotalCountPaginated("{ borrower: $borrower }", {
|
|
12270
|
-
borrower: userAddress.toLowerCase()
|
|
12271
|
-
});
|
|
12272
12440
|
let positions = [];
|
|
12273
12441
|
if (result && result.user && Array.isArray(result.user.positions)) {
|
|
12274
12442
|
positions = result.user.positions.filter((p) => p != null).map((p) => this.transformGraphPositionToLoanData(p));
|
|
12275
12443
|
}
|
|
12276
|
-
return
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
|
|
12444
|
+
return positions;
|
|
12445
|
+
}
|
|
12446
|
+
/**
|
|
12447
|
+
* Get user positions, plus an accurate total count.
|
|
12448
|
+
*
|
|
12449
|
+
* The count is a SECOND round trip (`getTotalCountPaginated`, which pages to handle
|
|
12450
|
+
* >1000 items). Callers that only need the rows should use `getUserPositionsOnly` and
|
|
12451
|
+
* skip it — the event paths did not, and paid for a count they immediately discarded on
|
|
12452
|
+
* every activity refresh.
|
|
12453
|
+
*/
|
|
12454
|
+
async getUserPositions(userAddress, first, skip, orderBy, orderDirection) {
|
|
12455
|
+
const [positions, total] = await Promise.all([
|
|
12456
|
+
this.getUserPositionsOnly(userAddress, first, skip, orderBy, orderDirection),
|
|
12457
|
+
this.getTotalCountPaginated("{ borrower: $borrower }", {
|
|
12458
|
+
borrower: userAddress.toLowerCase()
|
|
12459
|
+
})
|
|
12460
|
+
]);
|
|
12461
|
+
return { positions, total };
|
|
12280
12462
|
}
|
|
12281
12463
|
/**
|
|
12282
12464
|
* Get user positions with enriched Bitcoin balance data
|
|
@@ -13367,6 +13549,16 @@ var DiamondHandsGraph = class {
|
|
|
13367
13549
|
orderDirection
|
|
13368
13550
|
};
|
|
13369
13551
|
const result = await this.client.execute(query, variables);
|
|
13552
|
+
return this.assembleLoanEvents(positionId, result);
|
|
13553
|
+
}
|
|
13554
|
+
/**
|
|
13555
|
+
* Map one position's raw event payload into `LoanEvents`.
|
|
13556
|
+
*
|
|
13557
|
+
* Extracted verbatim from getLoanEvents so the wallet-collapsed path produces
|
|
13558
|
+
* byte-identical objects by construction rather than by a second implementation
|
|
13559
|
+
* that has to be kept in step by hand.
|
|
13560
|
+
*/
|
|
13561
|
+
assembleLoanEvents(positionId, result) {
|
|
13370
13562
|
const rawCreated = result.positionCreatedEvents?.[0];
|
|
13371
13563
|
const positionCreated = rawCreated ? {
|
|
13372
13564
|
id: rawCreated.id,
|
|
@@ -13571,7 +13763,22 @@ var DiamondHandsGraph = class {
|
|
|
13571
13763
|
* @returns One LoanEvents object per position; empty array if the wallet has none.
|
|
13572
13764
|
*/
|
|
13573
13765
|
async getWalletLoanEvents(userAddress, filter) {
|
|
13574
|
-
|
|
13766
|
+
if (!hasLoanEventsFilter(filter)) {
|
|
13767
|
+
return this.getWalletLoanEventsCollapsed(userAddress);
|
|
13768
|
+
}
|
|
13769
|
+
return this.getWalletLoanEventsFanout(userAddress, filter);
|
|
13770
|
+
}
|
|
13771
|
+
/**
|
|
13772
|
+
* The per-position path: enumerate the wallet's positions, then one `GetLoanEvents` each.
|
|
13773
|
+
*
|
|
13774
|
+
* Used for filtered calls, and as the completeness fallback when the collapsed document
|
|
13775
|
+
* hits a page limit. Costs `1 + N` requests, which is exactly why it is not the default.
|
|
13776
|
+
*/
|
|
13777
|
+
async getWalletLoanEventsFanout(userAddress, filter) {
|
|
13778
|
+
const positions = await this.getUserPositionsOnly(
|
|
13779
|
+
userAddress,
|
|
13780
|
+
THE_GRAPH_MAX_BATCH_SIZE
|
|
13781
|
+
);
|
|
13575
13782
|
const positionIds = positions.map((p) => p?.id != null ? String(p.id) : "").filter((id) => id.length > 0);
|
|
13576
13783
|
if (positionIds.length === 0)
|
|
13577
13784
|
return [];
|
|
@@ -13586,6 +13793,81 @@ var DiamondHandsGraph = class {
|
|
|
13586
13793
|
}
|
|
13587
13794
|
return results;
|
|
13588
13795
|
}
|
|
13796
|
+
/**
|
|
13797
|
+
* The whole wallet's event history in ONE request.
|
|
13798
|
+
*
|
|
13799
|
+
* Replaces `1 + N` round trips (one position enumeration plus one per position) with a
|
|
13800
|
+
* single document. Measured on Sepolia: a wallet holding 44 positions cost 46 requests
|
|
13801
|
+
* per activity refresh against a per-wallet budget of 30/min — this makes it 1.
|
|
13802
|
+
*
|
|
13803
|
+
* Three subgraph facts make it possible, all verified against the deployed schema rather
|
|
13804
|
+
* than assumed:
|
|
13805
|
+
* - ten event collections are `@derivedFrom` on Position, so they nest under a
|
|
13806
|
+
* borrower-filtered `positions(...)`;
|
|
13807
|
+
* - `positionCreatedEvents` is ALSO derived on Position — `getLoanEvents` queries it
|
|
13808
|
+
* top-level, which it never needed to;
|
|
13809
|
+
* - `ucdmintEvents` / `collateralEvents` are not derived and carry no `borrower`
|
|
13810
|
+
* field, but graph-node's nested `position_: { borrower }` filter reaches them.
|
|
13811
|
+
* Without that last one this would be two requests, not one.
|
|
13812
|
+
*/
|
|
13813
|
+
async getWalletLoanEventsCollapsed(userAddress) {
|
|
13814
|
+
const borrower = userAddress.toLowerCase();
|
|
13815
|
+
const pageSize = THE_GRAPH_MAX_BATCH_SIZE;
|
|
13816
|
+
const result = await this.client.execute(
|
|
13817
|
+
WALLET_LOAN_EVENTS_QUERY,
|
|
13818
|
+
{
|
|
13819
|
+
borrower,
|
|
13820
|
+
first: pageSize,
|
|
13821
|
+
limit: pageSize,
|
|
13822
|
+
orderDirection: "desc"
|
|
13823
|
+
}
|
|
13824
|
+
);
|
|
13825
|
+
const positions = result.positions || [];
|
|
13826
|
+
const ucdmintEvents = result.ucdmintEvents || [];
|
|
13827
|
+
const collateralEvents = result.collateralEvents || [];
|
|
13828
|
+
const truncated = positions.length >= pageSize || ucdmintEvents.length >= pageSize || collateralEvents.length >= pageSize;
|
|
13829
|
+
if (truncated) {
|
|
13830
|
+
log.warn(
|
|
13831
|
+
"[DiamondHandsGraph] wallet event page limit reached \u2014 falling back to the per-position path to avoid returning a partial history",
|
|
13832
|
+
{
|
|
13833
|
+
borrower,
|
|
13834
|
+
pageSize,
|
|
13835
|
+
positions: positions.length,
|
|
13836
|
+
ucdmintEvents: ucdmintEvents.length,
|
|
13837
|
+
collateralEvents: collateralEvents.length
|
|
13838
|
+
}
|
|
13839
|
+
);
|
|
13840
|
+
return this.getWalletLoanEventsFanout(userAddress);
|
|
13841
|
+
}
|
|
13842
|
+
if (positions.length === 0)
|
|
13843
|
+
return [];
|
|
13844
|
+
const mintsByPosition = /* @__PURE__ */ new Map();
|
|
13845
|
+
for (const m of result.ucdmintEvents || []) {
|
|
13846
|
+
const key = m.position?.id;
|
|
13847
|
+
if (!key)
|
|
13848
|
+
continue;
|
|
13849
|
+
const bucket = mintsByPosition.get(key) || [];
|
|
13850
|
+
bucket.push(m);
|
|
13851
|
+
mintsByPosition.set(key, bucket);
|
|
13852
|
+
}
|
|
13853
|
+
const collateralByPosition = /* @__PURE__ */ new Map();
|
|
13854
|
+
for (const c of result.collateralEvents || []) {
|
|
13855
|
+
const key = c.position?.id;
|
|
13856
|
+
if (!key)
|
|
13857
|
+
continue;
|
|
13858
|
+
const bucket = collateralByPosition.get(key) || [];
|
|
13859
|
+
bucket.push(c);
|
|
13860
|
+
collateralByPosition.set(key, bucket);
|
|
13861
|
+
}
|
|
13862
|
+
return positions.map(
|
|
13863
|
+
(p) => this.assembleLoanEvents(p.id, {
|
|
13864
|
+
position: p,
|
|
13865
|
+
positionCreatedEvents: p.positionCreatedEvents || [],
|
|
13866
|
+
ucdmintEvents: mintsByPosition.get(p.id) || [],
|
|
13867
|
+
collateralEvents: collateralByPosition.get(p.id) || []
|
|
13868
|
+
})
|
|
13869
|
+
);
|
|
13870
|
+
}
|
|
13589
13871
|
// ============================================================================
|
|
13590
13872
|
// Protocol-wide Events
|
|
13591
13873
|
// ============================================================================
|
|
@@ -18496,16 +18778,6 @@ var import_dh_lit_ops = require("@gvnrdao/dh-lit-ops");
|
|
|
18496
18778
|
var import_dh_lit_actions2 = __toESM(require_pkg_src());
|
|
18497
18779
|
|
|
18498
18780
|
// src/utils/telegram-messaging.utils.ts
|
|
18499
|
-
var TelegramBot = null;
|
|
18500
|
-
try {
|
|
18501
|
-
if (typeof window === "undefined" && typeof global !== "undefined") {
|
|
18502
|
-
TelegramBot = require("node-telegram-bot-api");
|
|
18503
|
-
}
|
|
18504
|
-
} catch (error) {
|
|
18505
|
-
log.warn("Telegram bot API not available", {
|
|
18506
|
-
error: error instanceof Error ? error.message : String(error)
|
|
18507
|
-
});
|
|
18508
|
-
}
|
|
18509
18781
|
function formatMintMessage(mintAmount, loanId, txHash) {
|
|
18510
18782
|
return `\u2705 DH SDK: ${mintAmount} UCD was minted for loan id: ${loanId} Tx: https://sepolia.etherscan.io/tx/${txHash}`;
|
|
18511
18783
|
}
|