@gearbox-protocol/sdk 8.28.4 → 8.29.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.
@@ -49,6 +49,7 @@ class AccountOpener extends import_sdk.SDKConstruct {
49
49
  #faucet;
50
50
  #poolDepositMultiplier;
51
51
  #minDebtMultiplier;
52
+ #allowMint;
52
53
  constructor(service, options_ = {}) {
53
54
  super(service.sdk);
54
55
  const {
@@ -56,9 +57,11 @@ class AccountOpener extends import_sdk.SDKConstruct {
56
57
  depositorKey,
57
58
  faucet,
58
59
  poolDepositMultiplier = 30000n,
59
- minDebtMultiplier = 10100n
60
+ minDebtMultiplier = 10100n,
61
+ allowMint = false
60
62
  } = options_;
61
63
  this.#service = service;
64
+ this.#allowMint = allowMint;
62
65
  this.#logger = (0, import_sdk.childLogger)("AccountOpener", service.sdk.logger);
63
66
  this.#anvil = (0, import_createAnvilClient.createAnvilClient)({
64
67
  chain: service.sdk.provider.chain,
@@ -244,6 +247,27 @@ class AccountOpener extends import_sdk.SDKConstruct {
244
247
  },
245
248
  "looking for open strategy"
246
249
  );
250
+ let borrowerBalance = await this.#anvil.readContract({
251
+ address: underlying,
252
+ abi: import_iERC20.ierc20Abi,
253
+ functionName: "balanceOf",
254
+ args: [borrower.address]
255
+ });
256
+ if (borrowerBalance < minDebt) {
257
+ this.#logger?.warn(
258
+ `borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} is less than the minimum debt: ${this.sdk.tokensMeta.formatBN(underlying, minDebt)}`
259
+ );
260
+ if (this.#allowMint) {
261
+ borrowerBalance = await this.#tryMint(
262
+ underlying,
263
+ borrower,
264
+ minDebt - borrowerBalance
265
+ );
266
+ }
267
+ }
268
+ this.#logger?.debug(
269
+ `borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} ${this.sdk.tokensMeta.symbol(underlying)}`
270
+ );
247
271
  const strategy = await this.sdk.routerFor(cm).findOpenStrategyPath({
248
272
  creditManager: cm.creditManager,
249
273
  expectedBalances,
@@ -359,12 +383,24 @@ class AccountOpener extends import_sdk.SDKConstruct {
359
383
  try {
360
384
  const amnt = this.sdk.tokensMeta.formatBN(pool.underlying, amount) + " " + this.sdk.tokensMeta.symbol(pool.underlying);
361
385
  this.#logger?.debug(`depositing ${amnt} into pool ${poolName}`);
362
- const allowance = await this.#anvil.readContract({
386
+ let allowance = await this.#anvil.readContract({
363
387
  address: underlying,
364
388
  abi: import_iERC20.ierc20Abi,
365
389
  functionName: "balanceOf",
366
390
  args: [depositor.address]
367
391
  });
392
+ if (allowance < amount) {
393
+ this.#logger?.warn(
394
+ `depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)} is less than the amount to deposit: ${amnt}`
395
+ );
396
+ if (this.#allowMint) {
397
+ allowance = await this.#tryMint(
398
+ underlying,
399
+ depositor,
400
+ amount - allowance
401
+ );
402
+ }
403
+ }
368
404
  this.#logger?.debug(
369
405
  `depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)}`
370
406
  );
@@ -417,6 +453,78 @@ class AccountOpener extends import_sdk.SDKConstruct {
417
453
  };
418
454
  }
419
455
  }
456
+ /**
457
+ * Tries to mint tokens, returns the balance after attempt (success or not)
458
+ * @param token
459
+ * @param dest
460
+ * @param amount
461
+ */
462
+ async #tryMint(token, dest, amount) {
463
+ const symbol = this.sdk.tokensMeta.symbol(token);
464
+ const amnt = this.sdk.tokensMeta.formatBN(token, amount);
465
+ try {
466
+ await this.#mint(token, dest, amount);
467
+ } catch (e) {
468
+ this.#logger?.warn(
469
+ `failed to mint ${amnt} ${symbol} to ${dest.address}: ${e}`
470
+ );
471
+ }
472
+ return await this.#anvil.readContract({
473
+ address: token,
474
+ abi: import_iERC20.ierc20Abi,
475
+ functionName: "balanceOf",
476
+ args: [dest.address]
477
+ });
478
+ }
479
+ async #mint(token, dest, amount) {
480
+ const symbol = this.sdk.tokensMeta.symbol(token);
481
+ const amnt = this.sdk.tokensMeta.formatBN(token, amount);
482
+ this.#logger?.warn(`minting ${amnt} ${symbol} to ${dest.address}`);
483
+ const owner = await this.#anvil.readContract({
484
+ address: token,
485
+ abi: import_abi.iOwnableAbi,
486
+ functionName: "owner"
487
+ });
488
+ this.#logger?.warn(`owner of ${symbol}: ${owner}`);
489
+ await this.#anvil.impersonateAccount({ address: owner });
490
+ await this.#anvil.setBalance({
491
+ address: owner,
492
+ value: (0, import_viem.parseEther)("100")
493
+ });
494
+ let hash = await this.#anvil.writeContract({
495
+ account: owner,
496
+ address: token,
497
+ abi: (0, import_viem.parseAbi)(["function mint(uint256 amount) external returns (bool)"]),
498
+ functionName: "mint",
499
+ args: [amount],
500
+ chain: this.#anvil.chain
501
+ });
502
+ this.#logger?.debug(`mint ${amnt} ${symbol} to ${owner} in tx ${hash}`);
503
+ let receipt = await this.#anvil.waitForTransactionReceipt({ hash });
504
+ if (receipt.status === "reverted") {
505
+ throw new Error(
506
+ `failed to mint ${amnt} ${symbol} to ${owner} in tx ${hash}: reverted`
507
+ );
508
+ }
509
+ hash = await this.#anvil.writeContract({
510
+ account: owner,
511
+ address: token,
512
+ abi: import_iERC20.ierc20Abi,
513
+ functionName: "transfer",
514
+ args: [dest.address, amount],
515
+ chain: this.#anvil.chain
516
+ });
517
+ this.#logger?.debug(
518
+ `transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}`
519
+ );
520
+ receipt = await this.#anvil.waitForTransactionReceipt({ hash });
521
+ if (receipt.status === "reverted") {
522
+ throw new Error(
523
+ `failed to transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}: reverted`
524
+ );
525
+ }
526
+ await this.#anvil.stopImpersonatingAccount({ address: owner });
527
+ }
420
528
  /**
421
529
  * Creates borrower wallet,
422
530
  * Sets ETH balance,
@@ -2,6 +2,7 @@ import {
2
2
  BaseError,
3
3
  erc20Abi,
4
4
  isAddress,
5
+ parseAbi,
5
6
  parseEther,
6
7
  parseEventLogs
7
8
  } from "viem";
@@ -19,7 +20,7 @@ import {
19
20
  SDKConstruct,
20
21
  sendRawTx
21
22
  } from "../sdk/index.js";
22
- import { iDegenNftv2Abi } from "./abi.js";
23
+ import { iDegenNftv2Abi, iOwnableAbi } from "./abi.js";
23
24
  import { claimFromFaucet } from "./claimFromFaucet.js";
24
25
  import { createAnvilClient } from "./createAnvilClient.js";
25
26
  const DIRECT_TRANSFERS_QUOTA = 10000n;
@@ -41,6 +42,7 @@ class AccountOpener extends SDKConstruct {
41
42
  #faucet;
42
43
  #poolDepositMultiplier;
43
44
  #minDebtMultiplier;
45
+ #allowMint;
44
46
  constructor(service, options_ = {}) {
45
47
  super(service.sdk);
46
48
  const {
@@ -48,9 +50,11 @@ class AccountOpener extends SDKConstruct {
48
50
  depositorKey,
49
51
  faucet,
50
52
  poolDepositMultiplier = 30000n,
51
- minDebtMultiplier = 10100n
53
+ minDebtMultiplier = 10100n,
54
+ allowMint = false
52
55
  } = options_;
53
56
  this.#service = service;
57
+ this.#allowMint = allowMint;
54
58
  this.#logger = childLogger("AccountOpener", service.sdk.logger);
55
59
  this.#anvil = createAnvilClient({
56
60
  chain: service.sdk.provider.chain,
@@ -236,6 +240,27 @@ class AccountOpener extends SDKConstruct {
236
240
  },
237
241
  "looking for open strategy"
238
242
  );
243
+ let borrowerBalance = await this.#anvil.readContract({
244
+ address: underlying,
245
+ abi: ierc20Abi,
246
+ functionName: "balanceOf",
247
+ args: [borrower.address]
248
+ });
249
+ if (borrowerBalance < minDebt) {
250
+ this.#logger?.warn(
251
+ `borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} is less than the minimum debt: ${this.sdk.tokensMeta.formatBN(underlying, minDebt)}`
252
+ );
253
+ if (this.#allowMint) {
254
+ borrowerBalance = await this.#tryMint(
255
+ underlying,
256
+ borrower,
257
+ minDebt - borrowerBalance
258
+ );
259
+ }
260
+ }
261
+ this.#logger?.debug(
262
+ `borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} ${this.sdk.tokensMeta.symbol(underlying)}`
263
+ );
239
264
  const strategy = await this.sdk.routerFor(cm).findOpenStrategyPath({
240
265
  creditManager: cm.creditManager,
241
266
  expectedBalances,
@@ -351,12 +376,24 @@ class AccountOpener extends SDKConstruct {
351
376
  try {
352
377
  const amnt = this.sdk.tokensMeta.formatBN(pool.underlying, amount) + " " + this.sdk.tokensMeta.symbol(pool.underlying);
353
378
  this.#logger?.debug(`depositing ${amnt} into pool ${poolName}`);
354
- const allowance = await this.#anvil.readContract({
379
+ let allowance = await this.#anvil.readContract({
355
380
  address: underlying,
356
381
  abi: ierc20Abi,
357
382
  functionName: "balanceOf",
358
383
  args: [depositor.address]
359
384
  });
385
+ if (allowance < amount) {
386
+ this.#logger?.warn(
387
+ `depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)} is less than the amount to deposit: ${amnt}`
388
+ );
389
+ if (this.#allowMint) {
390
+ allowance = await this.#tryMint(
391
+ underlying,
392
+ depositor,
393
+ amount - allowance
394
+ );
395
+ }
396
+ }
360
397
  this.#logger?.debug(
361
398
  `depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)}`
362
399
  );
@@ -409,6 +446,78 @@ class AccountOpener extends SDKConstruct {
409
446
  };
410
447
  }
411
448
  }
449
+ /**
450
+ * Tries to mint tokens, returns the balance after attempt (success or not)
451
+ * @param token
452
+ * @param dest
453
+ * @param amount
454
+ */
455
+ async #tryMint(token, dest, amount) {
456
+ const symbol = this.sdk.tokensMeta.symbol(token);
457
+ const amnt = this.sdk.tokensMeta.formatBN(token, amount);
458
+ try {
459
+ await this.#mint(token, dest, amount);
460
+ } catch (e) {
461
+ this.#logger?.warn(
462
+ `failed to mint ${amnt} ${symbol} to ${dest.address}: ${e}`
463
+ );
464
+ }
465
+ return await this.#anvil.readContract({
466
+ address: token,
467
+ abi: ierc20Abi,
468
+ functionName: "balanceOf",
469
+ args: [dest.address]
470
+ });
471
+ }
472
+ async #mint(token, dest, amount) {
473
+ const symbol = this.sdk.tokensMeta.symbol(token);
474
+ const amnt = this.sdk.tokensMeta.formatBN(token, amount);
475
+ this.#logger?.warn(`minting ${amnt} ${symbol} to ${dest.address}`);
476
+ const owner = await this.#anvil.readContract({
477
+ address: token,
478
+ abi: iOwnableAbi,
479
+ functionName: "owner"
480
+ });
481
+ this.#logger?.warn(`owner of ${symbol}: ${owner}`);
482
+ await this.#anvil.impersonateAccount({ address: owner });
483
+ await this.#anvil.setBalance({
484
+ address: owner,
485
+ value: parseEther("100")
486
+ });
487
+ let hash = await this.#anvil.writeContract({
488
+ account: owner,
489
+ address: token,
490
+ abi: parseAbi(["function mint(uint256 amount) external returns (bool)"]),
491
+ functionName: "mint",
492
+ args: [amount],
493
+ chain: this.#anvil.chain
494
+ });
495
+ this.#logger?.debug(`mint ${amnt} ${symbol} to ${owner} in tx ${hash}`);
496
+ let receipt = await this.#anvil.waitForTransactionReceipt({ hash });
497
+ if (receipt.status === "reverted") {
498
+ throw new Error(
499
+ `failed to mint ${amnt} ${symbol} to ${owner} in tx ${hash}: reverted`
500
+ );
501
+ }
502
+ hash = await this.#anvil.writeContract({
503
+ account: owner,
504
+ address: token,
505
+ abi: ierc20Abi,
506
+ functionName: "transfer",
507
+ args: [dest.address, amount],
508
+ chain: this.#anvil.chain
509
+ });
510
+ this.#logger?.debug(
511
+ `transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}`
512
+ );
513
+ receipt = await this.#anvil.waitForTransactionReceipt({ hash });
514
+ if (receipt.status === "reverted") {
515
+ throw new Error(
516
+ `failed to transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}: reverted`
517
+ );
518
+ }
519
+ await this.#anvil.stopImpersonatingAccount({ address: owner });
520
+ }
412
521
  /**
413
522
  * Creates borrower wallet,
414
523
  * Sets ETH balance,
@@ -12,6 +12,7 @@ export interface AccountOpenerOptions {
12
12
  depositorKey?: Hex;
13
13
  poolDepositMultiplier?: bigint | string | number;
14
14
  minDebtMultiplier?: bigint | string | number;
15
+ allowMint?: boolean;
15
16
  }
16
17
  export interface TargetAccount {
17
18
  creditManager: Address;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "8.28.4",
3
+ "version": "8.29.0",
4
4
  "description": "Gearbox SDK",
5
5
  "license": "MIT",
6
6
  "main": "./dist/cjs/sdk/index.js",