@curvefi/api 1.6.1 → 1.7.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.
package/README.md CHANGED
@@ -1,13 +1,223 @@
1
1
  # Curve JS
2
2
 
3
+ ## Setup
4
+
5
+ Install from npm:
6
+
7
+ `npm install @curvefi/api`
8
+
9
+ ## Init
10
+ ```ts
11
+ import curve from "@curvefi/api";
12
+
13
+ (async () => {
14
+ // 1. Dev
15
+ await curve.init('JsonRpc', {url: 'http://localhost:8545/', privateKey: ''}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0, chainId: 1 });
16
+ // OR
17
+ await curve.init('JsonRpc', {}, { chainId: 1 }); // In this case fee data will be specified automatically
18
+
19
+ // 2. Infura
20
+ curve.init("Infura", { network: "homestead", apiKey: <INFURA_KEY> }, { chainId: 1 });
21
+
22
+ // 3. Web3 provider
23
+ curve.init('Web3', { externalProvider: <WEB3_PROVIDER> }, { chainId: 1 });
24
+ })()
25
+ ```
26
+ **Note 1.** ```chainId``` parameter is optional, but you must specify it in the case you use Metamask on localhost network, because Metamask has that [bug](https://hardhat.org/metamask-issue.html)
27
+
28
+ **Note 2.** Web3 init requires the address. Therefore, it can be initialized only after receiving the address.
29
+
30
+ **Wrong ❌️**
31
+ ```tsx
32
+ import type { FunctionComponent } from 'react'
33
+ import { useState, useMemo } from 'react'
34
+ import { providers } from 'ethers'
35
+ import Onboard from 'bnc-onboard'
36
+ import type { Wallet } from 'bnc-onboard/dist/src/interfaces'
37
+ import curve from '@curvefi/api'
38
+
39
+ ...
40
+
41
+ const WalletProvider: FunctionComponent = ({ children }) => {
42
+ const [wallet, setWallet] = useState<Wallet>()
43
+ const [provider, setProvider] = useState<providers.Web3Provider>()
44
+ const [address, setAddress] = useState<string>()
45
+
46
+ const networkId = 1
47
+
48
+ const onboard = useMemo(
49
+ () =>
50
+ Onboard({
51
+ dappId: DAPP_ID,
52
+ networkId,
53
+
54
+ subscriptions: {
55
+ address: (address) => {
56
+ setAddress(address)
57
+ },
58
+
59
+ wallet: (wallet) => {
60
+ setWallet(wallet)
61
+ if (wallet.provider) {
62
+ curve.init("Web3", { externalProvider: wallet.provider }, { chainId: networkId })
63
+ }
64
+ },
65
+ },
66
+ walletSelect: {
67
+ wallets: wallets,
68
+ },
69
+ }),
70
+ []
71
+ )
72
+
73
+ ...
74
+ ```
75
+
76
+ **Right ✔️**
77
+ ```tsx
78
+ import type { FunctionComponent } from 'react'
79
+ import { useState, useMemo, useEffect } from 'react'
80
+ import { providers } from 'ethers'
81
+ import Onboard from 'bnc-onboard'
82
+ import type { Wallet } from 'bnc-onboard/dist/src/interfaces'
83
+ import curve from '@curvefi/api'
84
+
85
+ ...
86
+
87
+ const WalletProvider: FunctionComponent = ({ children }) => {
88
+ const [wallet, setWallet] = useState<Wallet>()
89
+ const [provider, setProvider] = useState<providers.Web3Provider>()
90
+ const [address, setAddress] = useState<string>()
91
+
92
+ const networkId = 1
93
+
94
+ const onboard = useMemo(
95
+ () =>
96
+ Onboard({
97
+ dappId: DAPP_ID,
98
+ networkId,
99
+
100
+ subscriptions: {
101
+ address: (address) => {
102
+ setAddress(address)
103
+ },
104
+
105
+ wallet: (wallet) => {
106
+ setWallet(wallet)
107
+ },
108
+ },
109
+ walletSelect: {
110
+ wallets: wallets,
111
+ },
112
+ }),
113
+ []
114
+ )
115
+
116
+ useEffect(() => {
117
+ if (address && wallet?.provider) {
118
+ curve.init("Web3", { externalProvider: wallet.provider }, { chainId: networkId })
119
+ }
120
+ }, [address, wallet?.provider]);
121
+
122
+ ...
123
+ ```
124
+
125
+ ## Balances
126
+ ```ts
127
+ import curve from "@curvefi/api";
128
+
129
+ (async () => {
130
+ await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0, chainId: 1 });
131
+
132
+ console.log(await curve.getBalances(['DAI', 'sUSD']));
133
+ // OR console.log(await curve.getBalances(['0x6B175474E89094C44Da98b954EedeAC495271d0F', '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51']));
134
+
135
+ // [ '10000.0', '10000.0' ]
136
+
137
+ console.log(await curve.getBalances(['aDAI', 'aSUSD']));
138
+ // OR console.log(await curve.getBalances(['0x028171bCA77440897B824Ca71D1c56caC55b68A3', '0x6c5024cd4f8a59110119c56f8933403a539555eb']));
139
+
140
+ // [ '10000.000211315200513239', '10000.0' ]
141
+
142
+
143
+ // --- Pool ---
144
+
145
+ const saave = new curve.Pool('saave');
146
+
147
+
148
+ // 1. Current address balances (signer balances)
149
+
150
+ console.log(await saave.balances());
151
+ // {
152
+ // lpToken: '0.0',
153
+ // gauge: '0.0',
154
+ // DAI: '10000.0',
155
+ // sUSD: '10000.0',
156
+ // aDAI: '10000.000211315200513239',
157
+ // aSUSD: '10000.0'
158
+ // }
159
+
160
+ console.log(await saave.lpTokenBalances());
161
+ // { lpToken: '0.0', gauge: '0.0' }
162
+
163
+ console.log(await saave.underlyingCoinBalances());
164
+ // { DAI: '10000.0', sUSD: '10000.0' }
165
+
166
+ console.log(await saave.coinBalances());
167
+ // { aDAI: '10000.000211315200513239', aSUSD: '10000.0' }
168
+
169
+ console.log(await saave.allCoinBalances());
170
+ // {
171
+ // DAI: '10000.0',
172
+ // sUSD: '10000.0',
173
+ // aDAI: '10000.000211315200513239',
174
+ // aSUSD: '10000.0'
175
+ // }
176
+
177
+
178
+ // 2. For every method above you can specify the address
179
+
180
+ console.log(await saave.balances("0x0063046686E46Dc6F15918b61AE2B121458534a5"));
181
+ // {
182
+ // lpToken: '0.0',
183
+ // gauge: '0.0',
184
+ // DAI: '0.0',
185
+ // sUSD: '0.0',
186
+ // aDAI: '0.0',
187
+ // aSUSD: '0.0'
188
+ // }
189
+
190
+ // Or several addresses
191
+ console.log(await saave.balances("0x0063046686E46Dc6F15918b61AE2B121458534a5", "0x66aB6D9362d4F35596279692F0251Db635165871"));
192
+ // {
193
+ // '0x0063046686E46Dc6F15918b61AE2B121458534a5': {
194
+ // lpToken: '0.0',
195
+ // gauge: '0.0',
196
+ // DAI: '0.0',
197
+ // sUSD: '0.0',
198
+ // aDAI: '0.0',
199
+ // aSUSD: '0.0'
200
+ // },
201
+ // '0x66aB6D9362d4F35596279692F0251Db635165871': {
202
+ // lpToken: '0.0',
203
+ // gauge: '0.0',
204
+ // DAI: '10000.0',
205
+ // sUSD: '10000.0',
206
+ // aDAI: '10000.000211315200513239',
207
+ // aSUSD: '10000.0'
208
+ // }
209
+ // }
210
+
211
+ })()
212
+ ```
213
+
3
214
  ## Add/remove liquidity
4
215
 
5
216
  ```ts
6
- import curve from "curve";
217
+ import curve from "@curvefi/api";
7
218
 
8
219
  (async () => {
9
- await curve.init('JsonRpc', {url: 'http://localhost:8545/', privateKey: ''}, { gasPrice: 0, chainId: 1 });
10
- // OR await curve.init('JsonRpc', {}, { gasPrice: 0, chainId: 1 });
220
+ await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0, chainId: 1 });
11
221
 
12
222
  const pool = new curve.Pool('aave');
13
223
  console.log(pool.underlyingCoins); // [ 'DAI', 'USDC', 'USDT' ]
@@ -208,8 +418,10 @@ import curve from "curve";
208
418
  ## Exchange using all pools
209
419
 
210
420
  ```ts
421
+ import curve from "@curvefi/api";
422
+
211
423
  (async () => {
212
- await curve.init('JsonRpc', {}, { gasPrice: 0, chainId: 1 });
424
+ await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0, chainId: 1 });
213
425
 
214
426
  console.log(await curve.getBalances(['DAI', 'USDC']));
215
427
  // [ '1000.0', '0.0' ]
@@ -233,8 +445,10 @@ import curve from "curve";
233
445
  ## Cross-Asset Exchange
234
446
 
235
447
  ```ts
448
+ import curve from "@curvefi/api";
449
+
236
450
  (async () => {
237
- await curve.init('JsonRpc', {}, { gasPrice: 0, chainId: 1 });
451
+ await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0, chainId: 1 });
238
452
 
239
453
  console.log(await curve.getBalances(['DAI', 'WBTC']));
240
454
  // [ '1000.0', '0.0' ]
@@ -257,8 +471,10 @@ import curve from "curve";
257
471
 
258
472
  ## Boosting
259
473
  ```ts
260
- const boostingTest = async () => {
261
- await curve.init('JsonRpc', {}, { gasPrice: 0, chainId: 1 });
474
+ import curve from "@curvefi/api";
475
+
476
+ (async () => {
477
+ await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0, chainId: 1 });
262
478
 
263
479
  console.log(await curve.boosting.getCrv());
264
480
  // 100000.0
@@ -286,5 +502,122 @@ const boostingTest = async () => {
286
502
  // { lockedAmount: '1500.0', unlockTime: 1688601600000 }
287
503
  // 746.262271689452535192 veCRV
288
504
  // 0.000018613852077810 veCRV %
289
- }
505
+ })()
506
+ ```
507
+
508
+ ## Allowance and approve
509
+ ### General methods
510
+ ```ts
511
+ const spender = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7" // 3pool swap address
512
+
513
+ await curve.getAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], curve.signerAddress, spender)
514
+ // [ '0.0', '0.0' ]
515
+ await curve.hasAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], ['1000', '1000'], curve.signerAddress, spender)
516
+ // false
517
+ await curve.ensureAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], ['1000', '1000'], spender)
518
+ // [
519
+ // '0xb0cada2a2983dc0ed85a26916d32b9caefe45fecde47640bd7d0e214ff22aed3',
520
+ // '0x00ea7d827b3ad50ce933e96c579810cd7e70d66a034a86ec4e1e10005634d041'
521
+ // ]
522
+
523
+ ```
524
+
525
+ ### Pools
526
+ ```ts
527
+ const pool = new curve.Pool('usdn');
528
+
529
+ // --- Add Liquidity ---
530
+
531
+ await pool.addLiquidityIsApproved(["1000", "1000", "1000", "1000"])
532
+ // false
533
+ await pool.addLiquidityApprove(["1000", "1000", "1000", "1000"])
534
+ // [
535
+ // '0xbac4b0271ad340488a8135dda2f9adf3e3c402361b514f483ba2b7e9cafbdc21',
536
+ // '0x39fe196a52d9fb649f9c099fbd40ae773d28c457195c878ecdb7cd05be0f6512',
537
+ // '0xf39ebfb4b11434b879f951a08a1c633a038425c35eae09b2b7015816d068de3c',
538
+ // '0xa8b1631384da247efe1987b56fe010b852fc1d38e4d71d204c7dc5448a3a6c96'
539
+ // ]
540
+
541
+
542
+ // --- Add Liquidity Wrapped ---
543
+
544
+ await pool.addLiquidityWrappedIsApproved(["1000", "1000"])
545
+ // false
546
+ await pool.addLiquidityWrappedApprove(["1000", "1000"])
547
+ // [
548
+ // '0xe486bfba5e9e8190be580ad528707876136e6b0c201e228db0f3bd82e51619fa',
549
+ // '0xd56f7d583b20f4f7760510cc4310e3651f7dab8c276fe3bcde7e7200d65ed0dd'
550
+ // ]
551
+
552
+
553
+ // --- Remove Liquidity ---
554
+
555
+ await pool.removeLiquidityIsApproved("1000")
556
+ await pool.removeLiquidityApprove("1000")
557
+
558
+
559
+ // --- Remove Liquidity Imbalance ---
560
+
561
+ await pool.removeLiquidityImbalanceIsApproved(["1000", "1000", "1000", "1000"])
562
+ await pool.removeLiquidityImbalanceApprove(["1000", "1000", "1000", "1000"])
563
+
564
+
565
+ // --- Remove Liquidity One Coin ---
566
+
567
+ await pool.removeLiquidityOneCoinIsApproved("1000")
568
+ await pool.removeLiquidityOneCoinApprove("1000")
569
+
570
+
571
+ // --- Gauge Deposit ---
572
+
573
+ await pool.gaugeDepositIsApproved("1000")
574
+ await pool.gaugeDepositApprove("1000")
575
+
576
+
577
+ // --- Exchange ---
578
+
579
+ await pool.exchangeIsApproved("DAI", "1000")
580
+ await pool.exchangeApprove("DAI", "1000")
581
+
582
+
583
+ // --- Exchange Tricrypto ---
584
+
585
+ await pool.exchangeIsApproved(0, "1000")
586
+ await pool.exchangeApprove(0, "1000")
587
+
588
+
589
+ // --- Exchange Wrapped ---
590
+
591
+ await pool.exchangeWrappedIsApproved("0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", "1000")
592
+ await pool.exchangeWrappedApprove("0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", "1000")
593
+ ```
594
+ **Note.** Removing wrapped does not require approve.
595
+
596
+ ### Exchange
597
+ ```ts
598
+ await curve.exchangeisApproved("DAI", "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3", "1000"); // DAI -> MIM
599
+ await curve.exchangeApprove("DAI", "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3", "1000"); // DAI -> MIM
600
+ ```
601
+
602
+ ### Boosting
603
+ ```ts
604
+ await curve.boosting.isApproved('1000')
605
+ await curve.boosting.approve('1000')
606
+ ```
607
+
608
+ ## Gas estimation
609
+ Every non-constant method has corresponding gas estimation method. Rule: ```obj.method -> obj.estimateGas.method```
610
+
611
+ **Examples**
612
+ ```ts
613
+ const spender = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7" // 3pool swap address
614
+ await curve.estimateGas.ensureAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], curve.signerAddress, spender);
615
+
616
+ const pool = new curve.Pool('usdn');
617
+ await pool.estimateGas.addLiquidityApprove(["1000", "1000", "1000", "1000"])
618
+ await pool.estimateGas.addLiquidity(["1000", "1000", "1000", "1000"])
619
+
620
+ await curve.estimateGas.crossAssetExchange('DAI', "WBTC", "1000", 0.01)
621
+
622
+ await curve.boosting.estimateGas.createLock('1000', 365)
290
623
  ```
package/lib/boosting.d.ts CHANGED
@@ -9,6 +9,9 @@ export declare const getLockedAmountAndUnlockTime: (...addresses: string[] | str
9
9
  }>;
10
10
  export declare const getVeCrv: (...addresses: string[] | string[][]) => Promise<DictInterface<string> | string>;
11
11
  export declare const getVeCrvPct: (...addresses: string[] | string[][]) => Promise<DictInterface<string> | string>;
12
+ export declare const isApproved: (amount: string) => Promise<boolean>;
13
+ export declare const approveEstimateGas: (amount: string) => Promise<number>;
14
+ export declare const approve: (amount: string) => Promise<string[]>;
12
15
  export declare const createLockEstimateGas: (amount: string, days: number) => Promise<number>;
13
16
  export declare const createLock: (amount: string, days: number) => Promise<string>;
14
17
  export declare const increaseAmountEstimateGas: (amount: string) => Promise<number>;
package/lib/boosting.js CHANGED
@@ -47,7 +47,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
47
47
  }
48
48
  };
49
49
  Object.defineProperty(exports, "__esModule", { value: true });
50
- exports.withdrawLockedCrv = exports.withdrawLockedCrvEstimateGas = exports.increaseUnlockTime = exports.increaseUnlockTimeEstimateGas = exports.increaseAmount = exports.increaseAmountEstimateGas = exports.createLock = exports.createLockEstimateGas = exports.getVeCrvPct = exports.getVeCrv = exports.getLockedAmountAndUnlockTime = exports.getCrv = void 0;
50
+ exports.withdrawLockedCrv = exports.withdrawLockedCrvEstimateGas = exports.increaseUnlockTime = exports.increaseUnlockTimeEstimateGas = exports.increaseAmount = exports.increaseAmountEstimateGas = exports.createLock = exports.createLockEstimateGas = exports.approve = exports.approveEstimateGas = exports.isApproved = exports.getVeCrvPct = exports.getVeCrv = exports.getLockedAmountAndUnlockTime = exports.getCrv = void 0;
51
51
  var ethers_1 = require("ethers");
52
52
  var utils_1 = require("./utils");
53
53
  var utils_2 = require("./utils");
@@ -164,6 +164,33 @@ var getVeCrvPct = function () {
164
164
  });
165
165
  };
166
166
  exports.getVeCrvPct = getVeCrvPct;
167
+ var isApproved = function (amount) { return __awaiter(void 0, void 0, void 0, function () {
168
+ return __generator(this, function (_a) {
169
+ switch (_a.label) {
170
+ case 0: return [4 /*yield*/, (0, utils_1.hasAllowance)([curve_1.ALIASES.crv], [amount], curve_1.curve.signerAddress, curve_1.ALIASES.voting_escrow)];
171
+ case 1: return [2 /*return*/, _a.sent()];
172
+ }
173
+ });
174
+ }); };
175
+ exports.isApproved = isApproved;
176
+ var approveEstimateGas = function (amount) { return __awaiter(void 0, void 0, void 0, function () {
177
+ return __generator(this, function (_a) {
178
+ switch (_a.label) {
179
+ case 0: return [4 /*yield*/, (0, utils_1.ensureAllowanceEstimateGas)([curve_1.ALIASES.crv], [amount], curve_1.ALIASES.voting_escrow)];
180
+ case 1: return [2 /*return*/, _a.sent()];
181
+ }
182
+ });
183
+ }); };
184
+ exports.approveEstimateGas = approveEstimateGas;
185
+ var approve = function (amount) { return __awaiter(void 0, void 0, void 0, function () {
186
+ return __generator(this, function (_a) {
187
+ switch (_a.label) {
188
+ case 0: return [4 /*yield*/, (0, utils_1.ensureAllowance)([curve_1.ALIASES.crv], [amount], curve_1.ALIASES.voting_escrow)];
189
+ case 1: return [2 /*return*/, _a.sent()];
190
+ }
191
+ });
192
+ }); };
193
+ exports.approve = approve;
167
194
  var createLockEstimateGas = function (amount, days) { return __awaiter(void 0, void 0, void 0, function () {
168
195
  var crvBalance, _amount, unlockTime;
169
196
  return __generator(this, function (_a) {
package/lib/index.d.ts CHANGED
@@ -34,6 +34,8 @@ declare const curve: {
34
34
  output: string;
35
35
  }>;
36
36
  exchangeExpected: (inputCoin: string, outputCoin: string, amount: string) => Promise<string>;
37
+ exchangeIsApproved: (inputCoin: string, outputCoin: string, amount: string) => Promise<boolean>;
38
+ exchangeApprove: (inputCoin: string, outputCoin: string, amount: string) => Promise<string[]>;
37
39
  exchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
38
40
  crossAssetExchangeAvailable: (inputCoin: string, outputCoin: string) => Promise<boolean>;
39
41
  crossAssetExchangeOutputAndSlippage: (inputCoin: string, outputCoin: string, amount: string) => Promise<{
@@ -41,10 +43,14 @@ declare const curve: {
41
43
  output: string;
42
44
  }>;
43
45
  crossAssetExchangeExpected: (inputCoin: string, outputCoin: string, amount: string) => Promise<string>;
46
+ crossAssetExchangeIsApproved: (inputCoin: string, amount: string) => Promise<boolean>;
47
+ crossAssetExchangeApprove: (inputCoin: string, amount: string) => Promise<string[]>;
44
48
  crossAssetExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
45
49
  estimateGas: {
46
50
  ensureAllowance: (coins: string[], amounts: string[], spender: string) => Promise<number>;
51
+ exchangeApprove: (inputCoin: string, outputCoin: string, amount: string) => Promise<number>;
47
52
  exchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<number>;
53
+ crossAssetExchangeApprove: (inputCoin: string, amount: string) => Promise<number>;
48
54
  crossAssetExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<number>;
49
55
  };
50
56
  boosting: {
@@ -58,11 +64,14 @@ declare const curve: {
58
64
  }>;
59
65
  getVeCrv: (...addresses: string[] | string[][]) => Promise<string | import("./interfaces").DictInterface<string>>;
60
66
  getVeCrvPct: (...addresses: string[] | string[][]) => Promise<string | import("./interfaces").DictInterface<string>>;
67
+ isApproved: (amount: string) => Promise<boolean>;
68
+ approve: (amount: string) => Promise<string[]>;
61
69
  createLock: (amount: string, days: number) => Promise<string>;
62
70
  increaseAmount: (amount: string) => Promise<string>;
63
71
  increaseUnlockTime: (days: number) => Promise<string>;
64
72
  withdrawLockedCrv: () => Promise<string>;
65
73
  estimateGas: {
74
+ approve: (amount: string) => Promise<number>;
66
75
  createLock: (amount: string, days: number) => Promise<number>;
67
76
  increaseAmount: (amount: string) => Promise<number>;
68
77
  increaseUnlockTime: (days: number) => Promise<number>;
package/lib/index.js CHANGED
@@ -69,14 +69,20 @@ var curve = {
69
69
  ensureAllowance: utils_1.ensureAllowance,
70
70
  getBestPoolAndOutput: pools_1.getBestPoolAndOutput,
71
71
  exchangeExpected: pools_1.exchangeExpected,
72
+ exchangeIsApproved: pools_1.exchangeIsApproved,
73
+ exchangeApprove: pools_1.exchangeApprove,
72
74
  exchange: pools_1.exchange,
73
75
  crossAssetExchangeAvailable: pools_1.crossAssetExchangeAvailable,
74
76
  crossAssetExchangeOutputAndSlippage: pools_1.crossAssetExchangeOutputAndSlippage,
75
77
  crossAssetExchangeExpected: pools_1.crossAssetExchangeExpected,
78
+ crossAssetExchangeIsApproved: pools_1.crossAssetExchangeIsApproved,
79
+ crossAssetExchangeApprove: pools_1.crossAssetExchangeApprove,
76
80
  crossAssetExchange: pools_1.crossAssetExchange,
77
81
  estimateGas: {
78
82
  ensureAllowance: utils_1.ensureAllowanceEstimateGas,
83
+ exchangeApprove: pools_1.exchangeApproveEstimateGas,
79
84
  exchange: pools_1.exchangeEstimateGas,
85
+ crossAssetExchangeApprove: pools_1.crossAssetExchangeApproveEstimateGas,
80
86
  crossAssetExchange: pools_1.crossAssetExchangeEstimateGas,
81
87
  },
82
88
  boosting: {
@@ -84,11 +90,14 @@ var curve = {
84
90
  getLockedAmountAndUnlockTime: boosting_1.getLockedAmountAndUnlockTime,
85
91
  getVeCrv: boosting_1.getVeCrv,
86
92
  getVeCrvPct: boosting_1.getVeCrvPct,
93
+ isApproved: boosting_1.isApproved,
94
+ approve: boosting_1.approve,
87
95
  createLock: boosting_1.createLock,
88
96
  increaseAmount: boosting_1.increaseAmount,
89
97
  increaseUnlockTime: boosting_1.increaseUnlockTime,
90
98
  withdrawLockedCrv: boosting_1.withdrawLockedCrv,
91
99
  estimateGas: {
100
+ approve: boosting_1.approveEstimateGas,
92
101
  createLock: boosting_1.createLockEstimateGas,
93
102
  increaseAmount: boosting_1.increaseAmountEstimateGas,
94
103
  increaseUnlockTime: boosting_1.increaseUnlockTimeEstimateGas,
package/lib/pools.d.ts CHANGED
@@ -172,6 +172,9 @@ export declare const getBestPoolAndOutput: (inputCoin: string, outputCoin: strin
172
172
  output: string;
173
173
  }>;
174
174
  export declare const exchangeExpected: (inputCoin: string, outputCoin: string, amount: string) => Promise<string>;
175
+ export declare const exchangeIsApproved: (inputCoin: string, outputCoin: string, amount: string) => Promise<boolean>;
176
+ export declare const exchangeApproveEstimateGas: (inputCoin: string, outputCoin: string, amount: string) => Promise<number>;
177
+ export declare const exchangeApprove: (inputCoin: string, outputCoin: string, amount: string) => Promise<string[]>;
175
178
  export declare const exchangeEstimateGas: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<number>;
176
179
  export declare const exchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
177
180
  export declare const crossAssetExchangeAvailable: (inputCoin: string, outputCoin: string) => Promise<boolean>;
@@ -187,5 +190,8 @@ export declare const crossAssetExchangeOutputAndSlippage: (inputCoin: string, ou
187
190
  output: string;
188
191
  }>;
189
192
  export declare const crossAssetExchangeExpected: (inputCoin: string, outputCoin: string, amount: string) => Promise<string>;
193
+ export declare const crossAssetExchangeIsApproved: (inputCoin: string, amount: string) => Promise<boolean>;
194
+ export declare const crossAssetExchangeApproveEstimateGas: (inputCoin: string, amount: string) => Promise<number>;
195
+ export declare const crossAssetExchangeApprove: (inputCoin: string, amount: string) => Promise<string[]>;
190
196
  export declare const crossAssetExchangeEstimateGas: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<number>;
191
197
  export declare const crossAssetExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
package/lib/pools.js CHANGED
@@ -59,7 +59,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
59
59
  return (mod && mod.__esModule) ? mod : { "default": mod };
60
60
  };
61
61
  Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.crossAssetExchange = exports.crossAssetExchangeEstimateGas = exports.crossAssetExchangeExpected = exports.crossAssetExchangeOutputAndSlippage = exports._crossAssetExchangeInfo = exports._getSmallAmountForCoin = exports.crossAssetExchangeAvailable = exports.exchange = exports.exchangeEstimateGas = exports.exchangeExpected = exports.getBestPoolAndOutput = exports._getBestPoolAndOutput = exports.Pool = void 0;
62
+ exports.crossAssetExchange = exports.crossAssetExchangeEstimateGas = exports.crossAssetExchangeApprove = exports.crossAssetExchangeApproveEstimateGas = exports.crossAssetExchangeIsApproved = exports.crossAssetExchangeExpected = exports.crossAssetExchangeOutputAndSlippage = exports._crossAssetExchangeInfo = exports._getSmallAmountForCoin = exports.crossAssetExchangeAvailable = exports.exchange = exports.exchangeEstimateGas = exports.exchangeApprove = exports.exchangeApproveEstimateGas = exports.exchangeIsApproved = exports.exchangeExpected = exports.getBestPoolAndOutput = exports._getBestPoolAndOutput = exports.Pool = void 0;
63
63
  var ethers_1 = require("ethers");
64
64
  var utils_1 = require("./utils");
65
65
  var registry_exchange_json_1 = __importDefault(require("./constants/abis/json/registry_exchange.json"));
@@ -1489,7 +1489,7 @@ var Pool = /** @class */ (function () {
1489
1489
  return __generator(this, function (_a) {
1490
1490
  switch (_a.label) {
1491
1491
  case 0:
1492
- i = this._getCoinIdx(inputCoin);
1492
+ i = this._getCoinIdx(inputCoin, false);
1493
1493
  return [4 /*yield*/, (0, utils_1.hasAllowance)([this.coinAddresses[i]], [amount], curve_1.curve.signerAddress, this.swap)];
1494
1494
  case 1: return [2 /*return*/, _a.sent()];
1495
1495
  }
@@ -1500,7 +1500,7 @@ var Pool = /** @class */ (function () {
1500
1500
  return __generator(this, function (_a) {
1501
1501
  switch (_a.label) {
1502
1502
  case 0:
1503
- i = this._getCoinIdx(inputCoin);
1503
+ i = this._getCoinIdx(inputCoin, false);
1504
1504
  return [4 /*yield*/, (0, utils_1.ensureAllowanceEstimateGas)([this.coinAddresses[i]], [amount], this.swap)];
1505
1505
  case 1: return [2 /*return*/, _a.sent()];
1506
1506
  }
@@ -1511,7 +1511,7 @@ var Pool = /** @class */ (function () {
1511
1511
  return __generator(this, function (_a) {
1512
1512
  switch (_a.label) {
1513
1513
  case 0:
1514
- i = this._getCoinIdx(inputCoin);
1514
+ i = this._getCoinIdx(inputCoin, false);
1515
1515
  return [4 /*yield*/, (0, utils_1.ensureAllowance)([this.coinAddresses[i]], [amount], this.swap)];
1516
1516
  case 1: return [2 /*return*/, _a.sent()];
1517
1517
  }
@@ -1741,8 +1741,11 @@ var Pool = /** @class */ (function () {
1741
1741
  }
1742
1742
  return idx_1;
1743
1743
  }
1744
- var lowerCaseCoins = useUnderlying ? _this.underlyingCoins.map(function (c) { return c.toLowerCase(); }) : _this.coins.map(function (c) { return c.toLowerCase(); });
1745
- var idx = lowerCaseCoins.indexOf(coin.toLowerCase());
1744
+ var coinAddress = (0, utils_1._getCoinAddresses)(coin)[0];
1745
+ var lowerCaseCoinAddresses = useUnderlying ?
1746
+ _this.underlyingCoinAddresses.map(function (c) { return c.toLowerCase(); }) :
1747
+ _this.coinAddresses.map(function (c) { return c.toLowerCase(); });
1748
+ var idx = lowerCaseCoinAddresses.indexOf(coinAddress.toLowerCase());
1746
1749
  if (idx === -1) {
1747
1750
  throw Error("There is no " + coin + " in " + _this.name + " pool");
1748
1751
  }
@@ -1912,13 +1915,13 @@ var Pool = /** @class */ (function () {
1912
1915
  var poolBalancesRatios = poolBalances.map(function (b) { return b / poolBalances.reduce(function (a, b) { return a + b; }); });
1913
1916
  // Cross factors for each wallet balance used as reference to see the
1914
1917
  // max that can be used according to the lowest relative wallet balance
1915
- var balancesAmountsForEachScenario = walletBalances.map(function (_, i) { return (walletBalances.map(function (_, j) { return (poolBalancesRatios[j] * walletBalances[i] / poolBalancesRatios[i]); })); });
1916
- var firstCoinBalanceForEachScenario = balancesAmountsForEachScenario.map(function (_a) {
1918
+ var balancedAmountsForEachScenario = walletBalances.map(function (_, i) { return (walletBalances.map(function (_, j) { return (poolBalancesRatios[j] * walletBalances[i] / poolBalancesRatios[i]); })); });
1919
+ var firstCoinBalanceForEachScenario = balancedAmountsForEachScenario.map(function (_a) {
1917
1920
  var a = _a[0];
1918
1921
  return a;
1919
1922
  });
1920
1923
  var scenarioWithLowestBalances = firstCoinBalanceForEachScenario.indexOf(Math.min.apply(Math, firstCoinBalanceForEachScenario));
1921
- return balancesAmountsForEachScenario[scenarioWithLowestBalances].map(function (a, i) { return a.toFixed(decimals[i]); });
1924
+ return balancedAmountsForEachScenario[scenarioWithLowestBalances].map(function (a, i) { return a.toFixed(decimals[i]); });
1922
1925
  };
1923
1926
  this._calcLpTokenAmount = function (_amounts, isDeposit) {
1924
1927
  if (isDeposit === void 0) { isDeposit = true; }
@@ -2674,6 +2677,34 @@ var _getBestPoolAndOutput = function (inputCoinAddress, outputCoinAddress, input
2674
2677
  });
2675
2678
  }); };
2676
2679
  exports._getBestPoolAndOutput = _getBestPoolAndOutput;
2680
+ var _getExchangeData = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2681
+ var _a, inputCoinAddress, outputCoinAddress, inputCoinDecimals, addressProviderContract, registryAddress, registryContract, poolAddress, poolName, _c, _i, _j, isUnderlying, i, j;
2682
+ return __generator(this, function (_d) {
2683
+ switch (_d.label) {
2684
+ case 0:
2685
+ _a = (0, utils_1._getCoinAddresses)(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
2686
+ inputCoinDecimals = (0, utils_1._getCoinDecimals)(inputCoinAddress)[0];
2687
+ addressProviderContract = curve_1.curve.contracts[curve_1.ALIASES.address_provider].contract;
2688
+ return [4 /*yield*/, addressProviderContract.get_registry()];
2689
+ case 1:
2690
+ registryAddress = _d.sent();
2691
+ registryContract = new ethers_1.ethers.Contract(registryAddress, registry_json_1.default, curve_1.curve.signer);
2692
+ return [4 /*yield*/, (0, exports._getBestPoolAndOutput)(inputCoinAddress, outputCoinAddress, inputCoinDecimals, amount)];
2693
+ case 2:
2694
+ poolAddress = (_d.sent()).poolAddress;
2695
+ if (poolAddress === "0x0000000000000000000000000000000000000000") {
2696
+ throw new Error("This pair can't be exchanged");
2697
+ }
2698
+ poolName = (0, utils_1.getPoolNameBySwapAddress)(poolAddress);
2699
+ return [4 /*yield*/, registryContract.get_coin_indices(poolAddress, inputCoinAddress, outputCoinAddress)];
2700
+ case 3:
2701
+ _c = _d.sent(), _i = _c[0], _j = _c[1], isUnderlying = _c[2];
2702
+ i = Number(_i.toString());
2703
+ j = Number(_j.toString());
2704
+ return [2 /*return*/, [poolName, i, j, isUnderlying]];
2705
+ }
2706
+ });
2707
+ }); };
2677
2708
  var getBestPoolAndOutput = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2678
2709
  var _a, inputCoinAddress, outputCoinAddress, _c, inputCoinDecimals, outputCoinDecimals, _d, poolAddress, _output, output;
2679
2710
  return __generator(this, function (_e) {
@@ -2699,38 +2730,60 @@ var exchangeExpected = function (inputCoin, outputCoin, amount) { return __await
2699
2730
  });
2700
2731
  }); };
2701
2732
  exports.exchangeExpected = exchangeExpected;
2733
+ var exchangeIsApproved = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2734
+ var poolAddress;
2735
+ return __generator(this, function (_a) {
2736
+ switch (_a.label) {
2737
+ case 0: return [4 /*yield*/, (0, exports.getBestPoolAndOutput)(inputCoin, outputCoin, amount)];
2738
+ case 1:
2739
+ poolAddress = (_a.sent()).poolAddress;
2740
+ return [4 /*yield*/, (0, utils_1.hasAllowance)([inputCoin], [amount], curve_1.curve.signerAddress, poolAddress)];
2741
+ case 2: return [2 /*return*/, _a.sent()];
2742
+ }
2743
+ });
2744
+ }); };
2745
+ exports.exchangeIsApproved = exchangeIsApproved;
2746
+ var exchangeApproveEstimateGas = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2747
+ var poolAddress;
2748
+ return __generator(this, function (_a) {
2749
+ switch (_a.label) {
2750
+ case 0: return [4 /*yield*/, (0, exports.getBestPoolAndOutput)(inputCoin, outputCoin, amount)];
2751
+ case 1:
2752
+ poolAddress = (_a.sent()).poolAddress;
2753
+ return [4 /*yield*/, (0, utils_1.ensureAllowanceEstimateGas)([inputCoin], [amount], poolAddress)];
2754
+ case 2: return [2 /*return*/, _a.sent()];
2755
+ }
2756
+ });
2757
+ }); };
2758
+ exports.exchangeApproveEstimateGas = exchangeApproveEstimateGas;
2759
+ var exchangeApprove = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2760
+ var poolAddress;
2761
+ return __generator(this, function (_a) {
2762
+ switch (_a.label) {
2763
+ case 0: return [4 /*yield*/, (0, exports.getBestPoolAndOutput)(inputCoin, outputCoin, amount)];
2764
+ case 1:
2765
+ poolAddress = (_a.sent()).poolAddress;
2766
+ return [4 /*yield*/, (0, utils_1.ensureAllowance)([inputCoin], [amount], poolAddress)];
2767
+ case 2: return [2 /*return*/, _a.sent()];
2768
+ }
2769
+ });
2770
+ }); };
2771
+ exports.exchangeApprove = exchangeApprove;
2702
2772
  var exchangeEstimateGas = function (inputCoin, outputCoin, amount, maxSlippage) {
2703
2773
  if (maxSlippage === void 0) { maxSlippage = 0.01; }
2704
2774
  return __awaiter(void 0, void 0, void 0, function () {
2705
- var _a, inputCoinAddress, outputCoinAddress, inputCoinDecimals, addressProviderContract, registryAddress, registryContract, poolAddress, poolName, _c, _i, _j, is_underlying, i, j, pool;
2706
- return __generator(this, function (_d) {
2707
- switch (_d.label) {
2708
- case 0:
2709
- _a = (0, utils_1._getCoinAddresses)(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
2710
- inputCoinDecimals = (0, utils_1._getCoinDecimals)(inputCoinAddress)[0];
2711
- addressProviderContract = curve_1.curve.contracts[curve_1.ALIASES.address_provider].contract;
2712
- return [4 /*yield*/, addressProviderContract.get_registry()];
2775
+ var _a, poolName, i, j, isUnderlying, pool;
2776
+ return __generator(this, function (_c) {
2777
+ switch (_c.label) {
2778
+ case 0: return [4 /*yield*/, _getExchangeData(inputCoin, outputCoin, amount)];
2713
2779
  case 1:
2714
- registryAddress = _d.sent();
2715
- registryContract = new ethers_1.ethers.Contract(registryAddress, registry_json_1.default, curve_1.curve.signer);
2716
- return [4 /*yield*/, (0, exports._getBestPoolAndOutput)(inputCoinAddress, outputCoinAddress, inputCoinDecimals, amount)];
2717
- case 2:
2718
- poolAddress = (_d.sent()).poolAddress;
2719
- if (poolAddress === "0x0000000000000000000000000000000000000000") {
2720
- throw new Error("This pair can't be exchanged");
2721
- }
2722
- poolName = (0, utils_1.getPoolNameBySwapAddress)(poolAddress);
2723
- return [4 /*yield*/, registryContract.get_coin_indices(poolAddress, inputCoinAddress, outputCoinAddress)];
2724
- case 3:
2725
- _c = _d.sent(), _i = _c[0], _j = _c[1], is_underlying = _c[2];
2726
- i = Number(_i.toString());
2727
- j = Number(_j.toString());
2780
+ _a = _c.sent(), poolName = _a[0], i = _a[1], j = _a[2], isUnderlying = _a[3];
2728
2781
  pool = new Pool(poolName);
2729
- if (!is_underlying) return [3 /*break*/, 5];
2782
+ if (!isUnderlying) return [3 /*break*/, 3];
2730
2783
  return [4 /*yield*/, pool.estimateGas.exchange(i, j, amount, maxSlippage)];
2731
- case 4: return [2 /*return*/, _d.sent()];
2732
- case 5: return [4 /*yield*/, pool.estimateGas.exchangeWrapped(i, j, amount, maxSlippage)];
2733
- case 6: return [2 /*return*/, _d.sent()];
2784
+ case 2: return [2 /*return*/, _c.sent()];
2785
+ case 3: return [4 /*yield*/, pool.estimateGas.exchangeWrapped(i, j, amount, maxSlippage)];
2786
+ case 4: return [2 /*return*/, _c.sent()];
2734
2787
  }
2735
2788
  });
2736
2789
  });
@@ -2739,35 +2792,18 @@ exports.exchangeEstimateGas = exchangeEstimateGas;
2739
2792
  var exchange = function (inputCoin, outputCoin, amount, maxSlippage) {
2740
2793
  if (maxSlippage === void 0) { maxSlippage = 0.01; }
2741
2794
  return __awaiter(void 0, void 0, void 0, function () {
2742
- var _a, inputCoinAddress, outputCoinAddress, inputCoinDecimals, addressProviderContract, registryAddress, registryContract, poolAddress, poolName, _c, _i, _j, is_underlying, i, j, pool;
2743
- return __generator(this, function (_d) {
2744
- switch (_d.label) {
2745
- case 0:
2746
- _a = (0, utils_1._getCoinAddresses)(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
2747
- inputCoinDecimals = (0, utils_1._getCoinDecimals)(inputCoinAddress)[0];
2748
- addressProviderContract = curve_1.curve.contracts[curve_1.ALIASES.address_provider].contract;
2749
- return [4 /*yield*/, addressProviderContract.get_registry()];
2795
+ var _a, poolName, i, j, isUnderlying, pool;
2796
+ return __generator(this, function (_c) {
2797
+ switch (_c.label) {
2798
+ case 0: return [4 /*yield*/, _getExchangeData(inputCoin, outputCoin, amount)];
2750
2799
  case 1:
2751
- registryAddress = _d.sent();
2752
- registryContract = new ethers_1.ethers.Contract(registryAddress, registry_json_1.default, curve_1.curve.signer);
2753
- return [4 /*yield*/, (0, exports._getBestPoolAndOutput)(inputCoinAddress, outputCoinAddress, inputCoinDecimals, amount)];
2754
- case 2:
2755
- poolAddress = (_d.sent()).poolAddress;
2756
- if (poolAddress === "0x0000000000000000000000000000000000000000") {
2757
- throw new Error("This pair can't be exchanged");
2758
- }
2759
- poolName = (0, utils_1.getPoolNameBySwapAddress)(poolAddress);
2760
- return [4 /*yield*/, registryContract.get_coin_indices(poolAddress, inputCoinAddress, outputCoinAddress)];
2761
- case 3:
2762
- _c = _d.sent(), _i = _c[0], _j = _c[1], is_underlying = _c[2];
2763
- i = Number(_i.toString());
2764
- j = Number(_j.toString());
2800
+ _a = _c.sent(), poolName = _a[0], i = _a[1], j = _a[2], isUnderlying = _a[3];
2765
2801
  pool = new Pool(poolName);
2766
- if (!is_underlying) return [3 /*break*/, 5];
2802
+ if (!isUnderlying) return [3 /*break*/, 3];
2767
2803
  return [4 /*yield*/, pool.exchange(i, j, amount, maxSlippage)];
2768
- case 4: return [2 /*return*/, _d.sent()];
2769
- case 5: return [4 /*yield*/, pool.exchangeWrapped(i, j, amount, maxSlippage)];
2770
- case 6: return [2 /*return*/, _d.sent()];
2804
+ case 2: return [2 /*return*/, _c.sent()];
2805
+ case 3: return [4 /*yield*/, pool.exchangeWrapped(i, j, amount, maxSlippage)];
2806
+ case 4: return [2 /*return*/, _c.sent()];
2771
2807
  }
2772
2808
  });
2773
2809
  });
@@ -2861,6 +2897,33 @@ var crossAssetExchangeExpected = function (inputCoin, outputCoin, amount) { retu
2861
2897
  });
2862
2898
  }); };
2863
2899
  exports.crossAssetExchangeExpected = crossAssetExchangeExpected;
2900
+ var crossAssetExchangeIsApproved = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2901
+ return __generator(this, function (_a) {
2902
+ switch (_a.label) {
2903
+ case 0: return [4 /*yield*/, (0, utils_1.hasAllowance)([inputCoin], [amount], curve_1.curve.signerAddress, curve_1.ALIASES.router)];
2904
+ case 1: return [2 /*return*/, _a.sent()];
2905
+ }
2906
+ });
2907
+ }); };
2908
+ exports.crossAssetExchangeIsApproved = crossAssetExchangeIsApproved;
2909
+ var crossAssetExchangeApproveEstimateGas = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2910
+ return __generator(this, function (_a) {
2911
+ switch (_a.label) {
2912
+ case 0: return [4 /*yield*/, (0, utils_1.ensureAllowanceEstimateGas)([inputCoin], [amount], curve_1.ALIASES.router)];
2913
+ case 1: return [2 /*return*/, _a.sent()];
2914
+ }
2915
+ });
2916
+ }); };
2917
+ exports.crossAssetExchangeApproveEstimateGas = crossAssetExchangeApproveEstimateGas;
2918
+ var crossAssetExchangeApprove = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
2919
+ return __generator(this, function (_a) {
2920
+ switch (_a.label) {
2921
+ case 0: return [4 /*yield*/, (0, utils_1.ensureAllowance)([inputCoin], [amount], curve_1.ALIASES.router)];
2922
+ case 1: return [2 /*return*/, _a.sent()];
2923
+ }
2924
+ });
2925
+ }); };
2926
+ exports.crossAssetExchangeApprove = crossAssetExchangeApprove;
2864
2927
  var crossAssetExchangeEstimateGas = function (inputCoin, outputCoin, amount, maxSlippage) {
2865
2928
  if (maxSlippage === void 0) { maxSlippage = 0.02; }
2866
2929
  return __awaiter(void 0, void 0, void 0, function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curvefi/api",
3
- "version": "1.6.1",
3
+ "version": "1.7.0",
4
4
  "description": "JavaScript library for curve.fi",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {