@permissionless-technologies/upd-sdk 0.1.0

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.
Files changed (68) hide show
  1. package/README.md +172 -0
  2. package/dist/chunk-4RBWWS2X.js +6616 -0
  3. package/dist/chunk-4RBWWS2X.js.map +1 -0
  4. package/dist/chunk-4VXNJTNQ.cjs +58 -0
  5. package/dist/chunk-4VXNJTNQ.cjs.map +1 -0
  6. package/dist/chunk-5NNXIJE4.js +16 -0
  7. package/dist/chunk-5NNXIJE4.js.map +1 -0
  8. package/dist/chunk-63FIKV36.js +49 -0
  9. package/dist/chunk-63FIKV36.js.map +1 -0
  10. package/dist/chunk-CZEDT3MS.cjs +62 -0
  11. package/dist/chunk-CZEDT3MS.cjs.map +1 -0
  12. package/dist/chunk-DF34ON56.cjs +18 -0
  13. package/dist/chunk-DF34ON56.cjs.map +1 -0
  14. package/dist/chunk-DJBU2OEB.js +57 -0
  15. package/dist/chunk-DJBU2OEB.js.map +1 -0
  16. package/dist/chunk-LNGWRYGY.js +3 -0
  17. package/dist/chunk-LNGWRYGY.js.map +1 -0
  18. package/dist/chunk-POBNO37G.cjs +4 -0
  19. package/dist/chunk-POBNO37G.cjs.map +1 -0
  20. package/dist/chunk-R64I3LAO.js +701 -0
  21. package/dist/chunk-R64I3LAO.js.map +1 -0
  22. package/dist/chunk-RIRT4JX6.js +1808 -0
  23. package/dist/chunk-RIRT4JX6.js.map +1 -0
  24. package/dist/chunk-WRPVPA7E.cjs +713 -0
  25. package/dist/chunk-WRPVPA7E.cjs.map +1 -0
  26. package/dist/chunk-ZDAHLZWC.cjs +1812 -0
  27. package/dist/chunk-ZDAHLZWC.cjs.map +1 -0
  28. package/dist/chunk-ZSWETUGH.cjs +6623 -0
  29. package/dist/chunk-ZSWETUGH.cjs.map +1 -0
  30. package/dist/constants-Bk2bGYfX.d.ts +64 -0
  31. package/dist/constants-BlOP_9dy.d.cts +64 -0
  32. package/dist/contracts/index.cjs +45 -0
  33. package/dist/contracts/index.cjs.map +1 -0
  34. package/dist/contracts/index.d.cts +6559 -0
  35. package/dist/contracts/index.d.ts +6559 -0
  36. package/dist/contracts/index.js +4 -0
  37. package/dist/contracts/index.js.map +1 -0
  38. package/dist/core/index.cjs +76 -0
  39. package/dist/core/index.cjs.map +1 -0
  40. package/dist/core/index.d.cts +5 -0
  41. package/dist/core/index.d.ts +5 -0
  42. package/dist/core/index.js +7 -0
  43. package/dist/core/index.js.map +1 -0
  44. package/dist/health-BUb4ItNt.d.ts +46 -0
  45. package/dist/health-DPxBqH7b.d.cts +46 -0
  46. package/dist/index-XNClksom.d.ts +415 -0
  47. package/dist/index-yRBqVOHV.d.cts +415 -0
  48. package/dist/index.cjs +138 -0
  49. package/dist/index.cjs.map +1 -0
  50. package/dist/index.d.cts +7 -0
  51. package/dist/index.d.ts +7 -0
  52. package/dist/index.js +9 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/oracle/index.cjs +30 -0
  55. package/dist/oracle/index.cjs.map +1 -0
  56. package/dist/oracle/index.d.cts +41 -0
  57. package/dist/oracle/index.d.ts +41 -0
  58. package/dist/oracle/index.js +5 -0
  59. package/dist/oracle/index.js.map +1 -0
  60. package/dist/react/index.cjs +383 -0
  61. package/dist/react/index.cjs.map +1 -0
  62. package/dist/react/index.d.cts +339 -0
  63. package/dist/react/index.d.ts +339 -0
  64. package/dist/react/index.js +370 -0
  65. package/dist/react/index.js.map +1 -0
  66. package/dist/types-DySv82My.d.cts +70 -0
  67. package/dist/types-DySv82My.d.ts +70 -0
  68. package/package.json +93 -0
@@ -0,0 +1,370 @@
1
+ import '../chunk-RIRT4JX6.js';
2
+ import { quoteMintUPD, quoteBurnUPD, computeSystemHealth } from '../chunk-63FIKV36.js';
3
+ import { UPD_TOKEN_ABI, OVERCOLLATERALIZATION_REPORTER_ABI, STABILIZER_NFT_ABI, SUPD_ABI } from '../chunk-4RBWWS2X.js';
4
+ import { createOracleClient } from '../chunk-DJBU2OEB.js';
5
+ import { useReadContract, useWriteContract, useWaitForTransactionReceipt } from 'wagmi';
6
+ import { useQuery } from '@tanstack/react-query';
7
+ import { useMemo } from 'react';
8
+
9
+ function useUPD(config) {
10
+ const { tokenAddress, userAddress } = config;
11
+ const { data: balance, isLoading: balanceLoading } = useReadContract({
12
+ address: tokenAddress,
13
+ abi: UPD_TOKEN_ABI,
14
+ functionName: "balanceOf",
15
+ args: userAddress ? [userAddress] : void 0,
16
+ query: { enabled: !!userAddress }
17
+ });
18
+ const { data: totalSupply, isLoading: supplyLoading } = useReadContract({
19
+ address: tokenAddress,
20
+ abi: UPD_TOKEN_ABI,
21
+ functionName: "totalSupply"
22
+ });
23
+ return {
24
+ balance,
25
+ totalSupply,
26
+ isLoading: balanceLoading || supplyLoading
27
+ };
28
+ }
29
+ function useCollateral(config) {
30
+ const { reporterAddress, tokenAddress } = config;
31
+ const { data: totalStEthCollateral, isLoading: collateralLoading } = useReadContract({
32
+ address: reporterAddress,
33
+ abi: OVERCOLLATERALIZATION_REPORTER_ABI,
34
+ functionName: "totalStEthCollateral"
35
+ });
36
+ const { data: totalUPDSupply, isLoading: supplyLoading } = useReadContract({
37
+ address: tokenAddress,
38
+ abi: UPD_TOKEN_ABI,
39
+ functionName: "totalSupply"
40
+ });
41
+ return {
42
+ totalStEthCollateral,
43
+ totalUPDSupply,
44
+ isLoading: collateralLoading || supplyLoading
45
+ };
46
+ }
47
+ function useStabilizer(config) {
48
+ const { stabilizerNFTAddress, tokenId } = config;
49
+ const { data: positionEscrow, isLoading: posLoading } = useReadContract({
50
+ address: stabilizerNFTAddress,
51
+ abi: STABILIZER_NFT_ABI,
52
+ functionName: "positionEscrows",
53
+ args: tokenId !== void 0 ? [tokenId] : void 0,
54
+ query: { enabled: tokenId !== void 0 }
55
+ });
56
+ const { data: stabilizerEscrow, isLoading: stabLoading } = useReadContract({
57
+ address: stabilizerNFTAddress,
58
+ abi: STABILIZER_NFT_ABI,
59
+ functionName: "stabilizerEscrows",
60
+ args: tokenId !== void 0 ? [tokenId] : void 0,
61
+ query: { enabled: tokenId !== void 0 }
62
+ });
63
+ return {
64
+ positionEscrowAddress: positionEscrow,
65
+ stabilizerEscrowAddress: stabilizerEscrow,
66
+ isLoading: posLoading || stabLoading
67
+ };
68
+ }
69
+ function formatUsdPrice(price) {
70
+ if (price === void 0) return "--";
71
+ const priceFloat = Number(price) / 1e18;
72
+ return new Intl.NumberFormat("en-US", {
73
+ style: "currency",
74
+ currency: "USD",
75
+ minimumFractionDigits: 2,
76
+ maximumFractionDigits: 2
77
+ }).format(priceFloat);
78
+ }
79
+ function useEthUsdPrice(config) {
80
+ const oracleUrl = config?.oracleUrl;
81
+ const refetchInterval = config?.refetchInterval ?? 1e4;
82
+ const enabled = config?.enabled ?? true;
83
+ const oracle = createOracleClient({ oracleUrl });
84
+ const { data, isLoading, error, refetch } = useQuery({
85
+ queryKey: ["upd-oracle-eth-usd", oracleUrl],
86
+ queryFn: () => oracle.getEthUsdAttestation(),
87
+ refetchInterval,
88
+ enabled,
89
+ staleTime: 5e3
90
+ });
91
+ return {
92
+ price: data?.price,
93
+ priceFormatted: formatUsdPrice(data?.price),
94
+ attestation: data,
95
+ isLoading,
96
+ error,
97
+ refetch: () => {
98
+ refetch();
99
+ }
100
+ };
101
+ }
102
+ function useMintQuote(ethAmount, config) {
103
+ const { price, isLoading } = useEthUsdPrice({
104
+ ...config,
105
+ enabled: ethAmount > 0n && (config?.enabled ?? true)
106
+ });
107
+ const updAmount = useMemo(() => {
108
+ if (price === void 0 || ethAmount === 0n) return void 0;
109
+ return quoteMintUPD(ethAmount, price);
110
+ }, [ethAmount, price]);
111
+ return {
112
+ updAmount,
113
+ ethUsdPrice: price,
114
+ isLoading
115
+ };
116
+ }
117
+ function useBurnQuote(updAmount, config) {
118
+ const { price, isLoading } = useEthUsdPrice({
119
+ ...config,
120
+ enabled: updAmount > 0n && (config?.enabled ?? true)
121
+ });
122
+ const stEthAmount = useMemo(() => {
123
+ if (price === void 0 || updAmount === 0n) return void 0;
124
+ return quoteBurnUPD(updAmount, price);
125
+ }, [updAmount, price]);
126
+ return {
127
+ stEthAmount,
128
+ ethUsdPrice: price,
129
+ isLoading
130
+ };
131
+ }
132
+ function useMintUPD(config) {
133
+ const { stabilizerNFTAddress } = config;
134
+ const {
135
+ writeContract,
136
+ data: txHash,
137
+ isPending,
138
+ error: writeError,
139
+ reset
140
+ } = useWriteContract();
141
+ const {
142
+ isLoading: isConfirming,
143
+ isSuccess: isConfirmed
144
+ } = useWaitForTransactionReceipt({
145
+ hash: txHash
146
+ });
147
+ function mint(params) {
148
+ writeContract({
149
+ address: stabilizerNFTAddress,
150
+ abi: STABILIZER_NFT_ABI,
151
+ functionName: "mintUPD",
152
+ args: [
153
+ params.to,
154
+ {
155
+ price: params.attestation.price,
156
+ decimals: params.attestation.decimals,
157
+ dataTimestamp: params.attestation.dataTimestamp,
158
+ assetPair: params.attestation.assetPair,
159
+ signature: params.attestation.signature
160
+ }
161
+ ],
162
+ value: params.ethAmount
163
+ });
164
+ }
165
+ return {
166
+ mint,
167
+ isPending,
168
+ txHash,
169
+ isConfirming,
170
+ isConfirmed,
171
+ error: writeError,
172
+ reset
173
+ };
174
+ }
175
+ function useBurnUPD(config) {
176
+ const { stabilizerNFTAddress } = config;
177
+ const {
178
+ writeContract,
179
+ data: txHash,
180
+ isPending,
181
+ error: writeError,
182
+ reset
183
+ } = useWriteContract();
184
+ const {
185
+ isLoading: isConfirming,
186
+ isSuccess: isConfirmed
187
+ } = useWaitForTransactionReceipt({
188
+ hash: txHash
189
+ });
190
+ function burn(params) {
191
+ writeContract({
192
+ address: stabilizerNFTAddress,
193
+ abi: STABILIZER_NFT_ABI,
194
+ functionName: "burnUPD",
195
+ args: [
196
+ params.updAmount,
197
+ {
198
+ price: params.attestation.price,
199
+ decimals: params.attestation.decimals,
200
+ dataTimestamp: params.attestation.dataTimestamp,
201
+ assetPair: params.attestation.assetPair,
202
+ signature: params.attestation.signature
203
+ }
204
+ ]
205
+ });
206
+ }
207
+ return {
208
+ burn,
209
+ isPending,
210
+ txHash,
211
+ isConfirming,
212
+ isConfirmed,
213
+ error: writeError,
214
+ reset
215
+ };
216
+ }
217
+ function useSystemHealth(config) {
218
+ const collateralConfig = {
219
+ reporterAddress: config.reporterAddress,
220
+ tokenAddress: config.tokenAddress
221
+ };
222
+ const priceConfig = {
223
+ oracleUrl: config.oracleUrl
224
+ };
225
+ const {
226
+ totalStEthCollateral,
227
+ totalUPDSupply,
228
+ isLoading: collateralLoading
229
+ } = useCollateral(collateralConfig);
230
+ const {
231
+ price: ethUsdPrice,
232
+ isLoading: priceLoading
233
+ } = useEthUsdPrice(priceConfig);
234
+ const health = useMemo(() => {
235
+ if (totalStEthCollateral === void 0 || totalUPDSupply === void 0 || ethUsdPrice === void 0) {
236
+ return void 0;
237
+ }
238
+ return computeSystemHealth(
239
+ { totalStEthCollateral, totalUPDSupply },
240
+ ethUsdPrice,
241
+ config.minRatioBps
242
+ );
243
+ }, [totalStEthCollateral, totalUPDSupply, ethUsdPrice, config.minRatioBps]);
244
+ return {
245
+ health,
246
+ isLoading: collateralLoading || priceLoading
247
+ };
248
+ }
249
+ function useSUPD(config) {
250
+ const { supdAddress, userAddress } = config;
251
+ const { data: balance, isLoading: balLoading } = useReadContract({
252
+ address: supdAddress,
253
+ abi: SUPD_ABI,
254
+ functionName: "balanceOf",
255
+ args: userAddress ? [userAddress] : void 0,
256
+ query: { enabled: !!userAddress }
257
+ });
258
+ const { data: totalSupply, isLoading: supplyLoading } = useReadContract({
259
+ address: supdAddress,
260
+ abi: SUPD_ABI,
261
+ functionName: "totalSupply"
262
+ });
263
+ const { data: shareValue, isLoading: svLoading } = useReadContract({
264
+ address: supdAddress,
265
+ abi: SUPD_ABI,
266
+ functionName: "currentShareValue"
267
+ });
268
+ const { data: annualYieldBps, isLoading: apyLoading } = useReadContract({
269
+ address: supdAddress,
270
+ abi: SUPD_ABI,
271
+ functionName: "annualYieldBps"
272
+ });
273
+ const { data: totalLiabilityUSD, isLoading: liabLoading } = useReadContract({
274
+ address: supdAddress,
275
+ abi: SUPD_ABI,
276
+ functionName: "totalLiabilityUSD"
277
+ });
278
+ return {
279
+ balance,
280
+ totalSupply,
281
+ shareValue,
282
+ annualYieldBps,
283
+ totalLiabilityUSD,
284
+ isLoading: balLoading || supplyLoading || svLoading || apyLoading || liabLoading
285
+ };
286
+ }
287
+ function useStakeUPD(config) {
288
+ const { supdAddress } = config;
289
+ const {
290
+ writeContract,
291
+ data: txHash,
292
+ isPending,
293
+ error: writeError,
294
+ reset
295
+ } = useWriteContract();
296
+ const {
297
+ isLoading: isConfirming,
298
+ isSuccess: isConfirmed
299
+ } = useWaitForTransactionReceipt({ hash: txHash });
300
+ function stake(params) {
301
+ writeContract({
302
+ address: supdAddress,
303
+ abi: SUPD_ABI,
304
+ functionName: "stakeUPD",
305
+ args: [
306
+ params.updAmount,
307
+ {
308
+ price: params.attestation.price,
309
+ decimals: params.attestation.decimals,
310
+ dataTimestamp: params.attestation.dataTimestamp,
311
+ assetPair: params.attestation.assetPair,
312
+ signature: params.attestation.signature
313
+ }
314
+ ]
315
+ });
316
+ }
317
+ return {
318
+ stake,
319
+ isPending,
320
+ txHash,
321
+ isConfirming,
322
+ isConfirmed,
323
+ error: writeError,
324
+ reset
325
+ };
326
+ }
327
+ function useUnstakeUPD(config) {
328
+ const { supdAddress } = config;
329
+ const {
330
+ writeContract,
331
+ data: txHash,
332
+ isPending,
333
+ error: writeError,
334
+ reset
335
+ } = useWriteContract();
336
+ const {
337
+ isLoading: isConfirming,
338
+ isSuccess: isConfirmed
339
+ } = useWaitForTransactionReceipt({ hash: txHash });
340
+ function unstake(params) {
341
+ writeContract({
342
+ address: supdAddress,
343
+ abi: SUPD_ABI,
344
+ functionName: "unstakeToUPD",
345
+ args: [
346
+ params.shares,
347
+ {
348
+ price: params.attestation.price,
349
+ decimals: params.attestation.decimals,
350
+ dataTimestamp: params.attestation.dataTimestamp,
351
+ assetPair: params.attestation.assetPair,
352
+ signature: params.attestation.signature
353
+ }
354
+ ]
355
+ });
356
+ }
357
+ return {
358
+ unstake,
359
+ isPending,
360
+ txHash,
361
+ isConfirming,
362
+ isConfirmed,
363
+ error: writeError,
364
+ reset
365
+ };
366
+ }
367
+
368
+ export { useBurnQuote, useBurnUPD, useCollateral, useEthUsdPrice, useMintQuote, useMintUPD, useSUPD, useStabilizer, useStakeUPD, useSystemHealth, useUPD, useUnstakeUPD };
369
+ //# sourceMappingURL=index.js.map
370
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/use-upd.ts","../../src/react/use-collateral.ts","../../src/react/use-stabilizer.ts","../../src/react/use-eth-usd-price.ts","../../src/react/use-mint-quote.ts","../../src/react/use-burn-quote.ts","../../src/react/use-mint-upd.ts","../../src/react/use-burn-upd.ts","../../src/react/use-system-health.ts","../../src/react/use-supd.ts","../../src/react/use-stake-upd.ts","../../src/react/use-unstake-upd.ts"],"names":["useReadContract","useMemo","useWriteContract","useWaitForTransactionReceipt"],"mappings":";;;;;;;;AAeO,SAAS,OAAO,MAAA,EAAoC;AACzD,EAAA,MAAM,EAAE,YAAA,EAAc,WAAA,EAAY,GAAI,MAAA;AAEtC,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,SAAA,EAAW,cAAA,KAAmB,eAAA,CAAgB;AAAA,IACnE,OAAA,EAAS,YAAA;AAAA,IACT,GAAA,EAAK,aAAA;AAAA,IACL,YAAA,EAAc,WAAA;AAAA,IACd,IAAA,EAAM,WAAA,GAAc,CAAC,WAAW,CAAA,GAAI,MAAA;AAAA,IACpC,KAAA,EAAO,EAAE,OAAA,EAAS,CAAC,CAAC,WAAA;AAAY,GACjC,CAAA;AAED,EAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,SAAA,EAAW,aAAA,KAAkB,eAAA,CAAgB;AAAA,IACtE,OAAA,EAAS,YAAA;AAAA,IACT,GAAA,EAAK,aAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAW,cAAA,IAAkB;AAAA,GAC/B;AACF;ACrBO,SAAS,cAAc,MAAA,EAAkD;AAC9E,EAAA,MAAM,EAAE,eAAA,EAAiB,YAAA,EAAa,GAAI,MAAA;AAE1C,EAAA,MAAM,EAAE,IAAA,EAAM,oBAAA,EAAsB,SAAA,EAAW,iBAAA,KAC7CA,eAAAA,CAAgB;AAAA,IACd,OAAA,EAAS,eAAA;AAAA,IACT,GAAA,EAAK,kCAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AAEH,EAAA,MAAM,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAA,EAAW,aAAA,KAAkBA,eAAAA,CAAgB;AAAA,IACzE,OAAA,EAAS,YAAA;AAAA,IACT,GAAA,EAAK,aAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,OAAO;AAAA,IACL,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,WAAW,iBAAA,IAAqB;AAAA,GAClC;AACF;ACtBO,SAAS,cACd,MAAA,EACqB;AACrB,EAAA,MAAM,EAAE,oBAAA,EAAsB,OAAA,EAAQ,GAAI,MAAA;AAE1C,EAAA,MAAM,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAA,EAAW,UAAA,KAAeA,eAAAA,CAAgB;AAAA,IACtE,OAAA,EAAS,oBAAA;AAAA,IACT,GAAA,EAAK,kBAAA;AAAA,IACL,YAAA,EAAc,iBAAA;AAAA,IACd,IAAA,EAAM,OAAA,KAAY,MAAA,GAAY,CAAC,OAAO,CAAA,GAAI,MAAA;AAAA,IAC1C,KAAA,EAAO,EAAE,OAAA,EAAS,OAAA,KAAY,MAAA;AAAU,GACzC,CAAA;AAED,EAAA,MAAM,EAAE,IAAA,EAAM,gBAAA,EAAkB,SAAA,EAAW,WAAA,KAAgBA,eAAAA,CAAgB;AAAA,IACzE,OAAA,EAAS,oBAAA;AAAA,IACT,GAAA,EAAK,kBAAA;AAAA,IACL,YAAA,EAAc,mBAAA;AAAA,IACd,IAAA,EAAM,OAAA,KAAY,MAAA,GAAY,CAAC,OAAO,CAAA,GAAI,MAAA;AAAA,IAC1C,KAAA,EAAO,EAAE,OAAA,EAAS,OAAA,KAAY,MAAA;AAAU,GACzC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,qBAAA,EAAuB,cAAA;AAAA,IACvB,uBAAA,EAAyB,gBAAA;AAAA,IACzB,WAAW,UAAA,IAAc;AAAA,GAC3B;AACF;ACbA,SAAS,eAAe,KAAA,EAAmC;AACzD,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,IAAA;AAChC,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,KAAK,CAAA,GAAI,IAAA;AACnC,EAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,OAAA,EAAS;AAAA,IACpC,KAAA,EAAO,UAAA;AAAA,IACP,QAAA,EAAU,KAAA;AAAA,IACV,qBAAA,EAAuB,CAAA;AAAA,IACvB,qBAAA,EAAuB;AAAA,GACxB,CAAA,CAAE,MAAA,CAAO,UAAU,CAAA;AACtB;AAEO,SAAS,eAAe,MAAA,EAAqD;AAClF,EAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,IAAmB,GAAA;AACnD,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,IAAA;AAEnC,EAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,EAAE,SAAA,EAAW,CAAA;AAE/C,EAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,OAAA,KAAY,QAAA,CAAS;AAAA,IACnD,QAAA,EAAU,CAAC,oBAAA,EAAsB,SAAS,CAAA;AAAA,IAC1C,OAAA,EAAS,MAAM,MAAA,CAAO,oBAAA,EAAqB;AAAA,IAC3C,eAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACZ,CAAA;AAED,EAAA,OAAO;AAAA,IACL,OAAO,IAAA,EAAM,KAAA;AAAA,IACb,cAAA,EAAgB,cAAA,CAAe,IAAA,EAAM,KAAK,CAAA;AAAA,IAC1C,WAAA,EAAa,IAAA;AAAA,IACb,SAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAS,MAAM;AAAE,MAAA,OAAA,EAAQ;AAAA,IAAE;AAAA,GAC7B;AACF;ACnCO,SAAS,YAAA,CACd,WACA,MAAA,EACoB;AACpB,EAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAU,GAAI,cAAA,CAAe;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,OAAA,EAAS,SAAA,GAAY,EAAA,KAAO,MAAA,EAAQ,OAAA,IAAW,IAAA;AAAA,GAChD,CAAA;AAED,EAAA,MAAM,SAAA,GAAY,QAAQ,MAAM;AAC9B,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,SAAA,KAAc,EAAA,EAAI,OAAO,MAAA;AACpD,IAAA,OAAO,YAAA,CAAa,WAAW,KAAK,CAAA;AAAA,EACtC,CAAA,EAAG,CAAC,SAAA,EAAW,KAAK,CAAC,CAAA;AAErB,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,WAAA,EAAa,KAAA;AAAA,IACb;AAAA,GACF;AACF;ACnBO,SAAS,YAAA,CACd,WACA,MAAA,EACoB;AACpB,EAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAU,GAAI,cAAA,CAAe;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,OAAA,EAAS,SAAA,GAAY,EAAA,KAAO,MAAA,EAAQ,OAAA,IAAW,IAAA;AAAA,GAChD,CAAA;AAED,EAAA,MAAM,WAAA,GAAcC,QAAQ,MAAM;AAChC,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,SAAA,KAAc,EAAA,EAAI,OAAO,MAAA;AACpD,IAAA,OAAO,YAAA,CAAa,WAAW,KAAK,CAAA;AAAA,EACtC,CAAA,EAAG,CAAC,SAAA,EAAW,KAAK,CAAC,CAAA;AAErB,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,WAAA,EAAa,KAAA;AAAA,IACb;AAAA,GACF;AACF;ACEO,SAAS,WAAW,MAAA,EAA4C;AACrE,EAAA,MAAM,EAAE,sBAAqB,GAAI,MAAA;AAEjC,EAAA,MAAM;AAAA,IACJ,aAAA;AAAA,IACA,IAAA,EAAM,MAAA;AAAA,IACN,SAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,MACE,gBAAA,EAAiB;AAErB,EAAA,MAAM;AAAA,IACJ,SAAA,EAAW,YAAA;AAAA,IACX,SAAA,EAAW;AAAA,MACT,4BAAA,CAA6B;AAAA,IAC/B,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,SAAS,KAAK,MAAA,EAIX;AACD,IAAA,aAAA,CAAc;AAAA,MACZ,OAAA,EAAS,oBAAA;AAAA,MACT,GAAA,EAAK,kBAAA;AAAA,MACL,YAAA,EAAc,SAAA;AAAA,MACd,IAAA,EAAM;AAAA,QACJ,MAAA,CAAO,EAAA;AAAA,QACP;AAAA,UACE,KAAA,EAAO,OAAO,WAAA,CAAY,KAAA;AAAA,UAC1B,QAAA,EAAU,OAAO,WAAA,CAAY,QAAA;AAAA,UAC7B,aAAA,EAAe,OAAO,WAAA,CAAY,aAAA;AAAA,UAClC,SAAA,EAAW,OAAO,WAAA,CAAY,SAAA;AAAA,UAC9B,SAAA,EAAW,OAAO,WAAA,CAAY;AAAA;AAChC,OACF;AAAA,MACA,OAAO,MAAA,CAAO;AAAA,KACf,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,GACF;AACF;ACpDO,SAAS,WAAW,MAAA,EAA4C;AACrE,EAAA,MAAM,EAAE,sBAAqB,GAAI,MAAA;AAEjC,EAAA,MAAM;AAAA,IACJ,aAAA;AAAA,IACA,IAAA,EAAM,MAAA;AAAA,IACN,SAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,MACEC,gBAAAA,EAAiB;AAErB,EAAA,MAAM;AAAA,IACJ,SAAA,EAAW,YAAA;AAAA,IACX,SAAA,EAAW;AAAA,MACTC,4BAAAA,CAA6B;AAAA,IAC/B,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,SAAS,KAAK,MAAA,EAGX;AACD,IAAA,aAAA,CAAc;AAAA,MACZ,OAAA,EAAS,oBAAA;AAAA,MACT,GAAA,EAAK,kBAAA;AAAA,MACL,YAAA,EAAc,SAAA;AAAA,MACd,IAAA,EAAM;AAAA,QACJ,MAAA,CAAO,SAAA;AAAA,QACP;AAAA,UACE,KAAA,EAAO,OAAO,WAAA,CAAY,KAAA;AAAA,UAC1B,QAAA,EAAU,OAAO,WAAA,CAAY,QAAA;AAAA,UAC7B,aAAA,EAAe,OAAO,WAAA,CAAY,aAAA;AAAA,UAClC,SAAA,EAAW,OAAO,WAAA,CAAY,SAAA;AAAA,UAC9B,SAAA,EAAW,OAAO,WAAA,CAAY;AAAA;AAChC;AACF,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,GACF;AACF;ACvDO,SAAS,gBAAgB,MAAA,EAAsD;AACpF,EAAA,MAAM,gBAAA,GAAwC;AAAA,IAC5C,iBAAiB,MAAA,CAAO,eAAA;AAAA,IACxB,cAAc,MAAA,CAAO;AAAA,GACvB;AAEA,EAAA,MAAM,WAAA,GAAoC;AAAA,IACxC,WAAW,MAAA,CAAO;AAAA,GACpB;AAEA,EAAA,MAAM;AAAA,IACJ,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACb,GAAI,cAAc,gBAAgB,CAAA;AAElC,EAAA,MAAM;AAAA,IACJ,KAAA,EAAO,WAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb,GAAI,eAAe,WAAW,CAAA;AAE9B,EAAA,MAAM,MAAA,GAASF,QAAQ,MAAM;AAC3B,IAAA,IACE,oBAAA,KAAyB,MAAA,IACzB,cAAA,KAAmB,MAAA,IACnB,gBAAgB,MAAA,EAChB;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,OAAO,mBAAA;AAAA,MACL,EAAE,sBAAsB,cAAA,EAAe;AAAA,MACvC,WAAA;AAAA,MACA,MAAA,CAAO;AAAA,KACT;AAAA,EACF,GAAG,CAAC,oBAAA,EAAsB,gBAAgB,WAAA,EAAa,MAAA,CAAO,WAAW,CAAC,CAAA;AAE1E,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,WAAW,iBAAA,IAAqB;AAAA,GAClC;AACF;AC3CO,SAAS,QAAQ,MAAA,EAAsC;AAC5D,EAAA,MAAM,EAAE,WAAA,EAAa,WAAA,EAAY,GAAI,MAAA;AAErC,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,SAAA,EAAW,UAAA,KAAeD,eAAAA,CAAgB;AAAA,IAC/D,OAAA,EAAS,WAAA;AAAA,IACT,GAAA,EAAK,QAAA;AAAA,IACL,YAAA,EAAc,WAAA;AAAA,IACd,IAAA,EAAM,WAAA,GAAc,CAAC,WAAW,CAAA,GAAI,MAAA;AAAA,IACpC,KAAA,EAAO,EAAE,OAAA,EAAS,CAAC,CAAC,WAAA;AAAY,GACjC,CAAA;AAED,EAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,SAAA,EAAW,aAAA,KAAkBA,eAAAA,CAAgB;AAAA,IACtE,OAAA,EAAS,WAAA;AAAA,IACT,GAAA,EAAK,QAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAY,SAAA,EAAW,SAAA,KAAcA,eAAAA,CAAgB;AAAA,IACjE,OAAA,EAAS,WAAA;AAAA,IACT,GAAA,EAAK,QAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,MAAM,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAA,EAAW,UAAA,KAAeA,eAAAA,CAAgB;AAAA,IACtE,OAAA,EAAS,WAAA;AAAA,IACT,GAAA,EAAK,QAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,MAAM,EAAE,IAAA,EAAM,iBAAA,EAAmB,SAAA,EAAW,WAAA,KAAgBA,eAAAA,CAAgB;AAAA,IAC1E,OAAA,EAAS,WAAA;AAAA,IACT,GAAA,EAAK,QAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,cAAA;AAAA,IACA,iBAAA;AAAA,IACA,SAAA,EAAW,UAAA,IAAc,aAAA,IAAiB,SAAA,IAAa,UAAA,IAAc;AAAA,GACvE;AACF;ACrCO,SAAS,YAAY,MAAA,EAA8C;AACxE,EAAA,MAAM,EAAE,aAAY,GAAI,MAAA;AAExB,EAAA,MAAM;AAAA,IACJ,aAAA;AAAA,IACA,IAAA,EAAM,MAAA;AAAA,IACN,SAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,MACEE,gBAAAA,EAAiB;AAErB,EAAA,MAAM;AAAA,IACJ,SAAA,EAAW,YAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb,GAAIC,4BAAAA,CAA6B,EAAE,IAAA,EAAM,QAAQ,CAAA;AAEjD,EAAA,SAAS,MAAM,MAAA,EAGZ;AACD,IAAA,aAAA,CAAc;AAAA,MACZ,OAAA,EAAS,WAAA;AAAA,MACT,GAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAc,UAAA;AAAA,MACd,IAAA,EAAM;AAAA,QACJ,MAAA,CAAO,SAAA;AAAA,QACP;AAAA,UACE,KAAA,EAAO,OAAO,WAAA,CAAY,KAAA;AAAA,UAC1B,QAAA,EAAU,OAAO,WAAA,CAAY,QAAA;AAAA,UAC7B,aAAA,EAAe,OAAO,WAAA,CAAY,aAAA;AAAA,UAClC,SAAA,EAAW,OAAO,WAAA,CAAY,SAAA;AAAA,UAC9B,SAAA,EAAW,OAAO,WAAA,CAAY;AAAA;AAChC;AACF,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,GACF;AACF;AC3CO,SAAS,cAAc,MAAA,EAAkD;AAC9E,EAAA,MAAM,EAAE,aAAY,GAAI,MAAA;AAExB,EAAA,MAAM;AAAA,IACJ,aAAA;AAAA,IACA,IAAA,EAAM,MAAA;AAAA,IACN,SAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,MACED,gBAAAA,EAAiB;AAErB,EAAA,MAAM;AAAA,IACJ,SAAA,EAAW,YAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb,GAAIC,4BAAAA,CAA6B,EAAE,IAAA,EAAM,QAAQ,CAAA;AAEjD,EAAA,SAAS,QAAQ,MAAA,EAGd;AACD,IAAA,aAAA,CAAc;AAAA,MACZ,OAAA,EAAS,WAAA;AAAA,MACT,GAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAc,cAAA;AAAA,MACd,IAAA,EAAM;AAAA,QACJ,MAAA,CAAO,MAAA;AAAA,QACP;AAAA,UACE,KAAA,EAAO,OAAO,WAAA,CAAY,KAAA;AAAA,UAC1B,QAAA,EAAU,OAAO,WAAA,CAAY,QAAA;AAAA,UAC7B,aAAA,EAAe,OAAO,WAAA,CAAY,aAAA;AAAA,UAClC,SAAA,EAAW,OAAO,WAAA,CAAY,SAAA;AAAA,UAC9B,SAAA,EAAW,OAAO,WAAA,CAAY;AAAA;AAChC;AACF,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA,EAAO,UAAA;AAAA,IACP;AAAA,GACF;AACF","file":"index.js","sourcesContent":["import { useReadContract } from 'wagmi'\nimport type { Address } from 'viem'\nimport { UPD_TOKEN_ABI } from '../contracts/index.js'\n\nexport interface UseUPDConfig {\n tokenAddress: Address\n userAddress?: Address\n}\n\nexport interface UseUPDReturn {\n balance: bigint | undefined\n totalSupply: bigint | undefined\n isLoading: boolean\n}\n\nexport function useUPD(config: UseUPDConfig): UseUPDReturn {\n const { tokenAddress, userAddress } = config\n\n const { data: balance, isLoading: balanceLoading } = useReadContract({\n address: tokenAddress,\n abi: UPD_TOKEN_ABI,\n functionName: 'balanceOf',\n args: userAddress ? [userAddress] : undefined,\n query: { enabled: !!userAddress },\n })\n\n const { data: totalSupply, isLoading: supplyLoading } = useReadContract({\n address: tokenAddress,\n abi: UPD_TOKEN_ABI,\n functionName: 'totalSupply',\n })\n\n return {\n balance: balance as bigint | undefined,\n totalSupply: totalSupply as bigint | undefined,\n isLoading: balanceLoading || supplyLoading,\n }\n}\n","import { useReadContract } from 'wagmi'\nimport type { Address } from 'viem'\nimport { OVERCOLLATERALIZATION_REPORTER_ABI } from '../contracts/index.js'\nimport { UPD_TOKEN_ABI } from '../contracts/index.js'\n\nexport interface UseCollateralConfig {\n reporterAddress: Address\n tokenAddress: Address\n}\n\nexport interface UseCollateralReturn {\n totalStEthCollateral: bigint | undefined\n totalUPDSupply: bigint | undefined\n isLoading: boolean\n}\n\nexport function useCollateral(config: UseCollateralConfig): UseCollateralReturn {\n const { reporterAddress, tokenAddress } = config\n\n const { data: totalStEthCollateral, isLoading: collateralLoading } =\n useReadContract({\n address: reporterAddress,\n abi: OVERCOLLATERALIZATION_REPORTER_ABI,\n functionName: 'totalStEthCollateral',\n })\n\n const { data: totalUPDSupply, isLoading: supplyLoading } = useReadContract({\n address: tokenAddress,\n abi: UPD_TOKEN_ABI,\n functionName: 'totalSupply',\n })\n\n return {\n totalStEthCollateral: totalStEthCollateral as bigint | undefined,\n totalUPDSupply: totalUPDSupply as bigint | undefined,\n isLoading: collateralLoading || supplyLoading,\n }\n}\n","import { useReadContract } from 'wagmi'\nimport type { Address } from 'viem'\nimport { STABILIZER_NFT_ABI } from '../contracts/index.js'\n\nexport interface UseStabilizerConfig {\n stabilizerNFTAddress: Address\n tokenId?: bigint\n}\n\nexport interface UseStabilizerReturn {\n positionEscrowAddress: Address | undefined\n stabilizerEscrowAddress: Address | undefined\n isLoading: boolean\n}\n\nexport function useStabilizer(\n config: UseStabilizerConfig,\n): UseStabilizerReturn {\n const { stabilizerNFTAddress, tokenId } = config\n\n const { data: positionEscrow, isLoading: posLoading } = useReadContract({\n address: stabilizerNFTAddress,\n abi: STABILIZER_NFT_ABI,\n functionName: 'positionEscrows',\n args: tokenId !== undefined ? [tokenId] : undefined,\n query: { enabled: tokenId !== undefined },\n })\n\n const { data: stabilizerEscrow, isLoading: stabLoading } = useReadContract({\n address: stabilizerNFTAddress,\n abi: STABILIZER_NFT_ABI,\n functionName: 'stabilizerEscrows',\n args: tokenId !== undefined ? [tokenId] : undefined,\n query: { enabled: tokenId !== undefined },\n })\n\n return {\n positionEscrowAddress: positionEscrow as Address | undefined,\n stabilizerEscrowAddress: stabilizerEscrow as Address | undefined,\n isLoading: posLoading || stabLoading,\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { createOracleClient } from '../oracle/client.js'\nimport type { PriceAttestationQuery } from '../core/types.js'\n\nexport interface UseEthUsdPriceConfig {\n /** Oracle service URL. Defaults to oracle.upd.io. */\n oracleUrl?: string\n /** Refetch interval in milliseconds. Defaults to 10000 (10s). */\n refetchInterval?: number\n /** Whether to enable the query. Defaults to true. */\n enabled?: boolean\n}\n\nexport interface UseEthUsdPriceReturn {\n /** Raw price in 18 decimals (e.g. 2000e18 = $2000). */\n price: bigint | undefined\n /** Human-readable formatted price string (e.g. \"$2,000.00\"). */\n priceFormatted: string\n /** Full signed attestation, ready to pass to mint/burn. */\n attestation: PriceAttestationQuery | undefined\n /** Whether the initial fetch is loading. */\n isLoading: boolean\n /** Error from the most recent fetch, if any. */\n error: Error | null\n /** Manually trigger a refetch. */\n refetch: () => void\n}\n\nfunction formatUsdPrice(price: bigint | undefined): string {\n if (price === undefined) return '--'\n const priceFloat = Number(price) / 1e18\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(priceFloat)\n}\n\nexport function useEthUsdPrice(config?: UseEthUsdPriceConfig): UseEthUsdPriceReturn {\n const oracleUrl = config?.oracleUrl\n const refetchInterval = config?.refetchInterval ?? 10_000\n const enabled = config?.enabled ?? true\n\n const oracle = createOracleClient({ oracleUrl })\n\n const { data, isLoading, error, refetch } = useQuery({\n queryKey: ['upd-oracle-eth-usd', oracleUrl],\n queryFn: () => oracle.getEthUsdAttestation(),\n refetchInterval,\n enabled,\n staleTime: 5_000,\n })\n\n return {\n price: data?.price,\n priceFormatted: formatUsdPrice(data?.price),\n attestation: data,\n isLoading,\n error: error as Error | null,\n refetch: () => { refetch() },\n }\n}\n","import { useMemo } from 'react'\nimport { useEthUsdPrice, type UseEthUsdPriceConfig } from './use-eth-usd-price.js'\nimport { quoteMintUPD } from '../core/quote.js'\n\nexport interface UseMintQuoteConfig extends UseEthUsdPriceConfig {}\n\nexport interface UseMintQuoteReturn {\n /** Expected UPD amount for the given ETH input (18 decimals). */\n updAmount: bigint | undefined\n /** Current ETH/USD price used for the quote (18 decimals). */\n ethUsdPrice: bigint | undefined\n /** Whether the price is still loading. */\n isLoading: boolean\n}\n\n/**\n * Real-time mint quote hook — composes oracle price + pure math.\n *\n * @param ethAmount - ETH amount to quote (in wei). Pass 0n to disable.\n * @param config - Optional oracle configuration.\n *\n * @example\n * ```tsx\n * const { updAmount, isLoading } = useMintQuote(parseEther('1'))\n * // updAmount ≈ 2000e18 (at $2000/ETH)\n * ```\n */\nexport function useMintQuote(\n ethAmount: bigint,\n config?: UseMintQuoteConfig,\n): UseMintQuoteReturn {\n const { price, isLoading } = useEthUsdPrice({\n ...config,\n enabled: ethAmount > 0n && (config?.enabled ?? true),\n })\n\n const updAmount = useMemo(() => {\n if (price === undefined || ethAmount === 0n) return undefined\n return quoteMintUPD(ethAmount, price)\n }, [ethAmount, price])\n\n return {\n updAmount,\n ethUsdPrice: price,\n isLoading,\n }\n}\n","import { useMemo } from 'react'\nimport { useEthUsdPrice, type UseEthUsdPriceConfig } from './use-eth-usd-price.js'\nimport { quoteBurnUPD } from '../core/quote.js'\n\nexport interface UseBurnQuoteConfig extends UseEthUsdPriceConfig {}\n\nexport interface UseBurnQuoteReturn {\n /** Expected stETH amount for the given UPD input (in wei). */\n stEthAmount: bigint | undefined\n /** Current ETH/USD price used for the quote (18 decimals). */\n ethUsdPrice: bigint | undefined\n /** Whether the price is still loading. */\n isLoading: boolean\n}\n\n/**\n * Real-time burn quote hook — composes oracle price + pure math.\n *\n * @param updAmount - UPD amount to quote (18 decimals). Pass 0n to disable.\n * @param config - Optional oracle configuration.\n *\n * @example\n * ```tsx\n * const { stEthAmount, isLoading } = useBurnQuote(parseUnits('2000', 18))\n * // stEthAmount ≈ 1e18 (at $2000/ETH)\n * ```\n */\nexport function useBurnQuote(\n updAmount: bigint,\n config?: UseBurnQuoteConfig,\n): UseBurnQuoteReturn {\n const { price, isLoading } = useEthUsdPrice({\n ...config,\n enabled: updAmount > 0n && (config?.enabled ?? true),\n })\n\n const stEthAmount = useMemo(() => {\n if (price === undefined || updAmount === 0n) return undefined\n return quoteBurnUPD(updAmount, price)\n }, [updAmount, price])\n\n return {\n stEthAmount,\n ethUsdPrice: price,\n isLoading,\n }\n}\n","import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'\nimport type { Address, Hash } from 'viem'\nimport type { PriceAttestationQuery } from '../core/types.js'\nimport { STABILIZER_NFT_ABI } from '../contracts/index.js'\n\nexport interface UseMintUPDConfig {\n /** Address of the StabilizerNFT contract. */\n stabilizerNFTAddress: Address\n}\n\nexport interface UseMintUPDReturn {\n /** Execute the mint transaction. */\n mint: (params: {\n to: Address\n ethAmount: bigint\n attestation: PriceAttestationQuery\n }) => void\n /** Whether the transaction is being sent. */\n isPending: boolean\n /** Transaction hash once submitted. */\n txHash: Hash | undefined\n /** Whether we're waiting for confirmation. */\n isConfirming: boolean\n /** Whether the transaction is confirmed. */\n isConfirmed: boolean\n /** Error from the transaction, if any. */\n error: Error | null\n /** Reset the mutation state. */\n reset: () => void\n}\n\n/**\n * Write hook for minting UPD by depositing ETH.\n *\n * @example\n * ```tsx\n * const { mint, isPending, isConfirmed, error } = useMintUPD({\n * stabilizerNFTAddress: deployment.contracts.StabilizerNFT,\n * })\n *\n * // Use with useEthUsdPrice to get attestation\n * const { attestation } = useEthUsdPrice()\n *\n * <button onClick={() => mint({ to: userAddress, ethAmount: parseEther('1'), attestation })}>\n * Mint UPD\n * </button>\n * ```\n */\nexport function useMintUPD(config: UseMintUPDConfig): UseMintUPDReturn {\n const { stabilizerNFTAddress } = config\n\n const {\n writeContract,\n data: txHash,\n isPending,\n error: writeError,\n reset,\n } = useWriteContract()\n\n const {\n isLoading: isConfirming,\n isSuccess: isConfirmed,\n } = useWaitForTransactionReceipt({\n hash: txHash,\n })\n\n function mint(params: {\n to: Address\n ethAmount: bigint\n attestation: PriceAttestationQuery\n }) {\n writeContract({\n address: stabilizerNFTAddress,\n abi: STABILIZER_NFT_ABI,\n functionName: 'mintUPD',\n args: [\n params.to,\n {\n price: params.attestation.price,\n decimals: params.attestation.decimals,\n dataTimestamp: params.attestation.dataTimestamp,\n assetPair: params.attestation.assetPair,\n signature: params.attestation.signature,\n },\n ],\n value: params.ethAmount,\n })\n }\n\n return {\n mint,\n isPending,\n txHash,\n isConfirming,\n isConfirmed,\n error: writeError as Error | null,\n reset,\n }\n}\n","import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'\nimport type { Address, Hash } from 'viem'\nimport type { PriceAttestationQuery } from '../core/types.js'\nimport { STABILIZER_NFT_ABI } from '../contracts/index.js'\n\nexport interface UseBurnUPDConfig {\n /** Address of the StabilizerNFT contract. */\n stabilizerNFTAddress: Address\n}\n\nexport interface UseBurnUPDReturn {\n /** Execute the burn transaction. */\n burn: (params: {\n updAmount: bigint\n attestation: PriceAttestationQuery\n }) => void\n /** Whether the transaction is being sent. */\n isPending: boolean\n /** Transaction hash once submitted. */\n txHash: Hash | undefined\n /** Whether we're waiting for confirmation. */\n isConfirming: boolean\n /** Whether the transaction is confirmed. */\n isConfirmed: boolean\n /** Error from the transaction, if any. */\n error: Error | null\n /** Reset the mutation state. */\n reset: () => void\n}\n\n/**\n * Write hook for burning UPD to receive stETH.\n *\n * @example\n * ```tsx\n * const { burn, isPending, isConfirmed } = useBurnUPD({\n * stabilizerNFTAddress: deployment.contracts.StabilizerNFT,\n * })\n *\n * const { attestation } = useEthUsdPrice()\n *\n * <button onClick={() => burn({ updAmount: parseUnits('1000', 18), attestation })}>\n * Burn 1000 UPD\n * </button>\n * ```\n */\nexport function useBurnUPD(config: UseBurnUPDConfig): UseBurnUPDReturn {\n const { stabilizerNFTAddress } = config\n\n const {\n writeContract,\n data: txHash,\n isPending,\n error: writeError,\n reset,\n } = useWriteContract()\n\n const {\n isLoading: isConfirming,\n isSuccess: isConfirmed,\n } = useWaitForTransactionReceipt({\n hash: txHash,\n })\n\n function burn(params: {\n updAmount: bigint\n attestation: PriceAttestationQuery\n }) {\n writeContract({\n address: stabilizerNFTAddress,\n abi: STABILIZER_NFT_ABI,\n functionName: 'burnUPD',\n args: [\n params.updAmount,\n {\n price: params.attestation.price,\n decimals: params.attestation.decimals,\n dataTimestamp: params.attestation.dataTimestamp,\n assetPair: params.attestation.assetPair,\n signature: params.attestation.signature,\n },\n ],\n })\n }\n\n return {\n burn,\n isPending,\n txHash,\n isConfirming,\n isConfirmed,\n error: writeError as Error | null,\n reset,\n }\n}\n","import { useMemo } from 'react'\nimport type { Address } from 'viem'\nimport { useCollateral, type UseCollateralConfig } from './use-collateral.js'\nimport { useEthUsdPrice, type UseEthUsdPriceConfig } from './use-eth-usd-price.js'\nimport { computeSystemHealth, type SystemHealth } from '../core/health.js'\n\nexport interface UseSystemHealthConfig {\n /** Address of the OvercollateralizationReporter contract. */\n reporterAddress: Address\n /** Address of the UPD token. */\n tokenAddress: Address\n /** Oracle service URL. */\n oracleUrl?: string\n /** Minimum collateral ratio in basis points (default: 12500 = 125%). */\n minRatioBps?: bigint\n}\n\nexport interface UseSystemHealthReturn {\n /** Computed system health metrics, or undefined if still loading. */\n health: SystemHealth | undefined\n /** Whether any underlying data is still loading. */\n isLoading: boolean\n}\n\n/**\n * System health hook — composes useCollateral + useEthUsdPrice + computeSystemHealth.\n *\n * @example\n * ```tsx\n * const { health, isLoading } = useSystemHealth({\n * reporterAddress: deployment.contracts.OvercollateralizationReporter,\n * tokenAddress: deployment.contracts.UPDToken,\n * })\n *\n * if (health && !health.isHealthy) {\n * return <Alert>System undercollateralized: {health.systemCollateralRatioBps} bps</Alert>\n * }\n * ```\n */\nexport function useSystemHealth(config: UseSystemHealthConfig): UseSystemHealthReturn {\n const collateralConfig: UseCollateralConfig = {\n reporterAddress: config.reporterAddress,\n tokenAddress: config.tokenAddress,\n }\n\n const priceConfig: UseEthUsdPriceConfig = {\n oracleUrl: config.oracleUrl,\n }\n\n const {\n totalStEthCollateral,\n totalUPDSupply,\n isLoading: collateralLoading,\n } = useCollateral(collateralConfig)\n\n const {\n price: ethUsdPrice,\n isLoading: priceLoading,\n } = useEthUsdPrice(priceConfig)\n\n const health = useMemo(() => {\n if (\n totalStEthCollateral === undefined ||\n totalUPDSupply === undefined ||\n ethUsdPrice === undefined\n ) {\n return undefined\n }\n\n return computeSystemHealth(\n { totalStEthCollateral, totalUPDSupply },\n ethUsdPrice,\n config.minRatioBps,\n )\n }, [totalStEthCollateral, totalUPDSupply, ethUsdPrice, config.minRatioBps])\n\n return {\n health,\n isLoading: collateralLoading || priceLoading,\n }\n}\n","import { useReadContract } from 'wagmi'\nimport type { Address } from 'viem'\nimport { SUPD_ABI } from '../contracts/index.js'\n\nexport interface UseSUPDConfig {\n /** Address of the sUPD contract. */\n supdAddress: Address\n /** User address to read balance for (optional). */\n userAddress?: Address\n}\n\nexport interface UseSUPDReturn {\n /** User's sUPD balance (18 decimals). */\n balance: bigint | undefined\n /** Total sUPD shares outstanding. */\n totalSupply: bigint | undefined\n /** Current share value with accrued yield (18 decimals). */\n shareValue: bigint | undefined\n /** Annual yield in basis points (e.g. 800 = 8%). */\n annualYieldBps: bigint | undefined\n /** Total USD liability of all outstanding sUPD. */\n totalLiabilityUSD: bigint | undefined\n /** Whether any read is still loading. */\n isLoading: boolean\n}\n\n/**\n * Read hook for sUPD — share value, APY, balances, and total liability.\n *\n * @example\n * ```tsx\n * const { balance, shareValue, annualYieldBps, isLoading } = useSUPD({\n * supdAddress: deployment.contracts.sUPD,\n * userAddress: account.address,\n * })\n * ```\n */\nexport function useSUPD(config: UseSUPDConfig): UseSUPDReturn {\n const { supdAddress, userAddress } = config\n\n const { data: balance, isLoading: balLoading } = useReadContract({\n address: supdAddress,\n abi: SUPD_ABI,\n functionName: 'balanceOf',\n args: userAddress ? [userAddress] : undefined,\n query: { enabled: !!userAddress },\n })\n\n const { data: totalSupply, isLoading: supplyLoading } = useReadContract({\n address: supdAddress,\n abi: SUPD_ABI,\n functionName: 'totalSupply',\n })\n\n const { data: shareValue, isLoading: svLoading } = useReadContract({\n address: supdAddress,\n abi: SUPD_ABI,\n functionName: 'currentShareValue',\n })\n\n const { data: annualYieldBps, isLoading: apyLoading } = useReadContract({\n address: supdAddress,\n abi: SUPD_ABI,\n functionName: 'annualYieldBps',\n })\n\n const { data: totalLiabilityUSD, isLoading: liabLoading } = useReadContract({\n address: supdAddress,\n abi: SUPD_ABI,\n functionName: 'totalLiabilityUSD',\n })\n\n return {\n balance: balance as bigint | undefined,\n totalSupply: totalSupply as bigint | undefined,\n shareValue: shareValue as bigint | undefined,\n annualYieldBps: annualYieldBps as bigint | undefined,\n totalLiabilityUSD: totalLiabilityUSD as bigint | undefined,\n isLoading: balLoading || supplyLoading || svLoading || apyLoading || liabLoading,\n }\n}\n","import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'\nimport type { Address, Hash } from 'viem'\nimport type { PriceAttestationQuery } from '../core/types.js'\nimport { SUPD_ABI } from '../contracts/index.js'\n\nexport interface UseStakeUPDConfig {\n /** Address of the sUPD contract. */\n supdAddress: Address\n}\n\nexport interface UseStakeUPDReturn {\n /** Execute the stake transaction. User must approve UPD transfer to sUPD first. */\n stake: (params: {\n updAmount: bigint\n attestation: PriceAttestationQuery\n }) => void\n isPending: boolean\n txHash: Hash | undefined\n isConfirming: boolean\n isConfirmed: boolean\n error: Error | null\n reset: () => void\n}\n\n/**\n * Write hook for staking UPD → sUPD.\n *\n * Note: The user must first approve the sUPD contract to spend their UPD tokens\n * (via UPDToken.approve or EIP-3009 transferWithAuthorization).\n *\n * @example\n * ```tsx\n * const { stake, isPending } = useStakeUPD({\n * supdAddress: deployment.contracts.sUPD,\n * })\n *\n * const { attestation } = useEthUsdPrice()\n *\n * <button onClick={() => stake({ updAmount: parseUnits('1000', 18), attestation })}>\n * Stake 1000 UPD\n * </button>\n * ```\n */\nexport function useStakeUPD(config: UseStakeUPDConfig): UseStakeUPDReturn {\n const { supdAddress } = config\n\n const {\n writeContract,\n data: txHash,\n isPending,\n error: writeError,\n reset,\n } = useWriteContract()\n\n const {\n isLoading: isConfirming,\n isSuccess: isConfirmed,\n } = useWaitForTransactionReceipt({ hash: txHash })\n\n function stake(params: {\n updAmount: bigint\n attestation: PriceAttestationQuery\n }) {\n writeContract({\n address: supdAddress,\n abi: SUPD_ABI,\n functionName: 'stakeUPD',\n args: [\n params.updAmount,\n {\n price: params.attestation.price,\n decimals: params.attestation.decimals,\n dataTimestamp: params.attestation.dataTimestamp,\n assetPair: params.attestation.assetPair,\n signature: params.attestation.signature,\n },\n ],\n })\n }\n\n return {\n stake,\n isPending,\n txHash,\n isConfirming,\n isConfirmed,\n error: writeError as Error | null,\n reset,\n }\n}\n","import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'\nimport type { Address, Hash } from 'viem'\nimport type { PriceAttestationQuery } from '../core/types.js'\nimport { SUPD_ABI } from '../contracts/index.js'\n\nexport interface UseUnstakeUPDConfig {\n /** Address of the sUPD contract. */\n supdAddress: Address\n}\n\nexport interface UseUnstakeUPDReturn {\n /** Execute the unstake transaction (unstakeToUPD — full redemption). */\n unstake: (params: {\n shares: bigint\n attestation: PriceAttestationQuery\n }) => void\n isPending: boolean\n txHash: Hash | undefined\n isConfirming: boolean\n isConfirmed: boolean\n error: Error | null\n reset: () => void\n}\n\n/**\n * Write hook for unstaking sUPD → UPD.\n *\n * Calls `unstakeToUPD(shares, priceQuery)` which gathers stETH from sUPD's\n * stabilizer escrows and mints fresh UPD to the caller.\n *\n * For advanced unstake variants (pro-rata, queued, with-extra-UPD), use the\n * contract ABI directly.\n *\n * @example\n * ```tsx\n * const { unstake, isPending } = useUnstakeUPD({\n * supdAddress: deployment.contracts.sUPD,\n * })\n *\n * const { attestation } = useEthUsdPrice()\n *\n * <button onClick={() => unstake({ shares: myShares, attestation })}>\n * Unstake\n * </button>\n * ```\n */\nexport function useUnstakeUPD(config: UseUnstakeUPDConfig): UseUnstakeUPDReturn {\n const { supdAddress } = config\n\n const {\n writeContract,\n data: txHash,\n isPending,\n error: writeError,\n reset,\n } = useWriteContract()\n\n const {\n isLoading: isConfirming,\n isSuccess: isConfirmed,\n } = useWaitForTransactionReceipt({ hash: txHash })\n\n function unstake(params: {\n shares: bigint\n attestation: PriceAttestationQuery\n }) {\n writeContract({\n address: supdAddress,\n abi: SUPD_ABI,\n functionName: 'unstakeToUPD',\n args: [\n params.shares,\n {\n price: params.attestation.price,\n decimals: params.attestation.decimals,\n dataTimestamp: params.attestation.dataTimestamp,\n assetPair: params.attestation.assetPair,\n signature: params.attestation.signature,\n },\n ],\n })\n }\n\n return {\n unstake,\n isPending,\n txHash,\n isConfirming,\n isConfirmed,\n error: writeError as Error | null,\n reset,\n }\n}\n"]}
@@ -0,0 +1,70 @@
1
+ import { Address, Hash, PublicClient, WalletClient } from 'viem';
2
+
3
+ interface UPDClientConfig {
4
+ publicClient: PublicClient;
5
+ walletClient?: WalletClient;
6
+ chainId: number;
7
+ /** Oracle service URL for convenience methods (mintWithOracle, burnWithOracle). Defaults to oracle.upd.io. */
8
+ oracleUrl?: string;
9
+ }
10
+ interface StabilizerPosition {
11
+ tokenId: bigint;
12
+ positionEscrowAddress: Address;
13
+ stabilizerEscrowAddress: Address;
14
+ collateralizationRatio: bigint;
15
+ backedUPDAmount: bigint;
16
+ stETHBalance: bigint;
17
+ unallocatedStETH: bigint;
18
+ minCollateralRatio: bigint;
19
+ }
20
+ interface MintParams {
21
+ to: Address;
22
+ ethAmount: bigint;
23
+ priceAttestation: PriceAttestationQuery;
24
+ }
25
+ interface BurnParams {
26
+ updAmount: bigint;
27
+ priceAttestation: PriceAttestationQuery;
28
+ }
29
+ /**
30
+ * Matches the Solidity IPriceOracle.PriceAttestationQuery struct.
31
+ *
32
+ * Fields:
33
+ * - price: ETH/USD price (18 decimals, e.g. 2000e18 = $2000)
34
+ * - decimals: Always 18
35
+ * - dataTimestamp: Milliseconds since epoch
36
+ * - assetPair: keccak256("MORPHER:ETH_USD") for ETH/USD
37
+ * - signature: ECDSA signature from authorized oracle signer
38
+ */
39
+ interface PriceAttestationQuery {
40
+ price: bigint;
41
+ decimals: number;
42
+ dataTimestamp: bigint;
43
+ assetPair: `0x${string}`;
44
+ signature: `0x${string}`;
45
+ }
46
+ interface CollateralInfo {
47
+ totalStEthCollateral: bigint;
48
+ totalUPDSupply: bigint;
49
+ }
50
+ interface SUPDInfo {
51
+ /** Current share value (18 decimals, e.g. 1.05e18 = $1.05/share). */
52
+ shareValue: bigint;
53
+ /** Annual yield in basis points (e.g. 800 = 8% APY). */
54
+ annualYieldBps: bigint;
55
+ /** Total sUPD shares outstanding (18 decimals). */
56
+ totalSupply: bigint;
57
+ /** Total USD liability of all outstanding sUPD (18 decimals). */
58
+ totalLiabilityUSD: bigint;
59
+ }
60
+ interface StakeParams {
61
+ updAmount: bigint;
62
+ priceAttestation: PriceAttestationQuery;
63
+ }
64
+ interface UnstakeParams {
65
+ shares: bigint;
66
+ priceAttestation: PriceAttestationQuery;
67
+ }
68
+ type TransactionHash = Hash;
69
+
70
+ export type { BurnParams as B, CollateralInfo as C, MintParams as M, PriceAttestationQuery as P, SUPDInfo as S, TransactionHash as T, UPDClientConfig as U, StabilizerPosition as a, StakeParams as b, UnstakeParams as c };
@@ -0,0 +1,70 @@
1
+ import { Address, Hash, PublicClient, WalletClient } from 'viem';
2
+
3
+ interface UPDClientConfig {
4
+ publicClient: PublicClient;
5
+ walletClient?: WalletClient;
6
+ chainId: number;
7
+ /** Oracle service URL for convenience methods (mintWithOracle, burnWithOracle). Defaults to oracle.upd.io. */
8
+ oracleUrl?: string;
9
+ }
10
+ interface StabilizerPosition {
11
+ tokenId: bigint;
12
+ positionEscrowAddress: Address;
13
+ stabilizerEscrowAddress: Address;
14
+ collateralizationRatio: bigint;
15
+ backedUPDAmount: bigint;
16
+ stETHBalance: bigint;
17
+ unallocatedStETH: bigint;
18
+ minCollateralRatio: bigint;
19
+ }
20
+ interface MintParams {
21
+ to: Address;
22
+ ethAmount: bigint;
23
+ priceAttestation: PriceAttestationQuery;
24
+ }
25
+ interface BurnParams {
26
+ updAmount: bigint;
27
+ priceAttestation: PriceAttestationQuery;
28
+ }
29
+ /**
30
+ * Matches the Solidity IPriceOracle.PriceAttestationQuery struct.
31
+ *
32
+ * Fields:
33
+ * - price: ETH/USD price (18 decimals, e.g. 2000e18 = $2000)
34
+ * - decimals: Always 18
35
+ * - dataTimestamp: Milliseconds since epoch
36
+ * - assetPair: keccak256("MORPHER:ETH_USD") for ETH/USD
37
+ * - signature: ECDSA signature from authorized oracle signer
38
+ */
39
+ interface PriceAttestationQuery {
40
+ price: bigint;
41
+ decimals: number;
42
+ dataTimestamp: bigint;
43
+ assetPair: `0x${string}`;
44
+ signature: `0x${string}`;
45
+ }
46
+ interface CollateralInfo {
47
+ totalStEthCollateral: bigint;
48
+ totalUPDSupply: bigint;
49
+ }
50
+ interface SUPDInfo {
51
+ /** Current share value (18 decimals, e.g. 1.05e18 = $1.05/share). */
52
+ shareValue: bigint;
53
+ /** Annual yield in basis points (e.g. 800 = 8% APY). */
54
+ annualYieldBps: bigint;
55
+ /** Total sUPD shares outstanding (18 decimals). */
56
+ totalSupply: bigint;
57
+ /** Total USD liability of all outstanding sUPD (18 decimals). */
58
+ totalLiabilityUSD: bigint;
59
+ }
60
+ interface StakeParams {
61
+ updAmount: bigint;
62
+ priceAttestation: PriceAttestationQuery;
63
+ }
64
+ interface UnstakeParams {
65
+ shares: bigint;
66
+ priceAttestation: PriceAttestationQuery;
67
+ }
68
+ type TransactionHash = Hash;
69
+
70
+ export type { BurnParams as B, CollateralInfo as C, MintParams as M, PriceAttestationQuery as P, SUPDInfo as S, TransactionHash as T, UPDClientConfig as U, StabilizerPosition as a, StakeParams as b, UnstakeParams as c };
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@permissionless-technologies/upd-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Universal Private Dollar SDK — Non-rebasing stablecoin backed by stETH with stabilizer collateral management",
5
+ "workspaces": [
6
+ "packages/*"
7
+ ],
8
+ "type": "module",
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./core": {
19
+ "types": "./dist/core/index.d.ts",
20
+ "import": "./dist/core/index.js",
21
+ "require": "./dist/core/index.cjs"
22
+ },
23
+ "./contracts": {
24
+ "types": "./dist/contracts/index.d.ts",
25
+ "import": "./dist/contracts/index.js",
26
+ "require": "./dist/contracts/index.cjs"
27
+ },
28
+ "./react": {
29
+ "types": "./dist/react/index.d.ts",
30
+ "import": "./dist/react/index.js",
31
+ "require": "./dist/react/index.cjs"
32
+ },
33
+ "./oracle": {
34
+ "types": "./dist/oracle/index.d.ts",
35
+ "import": "./dist/oracle/index.js",
36
+ "require": "./dist/oracle/index.cjs"
37
+ }
38
+ },
39
+ "files": [
40
+ "dist"
41
+ ],
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "dev": "tsup --watch",
45
+ "test": "vitest",
46
+ "test:run": "vitest run",
47
+ "test:forge": "forge test",
48
+ "lint": "eslint src --ext .ts",
49
+ "typecheck": "tsc --noEmit",
50
+ "generate:abis": "forge build && node scripts/generate-abis.js",
51
+ "deploy:local": "node scripts/deploy.js 31337",
52
+ "deploy:sepolia": "node scripts/deploy.js 11155111",
53
+ "prepublishOnly": "npm run build"
54
+ },
55
+ "keywords": [
56
+ "ethereum",
57
+ "stablecoin",
58
+ "steth",
59
+ "collateral",
60
+ "stabilizer",
61
+ "defi",
62
+ "non-rebasing",
63
+ "viem"
64
+ ],
65
+ "author": "",
66
+ "license": "AGPL-3.0-or-later",
67
+ "peerDependencies": {
68
+ "react": "^18.0.0 || ^19.0.0",
69
+ "viem": "^2.0.0",
70
+ "wagmi": "^2.0.0"
71
+ },
72
+ "peerDependenciesMeta": {
73
+ "react": {
74
+ "optional": true
75
+ },
76
+ "wagmi": {
77
+ "optional": true
78
+ }
79
+ },
80
+ "devDependencies": {
81
+ "@types/node": "^20.0.0",
82
+ "@types/react": "^18.0.0 || ^19.0.0",
83
+ "react": "^19.0.0",
84
+ "tsup": "^8.0.0",
85
+ "typescript": "^5.0.0",
86
+ "viem": "^2.0.0",
87
+ "vitest": "^1.0.0",
88
+ "wagmi": "^2.0.0"
89
+ },
90
+ "engines": {
91
+ "node": ">=18.0.0"
92
+ }
93
+ }