@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,701 @@
1
+ import { computeSystemHealth } from './chunk-63FIKV36.js';
2
+ import { UPD_TOKEN_ABI, OVERCOLLATERALIZATION_REPORTER_ABI, STABILIZER_NFT_ABI, POSITION_ESCROW_ABI, STABILIZER_ESCROW_ABI, SUPD_ABI } from './chunk-4RBWWS2X.js';
3
+ import { createOracleClient } from './chunk-DJBU2OEB.js';
4
+ import { hexToBytes, bytesToHex } from 'viem';
5
+
6
+ // src/deployments/31337.json
7
+ var __default = {
8
+ contracts: {
9
+ UPDToken: "0x0000000000000000000000000000000000000000",
10
+ PriceOracle: "0x0000000000000000000000000000000000000000",
11
+ StabilizerNFT: "0x0000000000000000000000000000000000000000",
12
+ OvercollateralizationReporter: "0x0000000000000000000000000000000000000000",
13
+ InsuranceEscrow: "0x0000000000000000000000000000000000000000",
14
+ BridgeEscrow: "0x0000000000000000000000000000000000000000",
15
+ sUPD: "0x0000000000000000000000000000000000000000"
16
+ },
17
+ implementations: {
18
+ PriceOracle: "0x0000000000000000000000000000000000000000",
19
+ StabilizerNFT: "0x0000000000000000000000000000000000000000",
20
+ OvercollateralizationReporter: "0x0000000000000000000000000000000000000000"
21
+ },
22
+ libraries: {
23
+ LinkedListLib: "0x0000000000000000000000000000000000000000",
24
+ CollateralMathLib: "0x0000000000000000000000000000000000000000"
25
+ },
26
+ templates: {
27
+ StabilizerEscrow: "0x0000000000000000000000000000000000000000",
28
+ PositionEscrow: "0x0000000000000000000000000000000000000000"
29
+ },
30
+ external: {
31
+ stETH: "0x0000000000000000000000000000000000000000",
32
+ lido: "0x0000000000000000000000000000000000000000",
33
+ oracleSigner: "0x0000000000000000000000000000000000000000"
34
+ },
35
+ metadata: {
36
+ chainId: 31337,
37
+ deployBlock: 0,
38
+ deployTimestamp: 0,
39
+ deployer: "0x0000000000000000000000000000000000000000"
40
+ }
41
+ };
42
+
43
+ // src/deployments/11155111.json
44
+ var __default2 = {
45
+ contracts: {
46
+ UPDToken: "0x0000000000000000000000000000000000000000",
47
+ PriceOracle: "0x0000000000000000000000000000000000000000",
48
+ StabilizerNFT: "0x0000000000000000000000000000000000000000",
49
+ OvercollateralizationReporter: "0x0000000000000000000000000000000000000000",
50
+ InsuranceEscrow: "0x0000000000000000000000000000000000000000",
51
+ BridgeEscrow: "0x0000000000000000000000000000000000000000",
52
+ sUPD: "0x0000000000000000000000000000000000000000"
53
+ },
54
+ implementations: {
55
+ PriceOracle: "0x0000000000000000000000000000000000000000",
56
+ StabilizerNFT: "0x0000000000000000000000000000000000000000",
57
+ OvercollateralizationReporter: "0x0000000000000000000000000000000000000000"
58
+ },
59
+ libraries: {
60
+ LinkedListLib: "0x0000000000000000000000000000000000000000",
61
+ CollateralMathLib: "0x0000000000000000000000000000000000000000"
62
+ },
63
+ templates: {
64
+ StabilizerEscrow: "0x0000000000000000000000000000000000000000",
65
+ PositionEscrow: "0x0000000000000000000000000000000000000000"
66
+ },
67
+ external: {
68
+ stETH: "0x0000000000000000000000000000000000000000",
69
+ lido: "0x0000000000000000000000000000000000000000",
70
+ oracleSigner: "0x0000000000000000000000000000000000000000"
71
+ },
72
+ metadata: {
73
+ chainId: 11155111,
74
+ deployBlock: 0,
75
+ deployTimestamp: 0,
76
+ deployer: "0x0000000000000000000000000000000000000000"
77
+ }
78
+ };
79
+
80
+ // src/deployments/index.ts
81
+ function parseDeployment(json, chainId) {
82
+ return {
83
+ chainId,
84
+ contracts: {
85
+ UPDToken: json.contracts.UPDToken,
86
+ PriceOracle: json.contracts.PriceOracle,
87
+ StabilizerNFT: json.contracts.StabilizerNFT,
88
+ OvercollateralizationReporter: json.contracts.OvercollateralizationReporter,
89
+ InsuranceEscrow: json.contracts.InsuranceEscrow,
90
+ BridgeEscrow: json.contracts.BridgeEscrow,
91
+ sUPD: json.contracts.sUPD
92
+ },
93
+ implementations: {
94
+ PriceOracle: json.implementations.PriceOracle,
95
+ StabilizerNFT: json.implementations.StabilizerNFT,
96
+ OvercollateralizationReporter: json.implementations.OvercollateralizationReporter
97
+ },
98
+ libraries: {
99
+ LinkedListLib: json.libraries.LinkedListLib,
100
+ CollateralMathLib: json.libraries.CollateralMathLib
101
+ },
102
+ templates: {
103
+ StabilizerEscrow: json.templates.StabilizerEscrow,
104
+ PositionEscrow: json.templates.PositionEscrow
105
+ },
106
+ external: {
107
+ stETH: json.external.stETH,
108
+ lido: json.external.lido,
109
+ oracleSigner: json.external.oracleSigner
110
+ },
111
+ metadata: {
112
+ deployBlock: json.metadata.deployBlock,
113
+ deployTimestamp: json.metadata.deployTimestamp,
114
+ deployer: json.metadata.deployer
115
+ }
116
+ };
117
+ }
118
+ var deployments = {
119
+ 31337: parseDeployment(__default, 31337),
120
+ 11155111: parseDeployment(__default2, 11155111)
121
+ };
122
+ function getDeployment(chainId) {
123
+ return deployments[chainId] ?? null;
124
+ }
125
+ function getDeploymentOrThrow(chainId) {
126
+ const deployment = getDeployment(chainId);
127
+ if (!deployment) {
128
+ throw new Error(
129
+ `No UPD deployment found for chain ${chainId}. Supported chains: ${getSupportedChainIds().join(", ")}`
130
+ );
131
+ }
132
+ return deployment;
133
+ }
134
+ function hasDeployment(chainId) {
135
+ return chainId in deployments;
136
+ }
137
+ function getSupportedChainIds() {
138
+ return Object.keys(deployments).map(Number);
139
+ }
140
+ function getContractAddress(chainId, contractName) {
141
+ const deployment = getDeployment(chainId);
142
+ if (!deployment) return null;
143
+ return deployment.contracts[contractName] ?? null;
144
+ }
145
+
146
+ // src/core/client.ts
147
+ var UPDClient = class {
148
+ config;
149
+ deployment;
150
+ oracle;
151
+ constructor(config) {
152
+ this.config = config;
153
+ this.deployment = getDeploymentOrThrow(config.chainId);
154
+ this.oracle = createOracleClient({ oracleUrl: config.oracleUrl });
155
+ }
156
+ // ============================================================
157
+ // READ OPERATIONS
158
+ // ============================================================
159
+ /** Get UPD token balance for an address. */
160
+ async getUPDBalance(address) {
161
+ return this.config.publicClient.readContract({
162
+ address: this.deployment.contracts.UPDToken,
163
+ abi: UPD_TOKEN_ABI,
164
+ functionName: "balanceOf",
165
+ args: [address]
166
+ });
167
+ }
168
+ /** Get total UPD supply. */
169
+ async getTotalSupply() {
170
+ return this.config.publicClient.readContract({
171
+ address: this.deployment.contracts.UPDToken,
172
+ abi: UPD_TOKEN_ABI,
173
+ functionName: "totalSupply"
174
+ });
175
+ }
176
+ /** Get system collateral info: total stETH collateral and total UPD supply. */
177
+ async getCollateralInfo() {
178
+ const [totalStEthCollateral, totalUPDSupply] = await Promise.all([
179
+ this.config.publicClient.readContract({
180
+ address: this.deployment.contracts.OvercollateralizationReporter,
181
+ abi: OVERCOLLATERALIZATION_REPORTER_ABI,
182
+ functionName: "totalStEthCollateral"
183
+ }),
184
+ this.getTotalSupply()
185
+ ]);
186
+ return { totalStEthCollateral, totalUPDSupply };
187
+ }
188
+ /** Get details for a specific stabilizer position. */
189
+ async getStabilizerPosition(tokenId) {
190
+ const stabNFT = this.deployment.contracts.StabilizerNFT;
191
+ const [posEscrowAddr, stabEscrowAddr, minRatio] = await Promise.all([
192
+ this.config.publicClient.readContract({
193
+ address: stabNFT,
194
+ abi: STABILIZER_NFT_ABI,
195
+ functionName: "positionEscrows",
196
+ args: [tokenId]
197
+ }),
198
+ this.config.publicClient.readContract({
199
+ address: stabNFT,
200
+ abi: STABILIZER_NFT_ABI,
201
+ functionName: "stabilizerEscrows",
202
+ args: [tokenId]
203
+ }),
204
+ this.config.publicClient.readContract({
205
+ address: stabNFT,
206
+ abi: STABILIZER_NFT_ABI,
207
+ functionName: "minCollateralRatios",
208
+ args: [tokenId]
209
+ })
210
+ ]);
211
+ const [backedUPDAmount, stETHBalance, unallocatedStETH] = await Promise.all([
212
+ this.config.publicClient.readContract({
213
+ address: posEscrowAddr,
214
+ abi: POSITION_ESCROW_ABI,
215
+ functionName: "backedUPDAmount"
216
+ }),
217
+ this.config.publicClient.readContract({
218
+ address: posEscrowAddr,
219
+ abi: POSITION_ESCROW_ABI,
220
+ functionName: "getCurrentStEthBalance"
221
+ }),
222
+ this.config.publicClient.readContract({
223
+ address: stabEscrowAddr,
224
+ abi: STABILIZER_ESCROW_ABI,
225
+ functionName: "unallocatedStETH"
226
+ })
227
+ ]);
228
+ let collateralizationRatio2 = 0n;
229
+ if (backedUPDAmount > 0n && stETHBalance > 0n) {
230
+ collateralizationRatio2 = 0n;
231
+ }
232
+ return {
233
+ tokenId,
234
+ positionEscrowAddress: posEscrowAddr,
235
+ stabilizerEscrowAddress: stabEscrowAddr,
236
+ collateralizationRatio: collateralizationRatio2,
237
+ backedUPDAmount,
238
+ stETHBalance,
239
+ unallocatedStETH,
240
+ minCollateralRatio: minRatio
241
+ };
242
+ }
243
+ // ============================================================
244
+ // WRITE OPERATIONS
245
+ // ============================================================
246
+ /**
247
+ * Mint UPD by sending ETH. Requires walletClient.
248
+ *
249
+ * @example
250
+ * ```ts
251
+ * const attestation = createMockAttestation(2000n * 10n**18n)
252
+ * const hash = await client.mint({
253
+ * to: '0x...',
254
+ * ethAmount: parseEther('1'),
255
+ * priceAttestation: attestation,
256
+ * })
257
+ * ```
258
+ */
259
+ async mint(params) {
260
+ const walletClient = this._requireWallet();
261
+ const { to, ethAmount, priceAttestation } = params;
262
+ return walletClient.writeContract({
263
+ address: this.deployment.contracts.StabilizerNFT,
264
+ abi: STABILIZER_NFT_ABI,
265
+ functionName: "mintUPD",
266
+ args: [to, this._toSolidityAttestation(priceAttestation)],
267
+ value: ethAmount,
268
+ chain: walletClient.chain ?? null,
269
+ account: walletClient.account
270
+ });
271
+ }
272
+ /**
273
+ * Burn UPD to receive stETH. Requires walletClient.
274
+ *
275
+ * @example
276
+ * ```ts
277
+ * const attestation = createMockAttestation(2000n * 10n**18n)
278
+ * const hash = await client.burn({
279
+ * updAmount: parseUnits('2000', 18),
280
+ * priceAttestation: attestation,
281
+ * })
282
+ * ```
283
+ */
284
+ async burn(params) {
285
+ const walletClient = this._requireWallet();
286
+ const { updAmount, priceAttestation } = params;
287
+ return walletClient.writeContract({
288
+ address: this.deployment.contracts.StabilizerNFT,
289
+ abi: STABILIZER_NFT_ABI,
290
+ functionName: "burnUPD",
291
+ args: [updAmount, this._toSolidityAttestation(priceAttestation)],
292
+ chain: walletClient.chain ?? null,
293
+ account: walletClient.account
294
+ });
295
+ }
296
+ // ============================================================
297
+ // sUPD OPERATIONS
298
+ // ============================================================
299
+ /** Get sUPD contract info: share value, APY, supply, liability. */
300
+ async getSUPDInfo() {
301
+ const supdAddr = this.deployment.contracts.sUPD;
302
+ if (!supdAddr) throw new Error("sUPD not deployed on this chain");
303
+ const [shareValue, annualYieldBps, totalSupply, totalLiabilityUSD] = await Promise.all([
304
+ this.config.publicClient.readContract({
305
+ address: supdAddr,
306
+ abi: SUPD_ABI,
307
+ functionName: "currentShareValue"
308
+ }),
309
+ this.config.publicClient.readContract({
310
+ address: supdAddr,
311
+ abi: SUPD_ABI,
312
+ functionName: "annualYieldBps"
313
+ }),
314
+ this.config.publicClient.readContract({
315
+ address: supdAddr,
316
+ abi: SUPD_ABI,
317
+ functionName: "totalSupply"
318
+ }),
319
+ this.config.publicClient.readContract({
320
+ address: supdAddr,
321
+ abi: SUPD_ABI,
322
+ functionName: "totalLiabilityUSD"
323
+ })
324
+ ]);
325
+ return { shareValue, annualYieldBps, totalSupply, totalLiabilityUSD };
326
+ }
327
+ /** Stake UPD to receive sUPD shares. Requires walletClient. */
328
+ async stakeUPD(params) {
329
+ const walletClient = this._requireWallet();
330
+ const supdAddr = this.deployment.contracts.sUPD;
331
+ if (!supdAddr) throw new Error("sUPD not deployed on this chain");
332
+ return walletClient.writeContract({
333
+ address: supdAddr,
334
+ abi: SUPD_ABI,
335
+ functionName: "stakeUPD",
336
+ args: [params.updAmount, this._toSolidityAttestation(params.priceAttestation)],
337
+ chain: walletClient.chain ?? null,
338
+ account: walletClient.account
339
+ });
340
+ }
341
+ /** Unstake sUPD shares to receive UPD. Requires walletClient. */
342
+ async unstakeUPD(params) {
343
+ const walletClient = this._requireWallet();
344
+ const supdAddr = this.deployment.contracts.sUPD;
345
+ if (!supdAddr) throw new Error("sUPD not deployed on this chain");
346
+ return walletClient.writeContract({
347
+ address: supdAddr,
348
+ abi: SUPD_ABI,
349
+ functionName: "unstakeToUPD",
350
+ args: [params.shares, this._toSolidityAttestation(params.priceAttestation)],
351
+ chain: walletClient.chain ?? null,
352
+ account: walletClient.account
353
+ });
354
+ }
355
+ // ============================================================
356
+ // CONVENIENCE METHODS
357
+ // ============================================================
358
+ /**
359
+ * Mint UPD by sending ETH, automatically fetching a price attestation from the oracle.
360
+ *
361
+ * @example
362
+ * ```ts
363
+ * const hash = await client.mintWithOracle({
364
+ * to: '0x...',
365
+ * ethAmount: parseEther('1'),
366
+ * })
367
+ * ```
368
+ */
369
+ async mintWithOracle(params) {
370
+ const attestation = await this.oracle.getEthUsdAttestation();
371
+ return this.mint({ ...params, priceAttestation: attestation });
372
+ }
373
+ /**
374
+ * Burn UPD to receive stETH, automatically fetching a price attestation from the oracle.
375
+ *
376
+ * @example
377
+ * ```ts
378
+ * const hash = await client.burnWithOracle({
379
+ * updAmount: parseUnits('2000', 18),
380
+ * })
381
+ * ```
382
+ */
383
+ async burnWithOracle(params) {
384
+ const attestation = await this.oracle.getEthUsdAttestation();
385
+ return this.burn({ ...params, priceAttestation: attestation });
386
+ }
387
+ /**
388
+ * Get system health metrics by combining on-chain collateral data with oracle price.
389
+ *
390
+ * @example
391
+ * ```ts
392
+ * const health = await client.getSystemHealth()
393
+ * console.log(`System ratio: ${health.systemCollateralRatioBps} bps`)
394
+ * console.log(`Healthy: ${health.isHealthy}`)
395
+ * ```
396
+ */
397
+ async getSystemHealth() {
398
+ const [collateral, { price }] = await Promise.all([
399
+ this.getCollateralInfo(),
400
+ this.oracle.getEthUsdPrice()
401
+ ]);
402
+ return computeSystemHealth(collateral, price);
403
+ }
404
+ /** Stake UPD, fetching oracle attestation automatically. */
405
+ async stakeUPDWithOracle(params) {
406
+ const attestation = await this.oracle.getEthUsdAttestation();
407
+ return this.stakeUPD({ ...params, priceAttestation: attestation });
408
+ }
409
+ /** Unstake sUPD, fetching oracle attestation automatically. */
410
+ async unstakeUPDWithOracle(params) {
411
+ const attestation = await this.oracle.getEthUsdAttestation();
412
+ return this.unstakeUPD({ ...params, priceAttestation: attestation });
413
+ }
414
+ // ============================================================
415
+ // HELPERS
416
+ // ============================================================
417
+ _requireWallet() {
418
+ if (!this.config.walletClient) {
419
+ throw new Error(
420
+ "UPDClient: walletClient is required for write operations. Pass a walletClient in the config to use mint/burn."
421
+ );
422
+ }
423
+ return this.config.walletClient;
424
+ }
425
+ _toSolidityAttestation(a) {
426
+ return {
427
+ price: a.price,
428
+ decimals: a.decimals,
429
+ dataTimestamp: a.dataTimestamp,
430
+ assetPair: a.assetPair,
431
+ signature: a.signature
432
+ };
433
+ }
434
+ };
435
+ function createUPDClient(config) {
436
+ return new UPDClient(config);
437
+ }
438
+ var EIP3009_DOMAIN_VERSION = "1";
439
+ function randomNonce() {
440
+ const bytes = new Uint8Array(32);
441
+ crypto.getRandomValues(bytes);
442
+ return bytesToHex(bytes);
443
+ }
444
+ function eip3009Domain(tokenAddress, chainId, tokenName) {
445
+ return {
446
+ name: tokenName,
447
+ version: EIP3009_DOMAIN_VERSION,
448
+ chainId,
449
+ verifyingContract: tokenAddress
450
+ };
451
+ }
452
+ async function signTransferAuthorization(params, tokenName = "Universal Private Dollar") {
453
+ const {
454
+ walletClient,
455
+ tokenAddress,
456
+ from,
457
+ to,
458
+ value,
459
+ validAfter = 0n,
460
+ validBefore = BigInt(Math.floor(Date.now() / 1e3) + 3600),
461
+ nonce = randomNonce()
462
+ } = params;
463
+ const chainId = walletClient.chain?.id;
464
+ if (!chainId) throw new Error("walletClient must have a chain configured");
465
+ const signature = await walletClient.signTypedData({
466
+ account: from,
467
+ domain: eip3009Domain(tokenAddress, chainId, tokenName),
468
+ types: {
469
+ TransferWithAuthorization: [
470
+ { name: "from", type: "address" },
471
+ { name: "to", type: "address" },
472
+ { name: "value", type: "uint256" },
473
+ { name: "validAfter", type: "uint256" },
474
+ { name: "validBefore", type: "uint256" },
475
+ { name: "nonce", type: "bytes32" }
476
+ ]
477
+ },
478
+ primaryType: "TransferWithAuthorization",
479
+ message: { from, to, value, validAfter, validBefore, nonce }
480
+ });
481
+ const sigBytes = hexToBytes(signature);
482
+ const r = bytesToHex(sigBytes.slice(0, 32));
483
+ const s = bytesToHex(sigBytes.slice(32, 64));
484
+ const v = sigBytes[64];
485
+ return { from, to, value, validAfter, validBefore, nonce, v, r, s };
486
+ }
487
+ async function signReceiveAuthorization(params, tokenName = "Universal Private Dollar") {
488
+ const {
489
+ walletClient,
490
+ tokenAddress,
491
+ from,
492
+ to,
493
+ value,
494
+ validAfter = 0n,
495
+ validBefore = BigInt(Math.floor(Date.now() / 1e3) + 3600),
496
+ nonce = randomNonce()
497
+ } = params;
498
+ const chainId = walletClient.chain?.id;
499
+ if (!chainId) throw new Error("walletClient must have a chain configured");
500
+ const signature = await walletClient.signTypedData({
501
+ account: from,
502
+ domain: eip3009Domain(tokenAddress, chainId, tokenName),
503
+ types: {
504
+ ReceiveWithAuthorization: [
505
+ { name: "from", type: "address" },
506
+ { name: "to", type: "address" },
507
+ { name: "value", type: "uint256" },
508
+ { name: "validAfter", type: "uint256" },
509
+ { name: "validBefore", type: "uint256" },
510
+ { name: "nonce", type: "bytes32" }
511
+ ]
512
+ },
513
+ primaryType: "ReceiveWithAuthorization",
514
+ message: { from, to, value, validAfter, validBefore, nonce }
515
+ });
516
+ const sigBytes = hexToBytes(signature);
517
+ const r = bytesToHex(sigBytes.slice(0, 32));
518
+ const s = bytesToHex(sigBytes.slice(32, 64));
519
+ const v = sigBytes[64];
520
+ return { from, to, value, validAfter, validBefore, nonce, v, r, s };
521
+ }
522
+ async function signCancelAuthorization(params, tokenName = "Universal Private Dollar") {
523
+ const { walletClient, tokenAddress, authorizer, nonce } = params;
524
+ const chainId = walletClient.chain?.id;
525
+ if (!chainId) throw new Error("walletClient must have a chain configured");
526
+ const signature = await walletClient.signTypedData({
527
+ account: authorizer,
528
+ domain: eip3009Domain(tokenAddress, chainId, tokenName),
529
+ types: {
530
+ CancelAuthorization: [
531
+ { name: "authorizer", type: "address" },
532
+ { name: "nonce", type: "bytes32" }
533
+ ]
534
+ },
535
+ primaryType: "CancelAuthorization",
536
+ message: { authorizer, nonce }
537
+ });
538
+ const sigBytes = hexToBytes(signature);
539
+ const r = bytesToHex(sigBytes.slice(0, 32));
540
+ const s = bytesToHex(sigBytes.slice(32, 64));
541
+ const v = sigBytes[64];
542
+ return { authorizer, nonce, v, r, s };
543
+ }
544
+
545
+ // src/core/verify.ts
546
+ var ERC1967_IMPL_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
547
+ async function verifyDeployment(publicClient, deployment) {
548
+ const checks = [];
549
+ await _verifyBytecode(publicClient, checks, "UPDToken", deployment.contracts.UPDToken);
550
+ await _verifyBytecode(publicClient, checks, "PriceOracle", deployment.contracts.PriceOracle);
551
+ await _verifyBytecode(publicClient, checks, "StabilizerNFT", deployment.contracts.StabilizerNFT);
552
+ await _verifyBytecode(publicClient, checks, "Reporter", deployment.contracts.OvercollateralizationReporter);
553
+ await _verifyBytecode(publicClient, checks, "InsuranceEscrow", deployment.contracts.InsuranceEscrow);
554
+ await _verifyProxyImpl(publicClient, checks, "PriceOracle", deployment.contracts.PriceOracle, deployment.implementations.PriceOracle);
555
+ await _verifyProxyImpl(publicClient, checks, "StabilizerNFT", deployment.contracts.StabilizerNFT, deployment.implementations.StabilizerNFT);
556
+ await _verifyProxyImpl(publicClient, checks, "Reporter", deployment.contracts.OvercollateralizationReporter, deployment.implementations.OvercollateralizationReporter);
557
+ await _verifyStabilizerNFTStorage(publicClient, checks, deployment);
558
+ await _verifyReporterStorage(publicClient, checks, deployment);
559
+ await _verifyRole(
560
+ publicClient,
561
+ checks,
562
+ "UPDToken MINTER_ROLE -> StabilizerNFT",
563
+ deployment.contracts.UPDToken,
564
+ UPD_TOKEN_ABI,
565
+ "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6",
566
+ // keccak256("MINTER_ROLE")
567
+ deployment.contracts.StabilizerNFT
568
+ );
569
+ await _verifyRole(
570
+ publicClient,
571
+ checks,
572
+ "UPDToken BURNER_ROLE -> StabilizerNFT",
573
+ deployment.contracts.UPDToken,
574
+ UPD_TOKEN_ABI,
575
+ "0x3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848",
576
+ // keccak256("BURNER_ROLE")
577
+ deployment.contracts.StabilizerNFT
578
+ );
579
+ const passed = checks.filter((c) => c.passed).length;
580
+ const failed = checks.filter((c) => !c.passed).length;
581
+ return {
582
+ chainId: deployment.chainId,
583
+ checks,
584
+ passed,
585
+ failed,
586
+ allPassed: failed === 0
587
+ };
588
+ }
589
+ async function _verifyBytecode(client, checks, name, address) {
590
+ try {
591
+ const code = await client.getCode({ address });
592
+ const exists = code !== void 0 && code !== "0x" && code.length > 2;
593
+ checks.push({ name: `${name} bytecode exists`, passed: exists });
594
+ } catch {
595
+ checks.push({ name: `${name} bytecode exists`, passed: false });
596
+ }
597
+ }
598
+ async function _verifyProxyImpl(client, checks, name, proxyAddress, expectedImpl) {
599
+ try {
600
+ const implSlot = await client.getStorageAt({
601
+ address: proxyAddress,
602
+ slot: ERC1967_IMPL_SLOT
603
+ });
604
+ const actualImpl = ("0x" + (implSlot ?? "0x").slice(26)).toLowerCase();
605
+ const expected = expectedImpl.toLowerCase();
606
+ checks.push({
607
+ name: `${name} proxy -> impl`,
608
+ passed: actualImpl === expected,
609
+ expected: expectedImpl,
610
+ actual: actualImpl
611
+ });
612
+ } catch {
613
+ checks.push({ name: `${name} proxy -> impl`, passed: false, expected: expectedImpl });
614
+ }
615
+ }
616
+ async function _verifyStabilizerNFTStorage(client, checks, d) {
617
+ try {
618
+ const nft = d.contracts.StabilizerNFT;
619
+ const updToken = await client.readContract({
620
+ address: nft,
621
+ abi: STABILIZER_NFT_ABI,
622
+ functionName: "updToken"
623
+ });
624
+ checks.push({
625
+ name: "StabilizerNFT.updToken",
626
+ passed: updToken.toLowerCase() === d.contracts.UPDToken.toLowerCase(),
627
+ expected: d.contracts.UPDToken,
628
+ actual: updToken
629
+ });
630
+ const oracle = await client.readContract({
631
+ address: nft,
632
+ abi: STABILIZER_NFT_ABI,
633
+ functionName: "oracle"
634
+ });
635
+ checks.push({
636
+ name: "StabilizerNFT.oracle",
637
+ passed: oracle.toLowerCase() === d.contracts.PriceOracle.toLowerCase(),
638
+ expected: d.contracts.PriceOracle,
639
+ actual: oracle
640
+ });
641
+ const stETH = await client.readContract({
642
+ address: nft,
643
+ abi: STABILIZER_NFT_ABI,
644
+ functionName: "stETH"
645
+ });
646
+ checks.push({
647
+ name: "StabilizerNFT.stETH",
648
+ passed: stETH.toLowerCase() === d.external.stETH.toLowerCase(),
649
+ expected: d.external.stETH,
650
+ actual: stETH
651
+ });
652
+ } catch {
653
+ checks.push({ name: "StabilizerNFT storage", passed: false });
654
+ }
655
+ }
656
+ async function _verifyReporterStorage(client, checks, d) {
657
+ try {
658
+ const reporter = d.contracts.OvercollateralizationReporter;
659
+ const stabNFT = await client.readContract({
660
+ address: reporter,
661
+ abi: OVERCOLLATERALIZATION_REPORTER_ABI,
662
+ functionName: "stabilizerNFTContract"
663
+ });
664
+ checks.push({
665
+ name: "Reporter.stabilizerNFT",
666
+ passed: stabNFT.toLowerCase() === d.contracts.StabilizerNFT.toLowerCase(),
667
+ expected: d.contracts.StabilizerNFT,
668
+ actual: stabNFT
669
+ });
670
+ const updToken = await client.readContract({
671
+ address: reporter,
672
+ abi: OVERCOLLATERALIZATION_REPORTER_ABI,
673
+ functionName: "updToken"
674
+ });
675
+ checks.push({
676
+ name: "Reporter.updToken",
677
+ passed: updToken.toLowerCase() === d.contracts.UPDToken.toLowerCase(),
678
+ expected: d.contracts.UPDToken,
679
+ actual: updToken
680
+ });
681
+ } catch {
682
+ checks.push({ name: "Reporter storage", passed: false });
683
+ }
684
+ }
685
+ async function _verifyRole(client, checks, name, contractAddress, abi, roleHash, account) {
686
+ try {
687
+ const hasRole = await client.readContract({
688
+ address: contractAddress,
689
+ abi,
690
+ functionName: "hasRole",
691
+ args: [roleHash, account]
692
+ });
693
+ checks.push({ name, passed: hasRole });
694
+ } catch {
695
+ checks.push({ name, passed: false });
696
+ }
697
+ }
698
+
699
+ export { UPDClient, createUPDClient, getContractAddress, getDeployment, getDeploymentOrThrow, getSupportedChainIds, hasDeployment, signCancelAuthorization, signReceiveAuthorization, signTransferAuthorization, verifyDeployment };
700
+ //# sourceMappingURL=chunk-R64I3LAO.js.map
701
+ //# sourceMappingURL=chunk-R64I3LAO.js.map