deploy-sdk 0.0.1

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.
@@ -0,0 +1,733 @@
1
+ // src/modules/mint/MintModule.ts
2
+ import { Contract } from "ethers";
3
+
4
+ // src/core/errors.ts
5
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
6
+ ErrorCode2["NOT_INITIALIZED"] = "NOT_INITIALIZED";
7
+ ErrorCode2["WALLET_NOT_CONNECTED"] = "WALLET_NOT_CONNECTED";
8
+ ErrorCode2["INVALID_CHAIN"] = "INVALID_CHAIN";
9
+ ErrorCode2["INSUFFICIENT_BALANCE"] = "INSUFFICIENT_BALANCE";
10
+ ErrorCode2["INSUFFICIENT_ALLOWANCE"] = "INSUFFICIENT_ALLOWANCE";
11
+ ErrorCode2["TRANSACTION_FAILED"] = "TRANSACTION_FAILED";
12
+ ErrorCode2["STAKE_FAILED"] = "STAKE_FAILED";
13
+ ErrorCode2["UNSTAKE_FAILED"] = "UNSTAKE_FAILED";
14
+ ErrorCode2["COOLDOWN_FAILED"] = "COOLDOWN_FAILED";
15
+ ErrorCode2["MINT_FAILED"] = "MINT_FAILED";
16
+ ErrorCode2["REDEEM_FAILED"] = "REDEEM_FAILED";
17
+ ErrorCode2["INVALID_ORDER"] = "INVALID_ORDER";
18
+ ErrorCode2["SIGNATURE_FAILED"] = "SIGNATURE_FAILED";
19
+ ErrorCode2["API_ERROR"] = "API_ERROR";
20
+ ErrorCode2["VALIDATION_ERROR"] = "VALIDATION_ERROR";
21
+ return ErrorCode2;
22
+ })(ErrorCode || {});
23
+ var DeploySDKError = class _DeploySDKError extends Error {
24
+ constructor(code, message, originalError) {
25
+ super(message);
26
+ this.name = "DeploySDKError";
27
+ this.code = code;
28
+ this.originalError = originalError;
29
+ if (Error.captureStackTrace) {
30
+ Error.captureStackTrace(this, _DeploySDKError);
31
+ }
32
+ }
33
+ toJSON() {
34
+ return {
35
+ name: this.name,
36
+ code: this.code,
37
+ message: this.message,
38
+ originalError: this.originalError?.message || this.originalError
39
+ };
40
+ }
41
+ };
42
+
43
+ // src/core/constants.ts
44
+ var CONTRACT_ADDRESSES = {
45
+ [1 /* ETHEREUM */]: {
46
+ USDC: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
47
+ USDT: "0xdac17f958d2ee523a2206206994597c13d831ec7",
48
+ dUSD: "0xf42e0b98e32150fe02a370456e6479fcd94f5531",
49
+ DUSD_MINTER: "0x1ee453Ea35f6EAbD9BFF126586322cbC906D4EB3",
50
+ sDUSD_STAKING: "0x7f37B0133B1adC1D0647EE52eA38fA13caC4aA1B"
51
+ },
52
+ [42161 /* ARBITRUM */]: {}
53
+ };
54
+ var COLLATERAL_ASSETS = {
55
+ USDC: {
56
+ key: "USDC",
57
+ name: "USD Coin",
58
+ symbol: "USDC",
59
+ address: CONTRACT_ADDRESSES[1 /* ETHEREUM */].USDC,
60
+ decimals: 6,
61
+ mintingContract: CONTRACT_ADDRESSES[1 /* ETHEREUM */].DUSD_MINTER
62
+ },
63
+ USDT: {
64
+ key: "USDT",
65
+ name: "Tether USD",
66
+ symbol: "USDT",
67
+ address: CONTRACT_ADDRESSES[1 /* ETHEREUM */].USDT,
68
+ decimals: 6,
69
+ mintingContract: CONTRACT_ADDRESSES[1 /* ETHEREUM */].DUSD_MINTER
70
+ }
71
+ };
72
+ var STAKE_TOKENS = {
73
+ dUSD: {
74
+ key: "dUSD",
75
+ name: "Deploy USD",
76
+ symbol: "dUSD",
77
+ address: CONTRACT_ADDRESSES[1 /* ETHEREUM */].dUSD,
78
+ decimals: 18,
79
+ supportedCollateral: [COLLATERAL_ASSETS.USDC, COLLATERAL_ASSETS.USDT],
80
+ mintingContract: CONTRACT_ADDRESSES[1 /* ETHEREUM */].DUSD_MINTER,
81
+ stakingContract: CONTRACT_ADDRESSES[1 /* ETHEREUM */].sDUSD_STAKING,
82
+ stakingSymbol: "sDUSD",
83
+ cooldownPeriod: 90 * 24 * 60 * 60 * 1e3
84
+ }
85
+ };
86
+ var EIP712_TYPES_ORDER = {
87
+ Order: [
88
+ { name: "order_id", type: "string" },
89
+ { name: "order_type", type: "uint8" },
90
+ { name: "expiry", type: "uint256" },
91
+ { name: "nonce", type: "uint256" },
92
+ { name: "benefactor", type: "address" },
93
+ { name: "beneficiary", type: "address" },
94
+ { name: "collateral_asset", type: "address" },
95
+ { name: "collateral_amount", type: "uint256" },
96
+ { name: "dAsset_amount", type: "uint256" }
97
+ ]
98
+ };
99
+ var ERC4626_ABI = [
100
+ "function deposit(uint256 assets, address receiver) external returns (uint256 shares)",
101
+ "function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares)",
102
+ "function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets)",
103
+ "function cooldownShares(uint256 shares) external",
104
+ "function cooldowns(address user) external view returns (uint256 cooldownEnd, uint256 underlyingAmount)",
105
+ "function balanceOf(address owner) external view returns (uint256)",
106
+ "function convertToShares(uint256 assets) external view returns (uint256)",
107
+ "function convertToAssets(uint256 shares) external view returns (uint256)",
108
+ "function totalAssets() external view returns (uint256)",
109
+ "function totalSupply() external view returns (uint256)",
110
+ "event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares)",
111
+ "event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares)"
112
+ ];
113
+ var ERC20_ABI = [
114
+ "function approve(address spender, uint256 amount) external returns (bool)",
115
+ "function allowance(address owner, address spender) external view returns (uint256)",
116
+ "function balanceOf(address account) external view returns (uint256)",
117
+ "function decimals() external view returns (uint8)",
118
+ "function symbol() external view returns (string)",
119
+ "function name() external view returns (string)",
120
+ "function transfer(address recipient, uint256 amount) external returns (bool)",
121
+ "function transferFrom(address sender, address recipient, uint256 amount) external returns (bool)",
122
+ "event Approval(address indexed owner, address indexed spender, uint256 value)",
123
+ "event Transfer(address indexed from, address indexed to, uint256 value)"
124
+ ];
125
+ var MINTER_ABI = [
126
+ "function mint(tuple(string order_id, uint8 order_type, uint256 expiry, uint256 nonce, address benefactor, address beneficiary, address collateral_asset, uint256 collateral_amount, uint256 dAsset_amount) order, tuple(address[] addresses, uint256[] ratios) route, tuple(uint8 signature_type, bytes signature_bytes) signature) external",
127
+ "function redeem(tuple(string order_id, uint8 order_type, uint256 expiry, uint256 nonce, address benefactor, address beneficiary, address collateral_asset, uint256 collateral_amount, uint256 dAsset_amount) order, tuple(uint8 signature_type, bytes signature_bytes) signature) external",
128
+ "function isWhitelistedBenefactor(address benefactor) external view returns (bool)",
129
+ "function addWhitelistedBenefactor(address benefactor) external",
130
+ "function removeWhitelistedBenefactor(address benefactor) external"
131
+ ];
132
+
133
+ // src/modules/mint/MintModule.ts
134
+ import { v4 as uuidv4 } from "uuid";
135
+ var MintModule = class {
136
+ constructor(sdk) {
137
+ this.sdk = sdk;
138
+ }
139
+ async createOrder(collateralAsset, collateralAmount, dAssetAmount, options) {
140
+ const address = await this.sdk.getAddress();
141
+ const orderId = uuidv4();
142
+ const expiry = Math.floor(Date.now() / 1e3) + (options?.expiryMinutes || 5) * 60;
143
+ const minterAddress = collateralAsset.mintingContract;
144
+ const order = {
145
+ orderId,
146
+ orderType: 0,
147
+ expiry,
148
+ nonce: Date.now(),
149
+ benefactor: options?.benefactor || address,
150
+ beneficiary: options?.beneficiary || address,
151
+ collateralAsset: collateralAsset.address,
152
+ collateralAmount: collateralAmount.toString(),
153
+ dAssetAmount: dAssetAmount.toString(),
154
+ minterAddress
155
+ };
156
+ return order;
157
+ }
158
+ async signOrder(order) {
159
+ const signer = this.sdk.signer;
160
+ const domain = {
161
+ name: "DeployMinting",
162
+ version: "1",
163
+ chainId: await this.sdk.getChainId(),
164
+ verifyingContract: order.minterAddress
165
+ };
166
+ const value = {
167
+ order_id: order.orderId,
168
+ order_type: order.orderType,
169
+ expiry: order.expiry,
170
+ nonce: order.nonce,
171
+ benefactor: order.benefactor,
172
+ beneficiary: order.beneficiary,
173
+ collateral_asset: order.collateralAsset,
174
+ collateral_amount: order.collateralAmount,
175
+ dAsset_amount: order.dAssetAmount
176
+ };
177
+ try {
178
+ const signature = await signer._signTypedData(domain, EIP712_TYPES_ORDER, value);
179
+ return signature;
180
+ } catch (error) {
181
+ throw new DeploySDKError(
182
+ "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
183
+ "Failed to sign mint order",
184
+ error
185
+ );
186
+ }
187
+ }
188
+ async submitOrder(order, signature) {
189
+ try {
190
+ const response = await fetch(`${this.sdk.config.apiUrl}/api/mint`, {
191
+ method: "POST",
192
+ headers: {
193
+ "Content-Type": "application/json"
194
+ },
195
+ body: JSON.stringify({
196
+ order: {
197
+ order_id: order.orderId,
198
+ order_type: order.orderType,
199
+ expiry: order.expiry,
200
+ nonce: order.nonce,
201
+ benefactor: order.benefactor,
202
+ beneficiary: order.beneficiary,
203
+ collateral_asset: order.collateralAsset,
204
+ collateral_amount: order.collateralAmount,
205
+ dAsset_amount: order.dAssetAmount
206
+ },
207
+ signature: {
208
+ signature_type: 0,
209
+ signature_bytes: signature
210
+ }
211
+ })
212
+ });
213
+ if (!response.ok) {
214
+ const error = await response.json();
215
+ throw new DeploySDKError(
216
+ "API_ERROR" /* API_ERROR */,
217
+ error.message || "Failed to submit mint order"
218
+ );
219
+ }
220
+ const result = await response.json();
221
+ return {
222
+ success: true,
223
+ orderId: order.orderId,
224
+ txHash: result.txHash,
225
+ status: result.status
226
+ };
227
+ } catch (error) {
228
+ if (error instanceof DeploySDKError) throw error;
229
+ throw new DeploySDKError(
230
+ "API_ERROR" /* API_ERROR */,
231
+ "Failed to submit mint order",
232
+ error
233
+ );
234
+ }
235
+ }
236
+ async mint(collateralAsset, collateralAmount, dAssetAmount, options) {
237
+ try {
238
+ const order = await this.createOrder(
239
+ collateralAsset,
240
+ collateralAmount,
241
+ dAssetAmount,
242
+ options
243
+ );
244
+ const signature = await this.signOrder(order);
245
+ return await this.submitOrder(order, signature);
246
+ } catch (error) {
247
+ if (error instanceof DeploySDKError) throw error;
248
+ throw new DeploySDKError(
249
+ "MINT_FAILED" /* MINT_FAILED */,
250
+ "Failed to mint tokens",
251
+ error
252
+ );
253
+ }
254
+ }
255
+ async estimateGas(collateralAsset, collateralAmount, dAssetAmount, signature) {
256
+ const minterContract = new Contract(
257
+ collateralAsset.mintingContract,
258
+ MINTER_ABI,
259
+ this.sdk.provider
260
+ );
261
+ const order = {
262
+ order_id: uuidv4(),
263
+ order_type: 0,
264
+ expiry: Math.floor(Date.now() / 1e3) + 300,
265
+ nonce: Date.now(),
266
+ benefactor: await this.sdk.getAddress(),
267
+ beneficiary: await this.sdk.getAddress(),
268
+ collateral_asset: collateralAsset.address,
269
+ collateral_amount: collateralAmount.toString(),
270
+ dAsset_amount: dAssetAmount.toString()
271
+ };
272
+ try {
273
+ const gasEstimate = await minterContract.estimateGas.mint(
274
+ order,
275
+ { addresses: [], ratios: [] },
276
+ { signature_type: 0, signature_bytes: signature }
277
+ );
278
+ return gasEstimate.toBigInt();
279
+ } catch (error) {
280
+ throw new DeploySDKError(
281
+ "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
282
+ "Failed to estimate gas for mint",
283
+ error
284
+ );
285
+ }
286
+ }
287
+ };
288
+
289
+ // src/modules/stake/StakeModule.ts
290
+ import { Contract as Contract2, BigNumber } from "ethers";
291
+ var StakeModule = class {
292
+ constructor(sdk) {
293
+ this.sdk = sdk;
294
+ }
295
+ async stake(params) {
296
+ try {
297
+ const { token, amount, receiver } = params;
298
+ if (!token.stakingContract) {
299
+ throw new DeploySDKError(
300
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
301
+ `Token ${token.symbol} does not support staking`
302
+ );
303
+ }
304
+ const vaultContract = new Contract2(
305
+ token.stakingContract,
306
+ ERC4626_ABI,
307
+ this.sdk.signer
308
+ );
309
+ const receiverAddress = receiver || await this.sdk.getAddress();
310
+ const tx = await vaultContract.deposit(amount, receiverAddress);
311
+ const receipt = await tx.wait();
312
+ let sharesReceived;
313
+ const depositEvent = receipt.events?.find(
314
+ (e) => e.event === "Deposit"
315
+ );
316
+ if (depositEvent) {
317
+ sharesReceived = depositEvent.args?.shares?.toString();
318
+ }
319
+ return {
320
+ success: true,
321
+ txHash: receipt.transactionHash,
322
+ sharesReceived
323
+ };
324
+ } catch (error) {
325
+ if (error instanceof DeploySDKError) throw error;
326
+ throw new DeploySDKError(
327
+ "STAKE_FAILED" /* STAKE_FAILED */,
328
+ "Failed to stake tokens",
329
+ error
330
+ );
331
+ }
332
+ }
333
+ async getPosition(token, userAddress) {
334
+ if (!token.stakingContract) {
335
+ throw new DeploySDKError(
336
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
337
+ `Token ${token.symbol} does not support staking`
338
+ );
339
+ }
340
+ const address = userAddress || await this.sdk.getAddress();
341
+ const vaultContract = new Contract2(
342
+ token.stakingContract,
343
+ ERC4626_ABI,
344
+ this.sdk.provider
345
+ );
346
+ try {
347
+ const [shares, assets, cooldown] = await Promise.all([
348
+ vaultContract.balanceOf(address),
349
+ vaultContract.convertToAssets(await vaultContract.balanceOf(address)),
350
+ vaultContract.cooldowns(address).catch(() => ({ cooldownEnd: BigNumber.from(0), underlyingAmount: BigNumber.from(0) }))
351
+ ]);
352
+ const cooldownEnd = cooldown.cooldownEnd.toNumber() * 1e3;
353
+ return {
354
+ tokenKey: token.key,
355
+ stakedAmount: shares.toString(),
356
+ stakedValue: assets.toString(),
357
+ cooldownEnd: cooldownEnd > 0 ? cooldownEnd : void 0,
358
+ canUnstake: cooldownEnd === 0 || cooldownEnd <= Date.now()
359
+ };
360
+ } catch (error) {
361
+ throw new DeploySDKError(
362
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
363
+ "Failed to fetch staking position",
364
+ error
365
+ );
366
+ }
367
+ }
368
+ async previewStake(token, amount) {
369
+ if (!token.stakingContract) {
370
+ throw new DeploySDKError(
371
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
372
+ `Token ${token.symbol} does not support staking`
373
+ );
374
+ }
375
+ const vaultContract = new Contract2(
376
+ token.stakingContract,
377
+ ERC4626_ABI,
378
+ this.sdk.provider
379
+ );
380
+ try {
381
+ const shares = await vaultContract.convertToShares(amount);
382
+ return {
383
+ shares: shares.toString(),
384
+ assets: amount.toString()
385
+ };
386
+ } catch (error) {
387
+ throw new DeploySDKError(
388
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
389
+ "Failed to preview stake",
390
+ error
391
+ );
392
+ }
393
+ }
394
+ async getAPY(token) {
395
+ if (!token.stakingContract) {
396
+ return 0;
397
+ }
398
+ const vaultContract = new Contract2(
399
+ token.stakingContract,
400
+ ERC4626_ABI,
401
+ this.sdk.provider
402
+ );
403
+ try {
404
+ const [totalAssets, totalSupply] = await Promise.all([
405
+ vaultContract.totalAssets(),
406
+ vaultContract.totalSupply()
407
+ ]);
408
+ if (totalSupply.isZero()) {
409
+ return 0;
410
+ }
411
+ const sharePrice = totalAssets.mul(BigNumber.from(10).pow(18)).div(totalSupply);
412
+ const basePrice = BigNumber.from(10).pow(18);
413
+ if (sharePrice.lte(basePrice)) {
414
+ return 0;
415
+ }
416
+ const yieldPerShare = sharePrice.sub(basePrice);
417
+ const dailyYield = yieldPerShare.mul(365);
418
+ const apy = dailyYield.mul(1e4).div(basePrice).toNumber() / 100;
419
+ return apy;
420
+ } catch (error) {
421
+ return 0;
422
+ }
423
+ }
424
+ };
425
+
426
+ // src/modules/unstake/UnstakeModule.ts
427
+ import { Contract as Contract3 } from "ethers";
428
+ var UnstakeModule = class {
429
+ constructor(sdk) {
430
+ this.sdk = sdk;
431
+ }
432
+ async initiateCooldown(token, sharesAmount) {
433
+ try {
434
+ if (!token.stakingContract) {
435
+ throw new DeploySDKError(
436
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
437
+ `Token ${token.symbol} does not support staking`
438
+ );
439
+ }
440
+ const vaultContract = new Contract3(
441
+ token.stakingContract,
442
+ ERC4626_ABI,
443
+ this.sdk.signer
444
+ );
445
+ const tx = await vaultContract.cooldownShares(sharesAmount);
446
+ const receipt = await tx.wait();
447
+ const cooldownEnd = Date.now() + (token.cooldownPeriod || 90 * 24 * 60 * 60 * 1e3);
448
+ return {
449
+ success: true,
450
+ txHash: receipt.transactionHash,
451
+ cooldownEnd
452
+ };
453
+ } catch (error) {
454
+ if (error instanceof DeploySDKError) throw error;
455
+ throw new DeploySDKError(
456
+ "COOLDOWN_FAILED" /* COOLDOWN_FAILED */,
457
+ "Failed to initiate cooldown",
458
+ error
459
+ );
460
+ }
461
+ }
462
+ async unstake(params) {
463
+ try {
464
+ const { token, sharesAmount, receiver } = params;
465
+ if (!token.stakingContract) {
466
+ throw new DeploySDKError(
467
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
468
+ `Token ${token.symbol} does not support staking`
469
+ );
470
+ }
471
+ const cooldownStatus = await this.getCooldownStatus(token);
472
+ if (!cooldownStatus.canUnstake) {
473
+ throw new DeploySDKError(
474
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
475
+ `Cannot unstake. Cooldown ends at ${new Date(cooldownStatus.cooldownEnd).toLocaleString()}`
476
+ );
477
+ }
478
+ const vaultContract = new Contract3(
479
+ token.stakingContract,
480
+ ERC4626_ABI,
481
+ this.sdk.signer
482
+ );
483
+ const receiverAddress = receiver || await this.sdk.getAddress();
484
+ const owner = await this.sdk.getAddress();
485
+ const tx = await vaultContract.redeem(sharesAmount, receiverAddress, owner);
486
+ const receipt = await tx.wait();
487
+ let assetsWithdrawn;
488
+ const withdrawEvent = receipt.events?.find(
489
+ (e) => e.event === "Withdraw"
490
+ );
491
+ if (withdrawEvent) {
492
+ assetsWithdrawn = withdrawEvent.args?.assets?.toString();
493
+ }
494
+ return {
495
+ success: true,
496
+ txHash: receipt.transactionHash,
497
+ assetsWithdrawn
498
+ };
499
+ } catch (error) {
500
+ if (error instanceof DeploySDKError) throw error;
501
+ throw new DeploySDKError(
502
+ "UNSTAKE_FAILED" /* UNSTAKE_FAILED */,
503
+ "Failed to unstake tokens",
504
+ error
505
+ );
506
+ }
507
+ }
508
+ async getCooldownStatus(token, userAddress) {
509
+ if (!token.stakingContract) {
510
+ throw new DeploySDKError(
511
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
512
+ `Token ${token.symbol} does not support staking`
513
+ );
514
+ }
515
+ const address = userAddress || await this.sdk.getAddress();
516
+ const vaultContract = new Contract3(
517
+ token.stakingContract,
518
+ ERC4626_ABI,
519
+ this.sdk.provider
520
+ );
521
+ try {
522
+ const cooldown = await vaultContract.cooldowns(address);
523
+ const cooldownEnd = cooldown.cooldownEnd.toNumber() * 1e3;
524
+ return {
525
+ cooldownEnd,
526
+ sharesInCooldown: cooldown.underlyingAmount.toString(),
527
+ canUnstake: cooldownEnd > 0 && cooldownEnd <= Date.now()
528
+ };
529
+ } catch (error) {
530
+ throw new DeploySDKError(
531
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
532
+ "Failed to fetch cooldown status",
533
+ error
534
+ );
535
+ }
536
+ }
537
+ async previewUnstake(token, sharesAmount) {
538
+ if (!token.stakingContract) {
539
+ throw new DeploySDKError(
540
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
541
+ `Token ${token.symbol} does not support staking`
542
+ );
543
+ }
544
+ const vaultContract = new Contract3(
545
+ token.stakingContract,
546
+ ERC4626_ABI,
547
+ this.sdk.provider
548
+ );
549
+ try {
550
+ const assets = await vaultContract.convertToAssets(sharesAmount);
551
+ return assets.toString();
552
+ } catch (error) {
553
+ throw new DeploySDKError(
554
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
555
+ "Failed to preview unstake",
556
+ error
557
+ );
558
+ }
559
+ }
560
+ };
561
+
562
+ // src/modules/redeem/RedeemModule.ts
563
+ import { Contract as Contract4 } from "ethers";
564
+ import { v4 as uuidv42 } from "uuid";
565
+ var RedeemModule = class {
566
+ constructor(sdk) {
567
+ this.sdk = sdk;
568
+ }
569
+ async createOrder(token, redeemAmount, collateralAsset, collateralAmount, options) {
570
+ const address = await this.sdk.getAddress();
571
+ const orderId = uuidv42();
572
+ const expiry = Math.floor(Date.now() / 1e3) + (options?.expiryMinutes || 5) * 60;
573
+ const minterAddress = token.mintingContract;
574
+ const order = {
575
+ orderId,
576
+ orderType: 1,
577
+ expiry,
578
+ nonce: Date.now(),
579
+ benefactor: options?.benefactor || address,
580
+ beneficiary: options?.beneficiary || address,
581
+ collateralAsset,
582
+ collateralAmount: collateralAmount.toString(),
583
+ dAssetAmount: redeemAmount.toString(),
584
+ minterAddress
585
+ };
586
+ return order;
587
+ }
588
+ async signOrder(order) {
589
+ const signer = this.sdk.signer;
590
+ const domain = {
591
+ name: "DeployMinting",
592
+ version: "1",
593
+ chainId: await this.sdk.getChainId(),
594
+ verifyingContract: order.minterAddress
595
+ };
596
+ const value = {
597
+ order_id: order.orderId,
598
+ order_type: order.orderType,
599
+ expiry: order.expiry,
600
+ nonce: order.nonce,
601
+ benefactor: order.benefactor,
602
+ beneficiary: order.beneficiary,
603
+ collateral_asset: order.collateralAsset,
604
+ collateral_amount: order.collateralAmount,
605
+ dAsset_amount: order.dAssetAmount
606
+ };
607
+ try {
608
+ const signature = await signer._signTypedData(domain, EIP712_TYPES_ORDER, value);
609
+ return signature;
610
+ } catch (error) {
611
+ throw new DeploySDKError(
612
+ "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
613
+ "Failed to sign redeem order",
614
+ error
615
+ );
616
+ }
617
+ }
618
+ async submitOrder(order, signature) {
619
+ try {
620
+ const response = await fetch(`${this.sdk.config.apiUrl}/api/redeem`, {
621
+ method: "POST",
622
+ headers: {
623
+ "Content-Type": "application/json"
624
+ },
625
+ body: JSON.stringify({
626
+ order: {
627
+ order_id: order.orderId,
628
+ order_type: order.orderType,
629
+ expiry: order.expiry,
630
+ nonce: order.nonce,
631
+ benefactor: order.benefactor,
632
+ beneficiary: order.beneficiary,
633
+ collateral_asset: order.collateralAsset,
634
+ collateral_amount: order.collateralAmount,
635
+ dAsset_amount: order.dAssetAmount
636
+ },
637
+ signature: {
638
+ signature_type: 0,
639
+ signature_bytes: signature
640
+ }
641
+ })
642
+ });
643
+ if (!response.ok) {
644
+ const error = await response.json();
645
+ throw new DeploySDKError(
646
+ "API_ERROR" /* API_ERROR */,
647
+ error.message || "Failed to submit redeem order"
648
+ );
649
+ }
650
+ const result = await response.json();
651
+ return {
652
+ success: true,
653
+ orderId: order.orderId,
654
+ txHash: result.txHash,
655
+ status: result.status
656
+ };
657
+ } catch (error) {
658
+ if (error instanceof DeploySDKError) throw error;
659
+ throw new DeploySDKError(
660
+ "API_ERROR" /* API_ERROR */,
661
+ "Failed to submit redeem order",
662
+ error
663
+ );
664
+ }
665
+ }
666
+ async redeem(token, redeemAmount, collateralAsset, collateralAmount, options) {
667
+ try {
668
+ const order = await this.createOrder(
669
+ token,
670
+ redeemAmount,
671
+ collateralAsset,
672
+ collateralAmount,
673
+ options
674
+ );
675
+ const signature = await this.signOrder(order);
676
+ return await this.submitOrder(order, signature);
677
+ } catch (error) {
678
+ if (error instanceof DeploySDKError) throw error;
679
+ throw new DeploySDKError(
680
+ "REDEEM_FAILED" /* REDEEM_FAILED */,
681
+ "Failed to redeem tokens",
682
+ error
683
+ );
684
+ }
685
+ }
686
+ async estimateGas(token, redeemAmount, collateralAsset, collateralAmount, signature) {
687
+ const minterContract = new Contract4(
688
+ token.mintingContract,
689
+ MINTER_ABI,
690
+ this.sdk.provider
691
+ );
692
+ const order = {
693
+ order_id: uuidv42(),
694
+ order_type: 1,
695
+ expiry: Math.floor(Date.now() / 1e3) + 300,
696
+ nonce: Date.now(),
697
+ benefactor: await this.sdk.getAddress(),
698
+ beneficiary: await this.sdk.getAddress(),
699
+ collateral_asset: collateralAsset,
700
+ collateral_amount: collateralAmount.toString(),
701
+ dAsset_amount: redeemAmount.toString()
702
+ };
703
+ try {
704
+ const gasEstimate = await minterContract.estimateGas.redeem(
705
+ order,
706
+ { signature_type: 0, signature_bytes: signature }
707
+ );
708
+ return gasEstimate.toBigInt();
709
+ } catch (error) {
710
+ throw new DeploySDKError(
711
+ "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
712
+ "Failed to estimate gas for redeem",
713
+ error
714
+ );
715
+ }
716
+ }
717
+ };
718
+
719
+ export {
720
+ ErrorCode,
721
+ DeploySDKError,
722
+ CONTRACT_ADDRESSES,
723
+ COLLATERAL_ASSETS,
724
+ STAKE_TOKENS,
725
+ EIP712_TYPES_ORDER,
726
+ ERC4626_ABI,
727
+ ERC20_ABI,
728
+ MINTER_ABI,
729
+ MintModule,
730
+ StakeModule,
731
+ UnstakeModule,
732
+ RedeemModule
733
+ };