From f67c28a635f3f6f9b3b4129a7bc103f3f0694d2b Mon Sep 17 00:00:00 2001 From: Marcelo Morgado Date: Mon, 25 May 2020 21:37:43 +0100 Subject: [PATCH 1/7] Aave test cases --- docs/aave.md | 161 +++++++++++++++++++++++++++- docs/overview_mainnet_address.md | 2 +- src/aave/contracts.ts | 34 ++++++ tests/aave.test.ts | 176 +++++++++++++++++++++++++++++++ 4 files changed, 367 insertions(+), 6 deletions(-) create mode 100644 tests/aave.test.ts diff --git a/docs/aave.md b/docs/aave.md index a0ac7b0..c75fd78 100644 --- a/docs/aave.md +++ b/docs/aave.md @@ -5,6 +5,7 @@ _Special thanks to [mrdavey](https://github.com/mrdavey/) for his [ez-flashloan example](https://github.com/mrdavey/ez-flashloan)._ Flashloans are a bit tricky as they require you deploy a smart contract before you can start ultilizing it. The current standard way to interact with flashloans is by: + 1. Deploying a smart contract with specific logic that will return you a profit (e.g. arbitrage, liquidating acounts). 2. Interacting with the application specific smart contract from step 1. @@ -13,7 +14,8 @@ One thing to note about flashloan supported smart contracts is that they can get ### Flashloan Logic (Solidity) Your smart contract will need to inherit from `FlashLoanReceiverBase` and have two functions: -1. An entrypoint function where __you__ call to initiate the flashloan (`initateFlashLoan` in the example below). + +1. An entrypoint function where **you** call to initiate the flashloan (`initateFlashLoan` in the example below). 2. A callback function called `executeOperation` that contains the action logic to perform once the loan is given to us. ```js @@ -98,14 +100,14 @@ const contractWithFlashLoanAddress = const contractWithFlashLoan = new ethers.Contract( contractWithFlashLoanAddress, ContractWithFlashLoanArtifact.abi, - wallet + wallet, ); const main = async () => { // Encoding our custom data const myCustomDataEncoded = ethers.utils.defaultAbiCoder.encode( ["address", "uint"], - ["0x0000000000000000000000000000000000000000", 42] + ["0x0000000000000000000000000000000000000000", 42], ); const tx = await contractWithFlashLoan.initateFlashLoan( @@ -115,8 +117,157 @@ const main = async () => { myCustomDataEncoded, // _params encoded { gasLimit: 4000000, - } + }, ); await tx.wait(); }; -``` \ No newline at end of file +``` + +## Examples (JavaScript) + +### Supplying/Borrowing Tokens + +```js +// ../tests/aave.test.ts#L43-L62 + +test("lend 10 ETH (i.e. mint aETH)", async () => { + // given + const ethToLend = 10; + const before = await aEthContract.balanceOf(wallet.address); + + // when + const { address: reserveAddress } = erc20.eth; + const amount = parseEther(ethToLend.toString()); + const referralCode = "0"; + await lendingPool.deposit(reserveAddress, amount, referralCode, { + gasLimit: 1500000, + value: amount, + }); + + // then + const after = await aEthContract.balanceOf(wallet.address); + + const ethLended = parseFloat(fromWei(after.sub(before))); + expect(ethLended).toBeCloseTo(ethToLend); +}); +``` + +```js +// ../tests/aave.test.ts#L64-L85 + +test("borrow 20 DAI", async () => { + // given + const before = await daiContract.balanceOf(wallet.address); + + // when + const { address: reserveAddress } = erc20.dai; + const amount = parseEther("20"); + const interestRateMode = 1; // 1 = STABLE RATE, 2 = VARIABLE RATE + const referralCode = "0"; + await lendingPool.borrow( + reserveAddress, + amount, + interestRateMode, + referralCode, + { gasLimit: 1500000 }, + ); + + // then + const after = await daiContract.balanceOf(wallet.address); + const daiBorrowed = parseFloat(fromWei(after.sub(before))); + expect(daiBorrowed).toBe(20); +}); +``` + +### Retrieve Supply/Borrow Balance + +```js +// ../tests/aave.test.ts#L111-L121 + +test("get supply/borrow balances for DAI", async () => { + // when + const { + currentATokenBalance: daiLended, + currentBorrowBalance: daiBorrowed, + } = await lendingPool.getUserReserveData(erc20.dai.address, wallet.address); + + // then + expect(parseFloat(fromWei(daiBorrowed))).toBeCloseTo(20); + expect(parseFloat(fromWei(daiLended))).toBeCloseTo(5); +}); +``` + +### Withdraw Supply + +```js +// ../tests/aave.test.ts#L123-L139 + +test("withdraw 1 ETH from collateral", async () => { + // given + const ethBefore = await wallet.getBalance(); + const ethToRedeem = 1; + const ethToRedeemInWei = parseEther(ethToRedeem.toString()); + + // when + await aEthContract.redeem(ethToRedeemInWei, { + gasLimit: 1500000, + }); + + // then + const ethAfter = await wallet.getBalance(); + + const ethGained = parseFloat(fromWei(ethAfter.sub(ethBefore))); + expect(ethGained).toBeCloseTo(ethToRedeem, 1); +}); +``` + +### Repay Debt + +```js +// ../tests/aave.test.ts#L141-L165 + +test("repay 1 DAI of debt", async () => { + // given + const daiToRepay = 1; + const daiToRepayInWei = parseEther(daiToRepay.toString()); + + const daiBefore = await daiContract.balanceOf(wallet.address); + + // when + await daiContract.approve(aave.LendingPoolCore.address, daiToRepayInWei); + + await lendingPool.repay( + erc20.dai.address, + daiToRepayInWei, + wallet.address, + { + gasLimit: 1500000, + }, + ); + + // then + const daiAfter = await daiContract.balanceOf(wallet.address); + + const daiSpent = parseFloat(fromWei(daiBefore.sub(daiAfter))); + expect(daiSpent).toBe(daiToRepay); +}); +``` + +### Retrieve Health Factor + +The health factor should be > 1 otherwise the user's positions can be liquidated. +See more: https://docs.aave.com/developers/developing-on-aave/the-protocol/lendingpool#liquidationcall + +```js +// ../tests/aave.test.ts#L167-L175 + +test("retrieve current health factor", async () => { + // when + const { healthFactor } = await lendingPool.getUserAccountData( + wallet.address, + ); + + // then + expect(parseFloat(fromWei(healthFactor))).toBeGreaterThan(1); +}); +``` diff --git a/docs/overview_mainnet_address.md b/docs/overview_mainnet_address.md index 55204fe..978ae89 100644 --- a/docs/overview_mainnet_address.md +++ b/docs/overview_mainnet_address.md @@ -40,7 +40,7 @@ - cWBTC: [0xc11b1268c1a384e55c48c2391d8d480264a3a7f4](https://etherscan.io/address/0xc11b1268c1a384e55c48c2391d8d480264a3a7f4) - cZRX: [0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407](https://etherscan.io/address/0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407) - comptroller: [0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b](https://etherscan.io/address/0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b) - - priceOracle: [0x1d8aedc9e924730dd3f9641cdb4d1b92b848b4bd](https://etherscan.io/address/0x1d8aedc9e924730dd3f9641cdb4d1b92b848b4bd) + - priceOracle: [0xDDc46a3B076aec7ab3Fc37420A8eDd2959764Ec4](https://etherscan.io/address/0xDDc46a3B076aec7ab3Fc37420A8eDd2959764Ec4) ## Curvefi diff --git a/src/aave/contracts.ts b/src/aave/contracts.ts index 64bdf49..658e3a1 100644 --- a/src/aave/contracts.ts +++ b/src/aave/contracts.ts @@ -19,54 +19,88 @@ const contracts = { }, aETH: { address: "0x3a3a65aab0dd2a17e3f1947ba16138cd37d08c04", + abi: ATokenAbi, + decimals: 18, }, aDAI: { address: "0xfc1e690f61efd961294b3e1ce3313fbd8aa4f85d", + abi: ATokenAbi, + decimals: 18, }, aUSDC: { address: "0x9ba00d6856a4edf4665bca2c2309936572473b7e", + abi: ATokenAbi, + decimals: 6, }, aSUSD: { address: "0x625ae63000f46200499120b906716420bd059240", + abi: ATokenAbi, + decimals: 18, }, aTUSD: { address: "0x4da9b813057d04baef4e5800e36083717b4a0341", + abi: ATokenAbi, + decimals: 18, }, aUSDT: { address: "0x71fc860f7d3a592a4a98740e39db31d25db65ae8", + abi: ATokenAbi, + decimals: 6, }, aBUSD: { address: "0x6ee0f7bb50a54ab5253da0667b0dc2ee526c30a8", + abi: ATokenAbi, + decimals: 18, }, aBAT: { address: "0xe1ba0fb44ccb0d11b80f92f4f8ed94ca3ff51d00", + abi: ATokenAbi, + decimals: 18, }, aKNC: { address: "0x9d91be44c06d373a8a226e1f3b146956083803eb", + abi: ATokenAbi, + decimals: 18, }, aLEND: { address: "0x7d2d3688df45ce7c552e19c27e007673da9204b8", + abi: ATokenAbi, + decimals: 18, }, aLINK: { address: "0xa64bd6c70cb9051f6a9ba1f163fdc07e0dfb5f84", + abi: ATokenAbi, + decimals: 18, }, aMANA: { address: "0x6fce4a401b6b80ace52baaefe4421bd188e76f6f", + abi: ATokenAbi, + decimals: 18, }, aMKR: { address: "0x7deb5e830be29f91e298ba5ff1356bb7f8146998", + abi: ATokenAbi, + decimals: 18, }, aREP: { address: "0x71010a9d003445ac60c4e6a7017c1e89a477b438", + abi: ATokenAbi, + decimals: 18, }, aSNX: { address: "0x328c4c80bc7aca0834db37e6600a6c49e12da4de", + abi: ATokenAbi, + decimals: 18, }, aWBTC: { address: "0xfc4b8ed459e00e5400be803a9bb3954234fd50e3", + abi: ATokenAbi, + decimals: 8, }, aZRX: { address: "0x6fb0855c404e09c47c3fbca25f08d4e41f9f062f", + abi: ATokenAbi, + decimals: 18, }, }; diff --git a/tests/aave.test.ts b/tests/aave.test.ts new file mode 100644 index 0000000..972361b --- /dev/null +++ b/tests/aave.test.ts @@ -0,0 +1,176 @@ +jest.setTimeout(100000); + +import { Wallet, Contract, ethers } from "ethers"; + +// import legos +import erc20 from "../src/erc20"; +import aave from "../src/aave"; +import { fromWei } from "./utils"; +import { parseUnits } from "ethers/utils"; + +const { parseEther, bigNumberify } = ethers.utils; + +describe("aave", () => { + let wallet: Wallet; + let daiContract: Contract; + let aEthContract: Contract; + let lendingPool: Contract; + let aDaiContract: Contract; + + beforeAll(async () => { + ethers.errors.setLogLevel("error"); + + // @ts-ignore + wallet = global.wallet; + daiContract = new ethers.Contract(erc20.dai.address, erc20.abi, wallet); + aEthContract = new ethers.Contract( + aave.aETH.address, + aave.aETH.abi, + wallet, + ); + aDaiContract = new ethers.Contract( + aave.aDAI.address, + aave.aDAI.abi, + wallet, + ); + lendingPool = new ethers.Contract( + aave.LendingPool.address, + aave.LendingPool.abi, + wallet, + ); + }); + + test("lend 10 ETH (i.e. mint aETH)", async () => { + // given + const ethToLend = 10; + const before = await aEthContract.balanceOf(wallet.address); + + // when + const { address: reserveAddress } = erc20.eth; + const amount = parseEther(ethToLend.toString()); + const referralCode = "0"; + await lendingPool.deposit(reserveAddress, amount, referralCode, { + gasLimit: 1500000, + value: amount, + }); + + // then + const after = await aEthContract.balanceOf(wallet.address); + + const ethLended = parseFloat(fromWei(after.sub(before))); + expect(ethLended).toBeCloseTo(ethToLend); + }); + + test("borrow 20 DAI", async () => { + // given + const before = await daiContract.balanceOf(wallet.address); + + // when + const { address: reserveAddress } = erc20.dai; + const amount = parseEther("20"); + const interestRateMode = 1; // 1 = STABLE RATE, 2 = VARIABLE RATE + const referralCode = "0"; + await lendingPool.borrow( + reserveAddress, + amount, + interestRateMode, + referralCode, + { gasLimit: 1500000 }, + ); + + // then + const after = await daiContract.balanceOf(wallet.address); + const daiBorrowed = parseFloat(fromWei(after.sub(before))); + expect(daiBorrowed).toBe(20); + }); + + test("lend 5 DAI", async () => { + // given + const daiToLend = 5; + const daiToLendInWei = parseEther(daiToLend.toString()); + + const aDaiBefore = await aDaiContract.balanceOf(wallet.address); + + // when + await daiContract.approve(aave.LendingPoolCore.address, daiToLendInWei); + + const { address: reserveAddress } = erc20.dai; + const amount = daiToLendInWei; + const referralCode = "0"; + await lendingPool.deposit(reserveAddress, amount, referralCode, { + gasLimit: 1500000, + }); + + // then + const aDaiAfter = await aDaiContract.balanceOf(wallet.address); + + const daiLended = parseFloat(fromWei(aDaiAfter.sub(aDaiBefore))); + expect(daiLended).toBeCloseTo(daiToLend); + }); + + test("get supply/borrow balances for DAI", async () => { + // when + const { + currentATokenBalance: daiLended, + currentBorrowBalance: daiBorrowed, + } = await lendingPool.getUserReserveData(erc20.dai.address, wallet.address); + + // then + expect(parseFloat(fromWei(daiBorrowed))).toBeCloseTo(20); + expect(parseFloat(fromWei(daiLended))).toBeCloseTo(5); + }); + + test("withdraw 1 ETH from collateral", async () => { + // given + const ethBefore = await wallet.getBalance(); + const ethToRedeem = 1; + const ethToRedeemInWei = parseEther(ethToRedeem.toString()); + + // when + await aEthContract.redeem(ethToRedeemInWei, { + gasLimit: 1500000, + }); + + // then + const ethAfter = await wallet.getBalance(); + + const ethGained = parseFloat(fromWei(ethAfter.sub(ethBefore))); + expect(ethGained).toBeCloseTo(ethToRedeem, 1); + }); + + test("repay 1 DAI of debt", async () => { + // given + const daiToRepay = 1; + const daiToRepayInWei = parseEther(daiToRepay.toString()); + + const daiBefore = await daiContract.balanceOf(wallet.address); + + // when + await daiContract.approve(aave.LendingPoolCore.address, daiToRepayInWei); + + await lendingPool.repay( + erc20.dai.address, + daiToRepayInWei, + wallet.address, + { + gasLimit: 1500000, + }, + ); + + // then + const daiAfter = await daiContract.balanceOf(wallet.address); + + const daiSpent = parseFloat(fromWei(daiBefore.sub(daiAfter))); + expect(daiSpent).toBe(daiToRepay); + }); + + test("retrieve current health factor", async () => { + // when + const { healthFactor } = await lendingPool.getUserAccountData( + wallet.address, + ); + + // then + expect(parseFloat(fromWei(healthFactor))).toBeGreaterThan(1); + }); +}); From 3e32f41551fc68432801bc489944e36400f38908 Mon Sep 17 00:00:00 2001 From: Kris Urbas Date: Wed, 27 May 2020 14:04:19 +0200 Subject: [PATCH 2/7] add Idle v3 --- docs/README.md | 4 +- docs/_sidebar.md | 1 + docs/idle.md | 63 ++ docs/overview_mainnet_address.md | 18 + scripts/genAddrMainnetOverview.js | 6 +- src/idle/abi/IdleTokenV3.json | 1228 +++++++++++++++++++++++++++++ src/idle/contracts.ts | 26 + src/idle/index.ts | 8 + src/index.ts | 10 +- 9 files changed, 1356 insertions(+), 8 deletions(-) create mode 100644 docs/idle.md create mode 100644 src/idle/abi/IdleTokenV3.json create mode 100644 src/idle/contracts.ts create mode 100644 src/idle/index.ts diff --git a/docs/README.md b/docs/README.md index 668124a..29f904c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -28,7 +28,9 @@ - DappSys - DyDx - ERC20 +- Idle V3 +- Kyber.Network - MakerDAO - OneSplit +- UMA - Uniswap v1 -- Kyber.Network diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 97147d5..def0315 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -10,6 +10,7 @@ - [Compound](compound.md) - [CurveFi](curvefi.md) - [DyDx](dydx.md) + - [Idle V3](idle.md) - [Kyber Network](kyber.md) - [Maker](maker.md) - [OneSplit](onesplit.md) diff --git a/docs/idle.md b/docs/idle.md new file mode 100644 index 0000000..cd45e8d --- /dev/null +++ b/docs/idle.md @@ -0,0 +1,63 @@ +# Idle (V3) + +[Official Idle documentation](https://developers.idle.finance/) + +## Examples + +Import `@studydefi/money-legos/idle` package + +```js +const idle = require("@studydefi/money-legos/idle"); +``` + +List of all available contracts + +```js +idle.maxYield.dai.address; +idle.maxYield.usdc.address; +idle.maxYield.usdt.address; + +idle.riskAdjusted.dai.address; +idle.riskAdjusted.usdc.address; +idle.riskAdjusted.usdt.address; + +idle.abi; // the same abi for each idle v3 contract + +idle.decimals; // idle mints ERC-20 tokens +``` + +### JavaScript + +#### `mintIdleToken` + +```js +const { ethers } = require("ethers"); +const erc20 = require("@studydefi/money-legos/erc20"); +const idle = require("@studydefi/money-legos/idle"); + +const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545"); +const wallet = new ethers.Wallet(process.env.GANACHE_PRIV_KEY, provider); + +// init contracts +const daiContract = new ethers.Contract(erc20.dai.address, erc20.abi, wallet); +const idleContract = new ethers.Contract( + idle.maxYield.dai.address, + idle.abi, + wallet, +); + +// approve Idle to spend your DAI +const daiBalanceWei = await daiContract.balanceOf(wallet.address); +await daiContract.approve(idle.maxYield.dai.address, daiBalanceWei); + +// mint idleDAIYield +await idleContract.mintIdleToken(daiBalanceWei, true, { + gasLimit: 4000000, +}); + +// check idleDAI balance +const idleDaiBalance = await idleContract.balanceOf(wallet.address); +console.log( + `idleDAI: ${ethers.utils.formatUnits(idleDaiBalance, idle.decimals)}`, +); +``` diff --git a/docs/overview_mainnet_address.md b/docs/overview_mainnet_address.md index 978ae89..93c780f 100644 --- a/docs/overview_mainnet_address.md +++ b/docs/overview_mainnet_address.md @@ -105,6 +105,24 @@ - weth: [0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2](https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) - zrx: [0xE41d2489571d322189246DaFA5ebDe1F4699F498](https://etherscan.io/address/0xE41d2489571d322189246DaFA5ebDe1F4699F498) +## Idle + +[Link to ABIs](https://github.com/studydefi/money-legos/tree/master/src/idle/abi) + +#### maxYield + + + - dai: [0x78751b12da02728f467a44eac40f5cbc16bd7934](https://etherscan.io/address/0x78751b12da02728f467a44eac40f5cbc16bd7934) + - usdc: [0x12B98C621E8754Ae70d0fDbBC73D6208bC3e3cA6](https://etherscan.io/address/0x12B98C621E8754Ae70d0fDbBC73D6208bC3e3cA6) + - usdt: [0x63D27B3DA94A9E871222CB0A32232674B02D2f2D](https://etherscan.io/address/0x63D27B3DA94A9E871222CB0A32232674B02D2f2D) + +#### riskAdjusted + + + - dai: [0x1846bdfDB6A0f5c473dEc610144513bd071999fB](https://etherscan.io/address/0x1846bdfDB6A0f5c473dEc610144513bd071999fB) + - usdc: [0xcDdB1Bceb7a1979C6caa0229820707429dd3Ec6C](https://etherscan.io/address/0xcDdB1Bceb7a1979C6caa0229820707429dd3Ec6C) + - usdt: [0x42740698959761baf1b06baa51efbd88cb1d862b](https://etherscan.io/address/0x42740698959761baf1b06baa51efbd88cb1d862b) + ## Kyber [Link to ABIs](https://github.com/studydefi/money-legos/tree/master/src/kyber/abi) diff --git a/scripts/genAddrMainnetOverview.js b/scripts/genAddrMainnetOverview.js index fe0220b..2f05e49 100644 --- a/scripts/genAddrMainnetOverview.js +++ b/scripts/genAddrMainnetOverview.js @@ -7,7 +7,7 @@ const formatToEtherscanLink = (l) => // Funky protocols with different structures // Need to construct the markdown a bit differently -const funkyProtocols = ["curvefi"]; +const funkyProtocols = ["curvefi", "idle"]; const noRenderProtocols = ["dappsys"]; // Generated markdown @@ -28,8 +28,8 @@ Object.keys(legos) markdown.push({ link: { - title: 'Link to ABIs', - source: `https://github.com/studydefi/money-legos/tree/master/src/${curDefiProtocol}/abi` + title: "Link to ABIs", + source: `https://github.com/studydefi/money-legos/tree/master/src/${curDefiProtocol}/abi`, }, }); diff --git a/src/idle/abi/IdleTokenV3.json b/src/idle/abi/IdleTokenV3.json new file mode 100644 index 0000000..9156e65 --- /dev/null +++ b/src/idle/abi/IdleTokenV3.json @@ -0,0 +1,1228 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_cToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_iToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_rebalancer", + "type": "address" + }, + { + "internalType": "address", + "name": "_priceCalculator", + "type": "address" + }, + { + "internalType": "address", + "name": "_idleCompound", + "type": "address" + }, + { + "internalType": "address", + "name": "_idleFulcrum", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "PauserAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "PauserRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "addPauser", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allAvailableTokens", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "gst2", + "outputs": [ + { + "internalType": "contract GasToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "iToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isNewProtocolDelayed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isPauser", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isRiskAdjusted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastAllocations", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastITokenPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "manualPlay", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "priceCalculator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "protocolWrappers", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rebalancer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "releaseTimes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renouncePauser", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "tokenDecimals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "unpause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userAvgPrices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rebalancer", + "type": "address" + } + ], + "name": "setRebalancer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_priceCalculator", + "type": "address" + } + ], + "name": "setPriceCalculator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_wrapper", + "type": "address" + } + ], + "name": "setProtocolWrapper", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bool", + "name": "_manualPlay", + "type": "bool" + } + ], + "name": "setManualPlay", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bool", + "name": "_isRiskAdjusted", + "type": "bool" + } + ], + "name": "setIsRiskAdjusted", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "delayNewProtocols", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeAddress", + "type": "address" + } + ], + "name": "setFeeAddress", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256[]", + "name": "_amounts", + "type": "uint256[]" + } + ], + "name": "setGasParams", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "tokenPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAPRs", + "outputs": [ + { + "internalType": "address[]", + "name": "addresses", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "aprs", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAvgAPR", + "outputs": [ + { + "internalType": "uint256", + "name": "avgApr", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_skipWholeRebalance", + "type": "bool" + } + ], + "name": "mintIdleToken", + "outputs": [ + { + "internalType": "uint256", + "name": "mintedTokens", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "name": "mintIdleToken", + "outputs": [ + { + "internalType": "uint256", + "name": "mintedTokens", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_skipRebalance", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "name": "redeemIdleToken", + "outputs": [ + { + "internalType": "uint256", + "name": "redeemedTokens", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "redeemInterestBearingTokens", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256[]", + "name": "_newAllocations", + "type": "uint256[]" + } + ], + "name": "openRebalance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "avgApr", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "rebalanceWithGST", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "rebalance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "name": "rebalance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentAllocations", + "outputs": [ + { + "internalType": "address[]", + "name": "tokenAddresses", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/idle/contracts.ts b/src/idle/contracts.ts new file mode 100644 index 0000000..81df729 --- /dev/null +++ b/src/idle/contracts.ts @@ -0,0 +1,26 @@ +const contracts = { + maxYield: { + dai: { + address: "0x78751b12da02728f467a44eac40f5cbc16bd7934", + }, + usdc: { + address: "0x12B98C621E8754Ae70d0fDbBC73D6208bC3e3cA6", + }, + usdt: { + address: "0x63D27B3DA94A9E871222CB0A32232674B02D2f2D", + }, + }, + riskAdjusted: { + dai: { + address: "0x1846bdfDB6A0f5c473dEc610144513bd071999fB", + }, + usdc: { + address: "0xcDdB1Bceb7a1979C6caa0229820707429dd3Ec6C", + }, + usdt: { + address: "0x42740698959761baf1b06baa51efbd88cb1d862b", + }, + }, +}; + +export default contracts; diff --git a/src/idle/index.ts b/src/idle/index.ts new file mode 100644 index 0000000..643e2b6 --- /dev/null +++ b/src/idle/index.ts @@ -0,0 +1,8 @@ +import { default as contracts } from "./contracts"; +import abi from "./abi/IdleTokenV3.json"; + +export default { + ...contracts, + abi, + decimals: 18, +}; diff --git a/src/index.ts b/src/index.ts index 51a0f74..4b71d97 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,25 +1,27 @@ import { default as aave } from "./aave"; +import { default as compound } from "./compound"; import { default as curvefi } from "./curvefi"; import { default as dappsys } from "./dappsys"; import { default as dydx } from "./dydx"; import { default as erc20 } from "./erc20"; -import { default as compound } from "./compound"; +import { default as idle } from "./idle"; +import { default as kyber } from "./kyber"; import { default as maker } from "./maker"; import { default as onesplit } from "./onesplit"; import { default as uma } from "./uma"; import { default as uniswap } from "./uniswap"; -import { default as kyber } from "./kyber"; export const legos = { aave, + compound, curvefi, dappsys, dydx, erc20, - compound, + idle, + kyber, maker, onesplit, uma, uniswap, - kyber, }; From 548b6143ef017992855b080d2566f7eeb5a50826 Mon Sep 17 00:00:00 2001 From: Adrian Li Date: Wed, 27 May 2020 09:22:14 -0400 Subject: [PATCH 3/7] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fdae91..ec8d563 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,12 @@ Protocols supported: - DappSys - DyDx - ERC20 +- Idle V3 +- Kyber.Network - MakerDAO - OneSplit +- UMA Protocol - Uniswap v1 -- Kyber.Network Importing specific protocols is also supported: From 276664ee4be8eb016d19fda7c9fbecf26a7e42a7 Mon Sep 17 00:00:00 2001 From: Adrian Li Date: Wed, 27 May 2020 09:32:39 -0400 Subject: [PATCH 4/7] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 684c556..1cd2ee2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@studydefi/money-legos", - "version": "2.1.3", + "version": "2.2.0", "main": "index.js", "types": "index.d.ts", "repository": "git@github.com:studydefi/money-legos.git", From fecc6c763b5a6900ff289e10f642d9a98e853c09 Mon Sep 17 00:00:00 2001 From: Kris Urbas Date: Wed, 27 May 2020 16:54:08 +0200 Subject: [PATCH 5/7] fix exports and improve kyber docs --- docs/kyber.md | 26 ++++++++++---------------- src/idle/index.ts | 2 +- src/kyber/index.ts | 2 +- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/docs/kyber.md b/docs/kyber.md index 9d97166..b14f742 100644 --- a/docs/kyber.md +++ b/docs/kyber.md @@ -44,9 +44,7 @@ contract KyberNetworkProxy is KyberNetworkProxyInterface, SimpleNetworkInterface ```js const { ethers } = require("ethers"); -const { getLegosFor, networks } = require("@studydefi/money-legos"); - -const legos = getLegosFor(networks.mainnet); +const kyber = require("@studydefi/money-legos/kyber"); const provider = new ethers.providers.JsonRpcProvider( process.env.PROVIDER_URL || "http://localhost:8545", @@ -69,20 +67,16 @@ const swapOnKyber = async (fromAddress, toAddress, fromAmountWei) => { const minConversionRate = 1; const kyberNetwork = new ethers.Contract( - legos.kyber.contracts.network.address, - legos.kyber.contracts.factnetworkry.abi, + kyber.network.address, + kyber.network.abi, wallet, ); // ERC20 contract - const fromTokenContract = new ethers.Contract( - fromAddress, - legos.erc20.contracts.abi, - wallet, - ); + const fromTokenContract = new ethers.Contract(fromAddress, erc20.abi, wallet); // ETH -> Token - if (fromAddress === legos.erc20.contracts.eth.address) { + if (fromAddress === erc20.eth.address) { return kyberNetwork.swapEtherToToken(toAddress, minConversionRate, { gasLimit, value: fromAmountWei, @@ -93,7 +87,7 @@ const swapOnKyber = async (fromAddress, toAddress, fromAmountWei) => { await fromTokenContract.approve(kyberNetwork.address, fromAmountWei); // Token -> ETH - if (toAddress === legos.erc20.contracts.eth.address) { + if (toAddress === erc20.eth.address) { return fromExchangeContract.swapTokenToEther( fromAddress, fromAmountWei, @@ -125,7 +119,7 @@ const swapAndLog = async (fromToken, toToken, amount) => { ethers.utils.parseUnits(amount.toString(), fromToken.decimals), ); - if (toToken === legos.erc20.contracts.eth) { + if (toToken === erc20.eth) { const ethBalWei = await wallet.getBalance(); console.log( `${toToken.symbol} balance: ${ethers.utils.formatEther(ethBalWei)}`, @@ -145,9 +139,9 @@ const swapAndLog = async (fromToken, toToken, amount) => { }; const main = async () => { - await swapAndLog(legos.erc20.contracts.eth, legos.erc20.contracts.dai, 1); - await swapAndLog(legos.erc20.contracts.dai, legos.erc20.contracts.rep, 50); - await swapAndLog(legos.erc20.contracts.rep, legos.erc20.contracts.eth, 2); + await swapAndLog(erc20.eth, erc20.dai, 1); + await swapAndLog(erc20.dai, erc20.rep, 50); + await swapAndLog(erc20.rep, erc20.eth, 2); }; main(); diff --git a/src/idle/index.ts b/src/idle/index.ts index 643e2b6..57a2bd7 100644 --- a/src/idle/index.ts +++ b/src/idle/index.ts @@ -1,7 +1,7 @@ import { default as contracts } from "./contracts"; import abi from "./abi/IdleTokenV3.json"; -export default { +export = { ...contracts, abi, decimals: 18, diff --git a/src/kyber/index.ts b/src/kyber/index.ts index 0b557fa..e9a8a7a 100644 --- a/src/kyber/index.ts +++ b/src/kyber/index.ts @@ -1,5 +1,5 @@ import { default as contracts } from "./contracts"; -export default { +export = { ...contracts, }; From e0edb79bc738bd97db93b99fb89abcffcbce19fb Mon Sep 17 00:00:00 2001 From: Kris Urbas Date: Wed, 27 May 2020 17:02:18 +0200 Subject: [PATCH 6/7] fix example for kyber --- docs/kyber.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/kyber.md b/docs/kyber.md index b14f742..1280650 100644 --- a/docs/kyber.md +++ b/docs/kyber.md @@ -44,6 +44,7 @@ contract KyberNetworkProxy is KyberNetworkProxyInterface, SimpleNetworkInterface ```js const { ethers } = require("ethers"); +const erc20 = require("@studydefi/money-legos/erc20"); const kyber = require("@studydefi/money-legos/kyber"); const provider = new ethers.providers.JsonRpcProvider( From 2fe8b6ef2ec0567b03d2ab63123aa0b6d3982b57 Mon Sep 17 00:00:00 2001 From: Adrian Li Date: Wed, 27 May 2020 11:15:40 -0400 Subject: [PATCH 7/7] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1cd2ee2..ba98232 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@studydefi/money-legos", - "version": "2.2.0", + "version": "2.2.1", "main": "index.js", "types": "index.d.ts", "repository": "git@github.com:studydefi/money-legos.git",