diff --git a/.env.example b/.env.example index a51288b..2a8f1f9 100644 --- a/.env.example +++ b/.env.example @@ -3,3 +3,4 @@ TEST_TIMEOUT=700000 NODE_PROVIDER_MUMBAI_RPC_URL=https://rpc.ankr.com/polygon_mumbai NODE_PROVIDER_CELO_RPC_URL=https://rpc.ankr.com/celo NODE_PROVIDER_ALFAJORES_RPC_URL=https://alfajores-forno.celo-testnet.org +TEST_TIMEOUT=500000 diff --git a/.gitignore b/.gitignore index 9364bf3..cc40c2b 100644 --- a/.gitignore +++ b/.gitignore @@ -103,4 +103,8 @@ dist # TernJS port file .tern-port -cache \ No newline at end of file +cache + +# DS Store +*./DS_Store +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index ff3c9c7..d4d654d 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ [![NPM Package](https://img.shields.io/npm/v/toucan-sdk.svg)](https://www.npmjs.com/package/toucan-sdk) +The Toucan SDK allows developers to build using Toucan's infrastructure tools on [Celo](https://celo.org/) and [Polygon](https://polygon.technology/). It provides a set of functions that allow developers to interact with Toucan Protocol's smart contracts and subgraphs. This includes redeeming of pool tokens and retirements of carbon credits, as well as querying data on projects and retirements. + A Typescript SDK for [Toucan Protocol](https://toucan.earth/). Wraps around [Ethers.js](https://docs.ethers.io/v5/). Works in the web browser and Node.js. -_Full documentation coming soon._ +For the full documentation, check our [docs](https://docs.toucan.earth/toucan/dev-resources/sdk). ⚠️ This SDK is heavily under development. USE AT YOUR OWN RISK. ⚠️ @@ -22,11 +24,39 @@ yarn add toucan-sdk # Quickstart -Instantiate the ToucanClient and set a signer & provider to interact with our infrastructure. +Instantiate the ToucanClient and set a `signer` & `provider` to interact with our infrastructure. + +We recommend using to use [ethers.js ^5.6.4](https://docs.ethers.org/v5/api/signer/) for the signer and provider. When you are considering using [wagmi](https://0.3.x.wagmi.sh/docs/hooks/useSigner), only versions under 1.0 will work as this library has not yet been upgraded to viem. + +### [ethers.js](https://docs.ethers.org/v5/api/signer/) ```typescript import ToucanClient from "toucan-sdk"; +import { ethers } from "ethers"; + +// ethers signer and provider +const provider = new ethers.providers.JsonRpcProvider( + "https://rpc.ankr.com/polygon" +); + +// make sure to set your private key in your .env file +const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider); + +// set signer & provider +const toucan = new ToucanClient("alfajores", provider, signer); +``` + +### [wagmi](https://0.3.x.wagmi.sh/docs/hooks/useSigner) + +```typescript +import { ToucanClient } from "toucan-sdk"; +import { useProvider, useSigner } from "wagmi"; +// get signer & provider +const { data: signer } = useSigner(); +const provider = useProvider(); + +// set signer & provider const toucan = new ToucanClient("alfajores", provider, signer); ``` @@ -44,7 +74,7 @@ If you don't have a signer nor a provider set, you can only interact with the su ## Fetch pool prices from a Dex -You can find pools for Toucan pool tokens on [Celo Network](https://celo.org) at [Ubeswap](https://ubeswap.org) and for [Polygon Network](https://polygon.technology) on [SushiSwap](sushi.com) +You can find pools for Toucan pool tokens on [Celo Network](https://celo.org) at [Uniswap](https://uniswap.org/) and for [Polygon Network](https://polygon.technology) on [SushiSwap](sushi.com). Something that may come in handy in your applications is fetching the USD price of our pool tokens. @@ -52,7 +82,7 @@ Something that may come in handy in your applications is fetching the USD price nctPrice = await toucan.fetchTokenPriceOnDex("NCT"); ``` -The object returned by the above method will look like so: +The object returned by the above method will look like this: ```json { @@ -65,7 +95,7 @@ The object returned by the above method will look like so: # Interact with Toucan's Contracts? -You can always access any method or property of the BCT, NCT and TCO2 contracts by first getting and storing them in a variable, like so: +You can always access any method or property of the BCT, NCT and TCO2 [contracts](https://github.com/ToucanProtocol/contracts) by first getting and storing them in a variable, like this: ```typescript toucan.setSigner(signer); @@ -78,11 +108,11 @@ const remainingTCO2 = await nct.tokenBalances(tco2Address); This is useful if you need to interact with a method of our contracts that hasn't been implemented in the SDK yet. -It's important to note that, if you want to use write methods you need to have a signer set! +It's important to note that, if you want to use write methods you need to have a signer set in your ToucanClient! ## Example to retire Carbon Credits -To retire Carbon Credits on mainnet, you will have to get Carbon Pool Tokens from a DEX like Ubeswap, which you need to redeem for TCO2s. You can then retire these and get a certificate for that. If you already own NCTs, you can follow this example. In case you don't and are developing on testnet, you can also just get some at the [Toucan Faucet](https://faucet.toucan.earth). You can find more ways to retire in our [documentation](https://docs.toucan.earth/toucan/dev-resources/smart-contracts/tco2). +To retire Carbon Credits on mainnet, you will have to get Carbon Pool Tokens from a DEX like [Uniswap](https://uniswap.org), which you need to redeem for TCO2s. You can then retire these and get a certificate for that. If you already own NCTs, you can follow this example. In case you don't and are developing on testnet, you can also just get some at the [Toucan Faucet](https://faucet.toucan.earth). You can find more ways to retire in our [documentation](https://docs.toucan.earth/toucan/dev-resources/smart-contracts/tco2). **Redeem your Pool Tokens and get an array of redeemed TCO2s** @@ -93,7 +123,7 @@ const tco2Addresses = await toucan.redeemAuto("NCT", parseEther("1")); **Retire the Carbon Credits** ```typescript -await toucan.retire(parseEther("1"), tco2addresses[0].address); +await toucan.retire(parseEther("1"), tco2Addresses[0].address); ``` # Subgraph queries @@ -112,7 +142,7 @@ That's where subgraph queries come in handy. (and we have plenty of those 😉) const tco2 = await toucan.fetchTCO2TokenByFullSymbol("TCO2-VCS-1718-2013"); ``` -The result will look like so: +The result will look like this: ```json { @@ -136,49 +166,55 @@ Now you have quite some info on the project, including its address. Toucan SDK offers a lot of pre-defined queries. Try them out! ```typescript +import { ToucanClient } from "toucan-sdk"; + +// here we don't need to set the signer or provider +const toucan = new ToucanClient("alfajores"); + // Fetch the batches of a user. -fetchUserBatches(address: string); +await toucan.fetchUserBatches(address: string, first?: number, skip?: number); -// Fetch TCO2 token by it's address to get details like name, symbol, address and projectVintage. -fetchTCO2TokenById(address: string); +// Fetch TCO2 token by its address to get details like name, symbol, address and projectVintage. +await toucan.fetchTCO2TokenById(address: string); // Fetch TCO2Token with the symbol to get details like name, symbol, address and projectVintage. A symbol would look like this: `TCO2-VCS--YYYY`. Make sure to input the full symbol. -fetchTCO2TokenByFullSymbol(symbol: string); +await toucan.fetchTCO2TokenByFullSymbol(symbol: string); // Fetch all TCO2s details like name, symbol, address and projectVintage. - -fetchAllTCO2Tokens(); +await toucan.fetchAllTCO2Tokens(first?: number, skip?: number); // Fetch all user retirements to get information like creationTX, amount, token details and certificate details. -fetchUserRetirements(address: string, first?: number, skip?: number); +await toucan.fetchUserRetirements(address: string, first?: number, skip?: number); // Fetch all redeems of a given pool to get information like amount, creator and token details. Only accepts the Pooltypes "NCT" or "BCT". -fetchRedeems(poolSymbol: Pooltypes, first?: number, skip?: number); +await toucan.fetchRedeems(poolSymbol: Pooltypes, first?: number, skip?: number); // Fetch all redeems of a user by pool and get information like amount and token details. -fetchUserRedeems(address: string, poolSymbol: Pooltypes, first?: number, skip?: number); +await toucan.fetchUserRedeems(address: string, poolSymbol: Pooltypes, first?: number, skip?: number); // Fetch TCO2 tokens that are part of the given pool and get information on name, amount, methodology and more. -fetchPoolContents(poolSymbol: Pooltypes, first?: number, skip?: number); - -// Fetch a project by it's id to get more info on region and the standard. +await toucan.fetchPoolContents(poolSymbol: Pooltypes, first?: number, skip?: number); -fetchProjectById(); +// Fetch a project by it's id (e.g., Verra Project ID) to get more info on region and the standard. +await toucan.fetchProjectById(id: string); // Fetch all aggregations (including for example, tco2TotalRetired or totalCarbonBridged). -fetchAggregations(); +await toucan.fetchAggregations(); ``` ## Custom queries -There's a lot more other pre-built subgraph queries that I could show you, but what I really want to show you is the `fetchCustomQuery` method. +Now that you have an overview of our pre-build queries, let's have a look at the `fetchCustomQuery` method. This allows you to fetch with your own queries and can be very powerful if you know graphQL. You can also check out a lot of example queries in our subgraph [playgrounds](https://thegraph.com/hosted-service/subgraph/toucanprotocol/matic). -- Getting all infos on a project of a Carbon Credit +- Getting all infos on a carbon project (`region` stands for the country) ```typescript import { gql } from "@urql/core"; +import { ToucanClient } from "toucan-sdk"; + +const toucan = new ToucanClient("alfajores"); const query = gql` query ($id: String) { @@ -197,11 +233,9 @@ const query = gql` const result = await toucan.fetchCustomQuery(query, { id: "1" }); ``` -# AutoOffset using the OffsetHelper - -⚠️ This part is currently under construction and can't be used. ⚠️ +# Auto Offset using the OffsetHelper -## AutoOffset CO2 +## Auto Offset CO2 Using the OffsetHelper methods is the easiest way to offset CO2 right now as it handles the whole process for you. @@ -212,17 +246,20 @@ This is how you do that when you want to use ETH (or the network's native curren In this example, you'd be offsetting 1 TON of CO2 with carbon projects from the NCT pool. ```typescript -const offsetReceipt = await toucan.autoOffsetUsingETH("NCT", parseEther("1.0")); +const offsetReceipt = await toucan.autoOffsetExactOutETH( + "NCT", + parseEther("1.0") +); ``` ### Don't want to spend your ETH to offset? -You can use different tokens to do it. Currently it works with USDC, WMATIC and WETH only. +You can use different tokens to do it. Currently it works with cUSD, USDC, WMATIC and WETH. ```typescript const weth = new ethers.Contract(wethAddress, wethAbi, signer); -const offsetReceipt = await toucan.autoOffsetUsingSwapToken( +const offsetReceipt = await toucan.autoOffsetExactInToken( "NCT", parseEther("1.0"), weth @@ -231,10 +268,10 @@ const offsetReceipt = await toucan.autoOffsetUsingSwapToken( ### Offset with your own BCT/NCT -If you already have BCT/NCT, you can use `autoOffsetUsingPoolToken()` like so: +If you already have BCT/NCT, you can use `autoOffsetPoolToken()` like this: ```typescript -const offsetReceipt = await toucan.autoOffsetUsingPoolToken( +const offsetReceipt = await toucan.autoOffsetPoolToken( "NCT", parseEther("1.0") ); @@ -272,9 +309,9 @@ If you do, that's also quite easy to pull off. You just replace the usage of the ```typescript const retirementReceipt = await toucan.retireAndMintCertificate( - "Alex", + "Alice", signer.address, - "Alex", + "Bob", "Just helping the planet", parseEther("3.0"), tco2s[len - 1].address @@ -283,6 +320,6 @@ const retirementReceipt = await toucan.retireAndMintCertificate( Why do you see my name twice you ask? 🤔 -Well, the first "Alex" represents the entity that is doing the retirement/offset. The second one represents the party that 'benefits' from it. The address also represents the beneficiary. +Well, the first "Alice" represents the entity that is doing the retirement/offset. The second one represents the party that 'benefits' from it, in this case "Bob". We will also add Bob's address so now the relation of the certificate is set to that address instead of the retiring party. -That's useful in case you happen to be an entity that retires on behalf of someone else. +This useful in case you happen to be an entity that retires on behalf of someone else. diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e2ac661 --- /dev/null +++ b/docs/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..738b1f3 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,299 @@ +toucan-sdk / [Exports](modules.md) + +# Toucan SDK + +[![NPM Package](https://img.shields.io/npm/v/toucan-sdk.svg)](https://www.npmjs.com/package/toucan-sdk) + +The Toucan SDK allows developers to build using Toucan's infrastructure tools on [Celo](https://celo.org/) and [Polygon](https://polygon.technology/). It provides a set of functions that allow developers to interact with Toucan Protocol's smart contracts and subgraphs. This includes redeeming of pool tokens and retirements of carbon credits, as well as querying data on projects and retirements. + +A Typescript SDK for [Toucan Protocol](https://toucan.earth/). Wraps around [Ethers.js](https://docs.ethers.io/v5/). Works in the web browser and Node.js. + +For the full documentation, check our [docs](https://docs.toucan.earth/toucan/dev-resources/sdk). + +⚠️ This SDK is heavily under development. USE AT YOUR OWN RISK. ⚠️ + +## Install + +``` +npm i toucan-sdk +``` + +or + +``` +yarn add toucan-sdk +``` + +# Quickstart + +Instantiate the ToucanClient and set a `signer` & `provider` to interact with our infrastructure. + +```typescript +import { ToucanClient } from "toucan-sdk"; + +const toucan = new ToucanClient("alfajores", provider, signer); +``` + +You could also set the signer/provider later if you prefer that. They are optional. But you will need to set them if you want to interact with contracts. The provider is read-only, while the signer allows both writing to and reading from the blockchain. + +```typescript +import { ToucanClient } from "toucan-sdk"; + +const toucan = new ToucanClient("alfajores"); +toucan.setProvider(provider); +toucan.setSigner(signer); +``` + +If you don't have a signer nor a provider set, you can only interact with the subgraph. + +## Fetch pool prices from a Dex + +You can find pools for Toucan pool tokens on [Celo Network](https://celo.org) at [Uniswap](https://uniswap.org/) and for [Polygon Network](https://polygon.technology) on [SushiSwap](sushi.com). + +Something that may come in handy in your applications is fetching the USD price of our pool tokens. + +```typescript +nctPrice = await toucan.fetchTokenPriceOnDex("NCT"); +``` + +The object returned by the above method will look like this: + +```json +{ + "price": 0.6729727912290213, + "url": "https://info.ubeswap.org/token/0xfb60a08855389F3c0A66b29aB9eFa911ed5cbCB5", + "liquidityUSD": 6094809.639784346, + "volumeUSD": 2343496099.964215 +} +``` + +# Interact with Toucan's Contracts? + +You can always access any method or property of the BCT, NCT and TCO2 [contracts](https://github.com/ToucanProtocol/contracts) by first getting and storing them in a variable, like this: + +```typescript +toucan.setSigner(signer); + +const nct = await toucan.getPoolContract("NCT"); +const tco2 = await toucan.getTCO2Contract(tco2Address); +const registry = await toucan.getRegistryContract(); +const remainingTCO2 = await nct.tokenBalances(tco2Address); +``` + +This is useful if you need to interact with a method of our contracts that hasn't been implemented in the SDK yet. + +It's important to note that, if you want to use write methods you need to have a signer set in your ToucanClient! + +## Example to retire Carbon Credits + +To retire Carbon Credits on mainnet, you will have to get Carbon Pool Tokens from a DEX like [Uniswap](https://uniswap.org), which you need to redeem for TCO2s. You can then retire these and get a certificate for that. If you already own NCTs, you can follow this example. In case you don't and are developing on testnet, you can also just get some at the [Toucan Faucet](https://faucet.toucan.earth). You can find more ways to retire in our [documentation](https://docs.toucan.earth/toucan/dev-resources/smart-contracts/tco2). + +**Redeem your Pool Tokens and get an array of redeemed TCO2s** + +```typescript +const tco2Addresses = await toucan.redeemAuto2("NCT", parseEther("1")); +``` + +**Retire the Carbon Credits** + +```typescript +await toucan.retire(parseEther("1"), tco2Addresses[0].address); +``` + +# Subgraph queries + +Now, the above example of selective retirement is only useful in specific cases. + +**What if you only have the name or symbol of the project?** + +That's where subgraph queries come in handy. (and we have plenty of those 😉) - But feel free to also [create your own](#custom-queries). + +**_Make sure all addresses are input in lowercase letters, as the queries are case sensitive._** + +## Fetching a TCO2 by its symbol + +```typescript +const tco2 = await toucan.fetchTCO2TokenByFullSymbol("TCO2-VCS-1718-2013"); +``` + +The result will look like this: + +```json +{ + "id": "0x0044c5a5a6f626b673224a3c0d71e851ad3d5153", + "name": "Toucan Protocol: TCO2-VCS-1718-2013", + "symbol": "TCO2-VCS-1718-2013", + "address": "0x0044c5a5a6f626b673224a3c0d71e851ad3d5153", + "projectVintage": { + "name": "2013", + "project": { + "projectId": "VCS-1718" + } + } +} +``` + +Now you have quite some info on the project, including its address. + +## All queries: + +Toucan SDK offers a lot of pre-defined queries. Try them out! + +```typescript +import { ToucanClient } from "toucan-sdk"; + +// here we don't need to set the signer or provider +const toucan = new ToucanClient("alfajores"); + +// Fetch the batches of a user. +await toucan.fetchUserBatches(address: string, first?: number, skip?: number); + +// Fetch TCO2 token by its address to get details like name, symbol, address and projectVintage. +await toucan.fetchTCO2TokenById(address: string); + +// Fetch TCO2Token with the symbol to get details like name, symbol, address and projectVintage. A symbol would look like this: `TCO2-VCS--YYYY`. Make sure to input the full symbol. +await toucan.fetchTCO2TokenByFullSymbol(symbol: string); + +// Fetch all TCO2s details like name, symbol, address and projectVintage. +await toucan.fetchAllTCO2Tokens(first?: number, skip?: number); + +// Fetch all user retirements to get information like creationTX, amount, token details and certificate details. +await toucan.fetchUserRetirements(address: string, first?: number, skip?: number); + +// Fetch all redeems of a given pool to get information like amount, creator and token details. Only accepts the Pooltypes "NCT" or "BCT". +await toucan.fetchRedeems(poolSymbol: Pooltypes, first?: number, skip?: number); + +// Fetch all redeems of a user by pool and get information like amount and token details. +await toucan.fetchUserRedeems(address: string, poolSymbol: Pooltypes, first?: number, skip?: number); + +// Fetch TCO2 tokens that are part of the given pool and get information on name, amount, methodology and more. +await toucan.fetchPoolContents(poolSymbol: Pooltypes, first?: number, skip?: number); + +// Fetch a project by it's id (e.g., Verra Project ID) to get more info on region and the standard. +await toucan.fetchProjectById(id: string); + +// Fetch all aggregations (including for example, tco2TotalRetired or totalCarbonBridged). +await toucan.fetchAggregations(); +``` + +## Custom queries + +Now that you have an overview of our pre-build queries, let's have a look at the `fetchCustomQuery` method. + +This allows you to fetch with your own queries and can be very powerful if you know graphQL. You can also check out a lot of example queries in our subgraph [playgrounds](https://thegraph.com/hosted-service/subgraph/toucanprotocol/matic). + +- Getting all infos on a carbon project (`region` stands for the country) + +```typescript +import { gql } from "@urql/core"; +import { ToucanClient } from "toucan-sdk"; + +const toucan = new ToucanClient("alfajores"); + +const query = gql` + query ($id: String) { + project(id: $id) { + projectId + region + standard + methodology + vintages { + id + } + } + } +`; + +const result = await toucan.fetchCustomQuery(query, { id: "1" }); +``` + +# Auto Offset using the OffsetHelper + +## Auto Offset CO2 + +Using the OffsetHelper methods is the easiest way to offset CO2 right now as it handles the whole process for you. + +_(Uses Ubeswap/SushiSwap to acquire BCT/NCT, redeems it for TCO2s and retires them)_ + +This is how you do that when you want to use ETH (or the network's native currency) in your balance. + +In this example, you'd be offsetting 1 TON of CO2 with carbon projects from the NCT pool. + +```typescript +const offsetReceipt = await toucan.autoOffsetExactOutETH( + "NCT", + parseEther("1.0") +); +``` + +### Don't want to spend your ETH to offset? + +You can use different tokens to do it. Currently it works with cUSD, USDC, WMATIC and WETH. + +```typescript +const weth = new ethers.Contract(wethAddress, wethAbi, signer); + +const offsetReceipt = await toucan.autoOffsetExactInToken( + "NCT", + parseEther("1.0"), + weth +); +``` + +### Offset with your own BCT/NCT + +If you already have BCT/NCT, you can use `autoOffsetPoolToken()` like this: + +```typescript +const offsetReceipt = await toucan.autoOffsetPoolToken( + "NCT", + parseEther("1.0") +); +``` + +### Selectively Offset CO2 + +You may want to selectively offset certain carbon projects. You can do that too. + +Assuming you already have some NCT, this example gets an array of all TCO2s in the NCT pool ascending by rank/quality. + +Then redeems and retires 3 TONS of the highest ranked TCO2 it can find. + +```typescript +const scoredTCO2s = await toucan.getScoredTCO2s("NCT"); +const len = scoredTCO2s.length; + +const redeemReceipt = await toucan.redeemMany( + "NCT", + [scoredTCO2s[len - 1]], + [parseEther("3.0")] +); + +const retirementReceipt = await toucan.retire( + parseEther("3.0"), + tco2s[len - 1].address +); +``` + +Of course, you could have avoided using the `getScoredTCO2s` method if you already had the address of the TCO2s you wanted to offset. + +### But I want the Retirement NFT + +If you do, that's also quite easy to pull off. You just replace the usage of the `retire()` method in the example above with this: + +```typescript +const retirementReceipt = await toucan.retireAndMintCertificate( + "Alice", + signer.address, + "Bob", + "Just helping the planet", + parseEther("3.0"), + tco2s[len - 1].address +); +``` + +Why do you see my name twice you ask? 🤔 + +Well, the first "Alice" represents the entity that is doing the retirement/offset. The second one represents the party that 'benefits' from it, in this case "Bob". We will also add Bob's address so now the relation of the certificate is set to that address instead of the retiring party. + +This useful in case you happen to be an entity that retires on behalf of someone else. diff --git a/docs/classes/default.md b/docs/classes/default.md new file mode 100644 index 0000000..4aed8a1 --- /dev/null +++ b/docs/classes/default.md @@ -0,0 +1,1276 @@ +[toucan-sdk](../README.md) / [Exports](../modules.md) / default + +# Class: default + +**`Description`** + +This class wraps around classes that help users to interact with Toucan infrastructure + +**`Implements`** + +ContractInteractions, SubgraphInteractions + +## Table of contents + +### Constructors + +- [constructor](default.md#constructor) + +### Properties + +- [contractInteractions](default.md#contractinteractions) +- [fetchAggregations](default.md#fetchaggregations) +- [fetchAllTCO2Tokens](default.md#fetchalltco2tokens) +- [fetchBridgedBatchTokens](default.md#fetchbridgedbatchtokens) +- [fetchCustomQuery](default.md#fetchcustomquery) +- [fetchPoolContents](default.md#fetchpoolcontents) +- [fetchProjectById](default.md#fetchprojectbyid) +- [fetchRedeems](default.md#fetchredeems) +- [fetchTCO2TokenByFullSymbol](default.md#fetchtco2tokenbyfullsymbol) +- [fetchTCO2TokenById](default.md#fetchtco2tokenbyid) +- [fetchUserBatches](default.md#fetchuserbatches) +- [fetchUserRedeems](default.md#fetchuserredeems) +- [fetchUserRetirements](default.md#fetchuserretirements) +- [network](default.md#network) +- [provider](default.md#provider) +- [signer](default.md#signer) +- [subgraphInteractions](default.md#subgraphinteractions) + +### Methods + +- [autoOffsetExactInETH](default.md#autooffsetexactineth) +- [autoOffsetExactInToken](default.md#autooffsetexactintoken) +- [autoOffsetExactOutETH](default.md#autooffsetexactouteth) +- [autoOffsetExactOutToken](default.md#autooffsetexactouttoken) +- [autoOffsetPoolToken](default.md#autooffsetpooltoken) +- [calculateExpectedPoolTokenForETH](default.md#calculateexpectedpooltokenforeth) +- [calculateExpectedPoolTokenForToken](default.md#calculateexpectedpooltokenfortoken) +- [calculateNeededETHAmount](default.md#calculateneededethamount) +- [calculateNeededTokenAmount](default.md#calculateneededtokenamount) +- [calculateRedeemFees](default.md#calculateredeemfees) +- [checkEligible](default.md#checkeligible) +- [checkIfTCO2](default.md#checkiftco2) +- [depositTCO2](default.md#deposittco2) +- [fetchTokenPriceOnDex](default.md#fetchtokenpriceondex) +- [getAttributes](default.md#getattributes) +- [getDepositCap](default.md#getdepositcap) +- [getOffsetHelperContract](default.md#getoffsethelpercontract) +- [getPoolAddress](default.md#getpooladdress) +- [getPoolContract](default.md#getpoolcontract) +- [getPoolRemaining](default.md#getpoolremaining) +- [getRegistryContract](default.md#getregistrycontract) +- [getScoredTCO2s](default.md#getscoredtco2s) +- [getTCO2Contract](default.md#gettco2contract) +- [getTCO2Remaining](default.md#gettco2remaining) +- [redeemAuto](default.md#redeemauto) +- [redeemAuto2](default.md#redeemauto2) +- [redeemMany](default.md#redeemmany) +- [retire](default.md#retire) +- [retireAndMintCertificate](default.md#retireandmintcertificate) +- [retireFrom](default.md#retirefrom) +- [setProvider](default.md#setprovider) +- [setSigner](default.md#setsigner) + +## Constructors + +### constructor + +• **new default**(`network`, `provider?`, `signer?`) + +#### Parameters + +| Name | Type | Description | +| :---------- | :--------- | :------------------------------------- | +| `network` | `Network` | network that you want to work on | +| `provider?` | `Provider` | to be able to read from the blockchain | +| `signer?` | `Signer` | to be able to sign transactions | + +#### Defined in + +[index.ts:69](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L69) + +## Properties + +### contractInteractions + +• **contractInteractions**: `ContractInteractions` + +#### Defined in + +[index.ts:60](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L60) + +--- + +### fetchAggregations + +• **fetchAggregations**: `AggregationsMethod` + +**`Description`** + +fetch all aggregations (including, for example, tco2TotalRetired or totalCarbonBridged) + +#### Defined in + +[index.ts:805](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L805) + +--- + +### fetchAllTCO2Tokens + +• **fetchAllTCO2Tokens**: `AllTCO2TokensMethod` + +**`Description`** + +fetches TCO2Details of all TCO2s + +#### Defined in + +[index.ts:682](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L682) + +--- + +### fetchBridgedBatchTokens + +• **fetchBridgedBatchTokens**: `BridgedBatchTokensMethod` + +**`Description`** + +fetches data about BatchTokens that have been bridged + +#### Defined in + +[index.ts:695](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L695) + +--- + +### fetchCustomQuery + +• **fetchCustomQuery**: `CustomQueryMethod` + +**`Description`** + +if pre-made queries to Toucan's Subgraph don't fit all your needs; use this for custom queries + +**`Param`** + +a gql formated GraphQL query + +**`Param`** + +any parameters you may want to pass to the query + +#### Defined in + +[index.ts:820](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L820) + +--- + +### fetchPoolContents + +• **fetchPoolContents**: `PoolContentsMethod` + +**`Description`** + +fetches TCO2 tokens that are part of the given pool + +**`Param`** + +The pool symbol of the pool to fetch for + +**`Param`** + +how many TCO2 tokens you want fetched; defaults to 1000 + +**`Param`** + +how many (if any) retirements you want skipped; defaults to 0 + +#### Defined in + +[index.ts:774](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L774) + +--- + +### fetchProjectById + +• **fetchProjectById**: `ProjectByIdMethod` + +**`Description`** + +fetches a project by its id + +**`Param`** + +id of the project to fetch; e.g.: "10" + +#### Defined in + +[index.ts:792](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L792) + +--- + +### fetchRedeems + +• **fetchRedeems**: `RedeemsMethod` + +**`Description`** + +fetches redeems of a given pool + +**`Param`** + +The pool symbol of pool to fetch for + +**`Param`** + +how many redeems you want fetched; defaults to 100 + +**`Param`** + +how many (if any) redeems you want skipped; defaults to 0 + +#### Defined in + +[index.ts:735](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L735) + +--- + +### fetchTCO2TokenByFullSymbol + +• **fetchTCO2TokenByFullSymbol**: `TCO2TokenByFullSymbolMethod` + +**`Description`** + +fetches properties of a TCO2 + +**`Param`** + +full symbol of the TCO2 to query for e.g.: "TCO2-VCS-1718-2013" + +#### Defined in + +[index.ts:671](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L671) + +--- + +### fetchTCO2TokenById + +• **fetchTCO2TokenById**: `TCO2TokenByIdMethod` + +**`Description`** + +fetches properties of a TCO2 + +**`Param`** + +id of the TCO2 to query for; the id happens to be the same as the address e.g.: "0x004090eef602e024b2a6cb7f0c1edda992382994" + +#### Defined in + +[index.ts:661](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L661) + +--- + +### fetchUserBatches + +• **fetchUserBatches**: `UserBatchesMethod` + +**`Description`** + +fetches the batches of a user + +**`Param`** + +address of user to query for + +#### Defined in + +[index.ts:647](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L647) + +--- + +### fetchUserRedeems + +• **fetchUserRedeems**: `UserRedeemsMethod` + +**`Description`** + +fetches redeems of a given pool and user + +**`Param`** + +address of the user/wallet to query for + +**`Param`** + +The pool symbol of pool to fetch for + +**`Param`** + +how many redeems you want fetched; defaults to 100 + +**`Param`** + +how many (if any) redeems you want skipped; defaults to 0 + +#### Defined in + +[index.ts:748](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L748) + +--- + +### fetchUserRetirements + +• **fetchUserRetirements**: `UserRetirementsMethod` + +**`Description`** + +fetches retirements made by a user + +**`Param`** + +address of the user/wallet to query for + +**`Param`** + +how many retirements you want fetched; defaults to 100 + +**`Param`** + +how many (if any) retirements you want skipped; defaults to 0 + +#### Defined in + +[index.ts:711](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L711) + +--- + +### network + +• **network**: `Network` + +#### Defined in + +[index.ts:59](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L59) + +--- + +### provider + +• **provider**: `undefined` \| `Provider` + +#### Defined in + +[index.ts:58](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L58) + +--- + +### signer + +• **signer**: `undefined` \| `Signer` + +#### Defined in + +[index.ts:57](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L57) + +--- + +### subgraphInteractions + +• **subgraphInteractions**: `SubgraphInteractions` + +#### Defined in + +[index.ts:61](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L61) + +## Methods + +### autoOffsetExactInETH + +▸ **autoOffsetExactInETH**(`pool`, `amount`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :------- | :----------- | :--------------------------------------------------------------------------------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use e.g., "NCT" | +| `amount` | `BigNumber` | the amount of native tokens e.g., MATIC to swap into Toucan pool token. Full amount will be used for offsetting. | + +#### Returns + +`Promise`<`ContractReceipt`\> + +The offset transaction. + +**`Description`** + +Swaps ETH for carbon pool tokens and uses them to retire carbon + +**`Notice`** + +This method may take up to 1 minute to return a result + +#### Defined in + +[index.ts:511](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L511) + +--- + +### autoOffsetExactInToken + +▸ **autoOffsetExactInToken**(`swapToken`, `pool`, `amount`): `Promise`<`ContractReceipt`\> + +/\*\* + +- +- + +#### Parameters + +| Name | Type | Description | +| :---------- | :----------- | :---------------------------------------------------------------------------------------------------- | +| `swapToken` | `string` | portal for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC) \* | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use \* | +| `amount` | `BigNumber` | the amount of ERC20 token to swap into Toucan pool token. Full amount will be used for offsetting. \* | + +#### Returns + +`Promise`<`ContractReceipt`\> + +The offset transaction. + +**`Description`** + +retires carbon credits using the oldest TCO2 tokens available from the specified Toucan token pool by sending ERC20 + +- tokens (cUSD, USDC, WETH, WMATIC). All provided tokens are consumed for offsetting. +- + +**`Notice`** + +this method needs two different actions signed and may take up to 1 minute to return a result + +- + +**`Dev`** + +When automatically redeeming pool tokens for the oldest ones + +- TCO2s there are no fees and you receive exactly 1 TCO2 token for 1 pool +- token. +- + +#### Defined in + +[index.ts:459](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L459) + +--- + +### autoOffsetExactOutETH + +▸ **autoOffsetExactOutETH**(`pool`, `amount`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :------- | :----------- | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `amount` | `BigNumber` | The amount of CO2 tons to offset | + +#### Returns + +`Promise`<`ContractReceipt`\> + +The offset transaction. + +**`Description`** + +retires a specified amount of carbon credits using the oldest TCO2 tokens available from the specified Toucan token pool by sending a native token e.g. MATIC. + +**`Dev`** + +Use `calculateNeededETHAmount()` first in order to find out how much of the native token e.g. MATIC is required to retire the specified quantity of TCO2. If the user sends much native token e.g. MATIC, the leftover amount will be sent back to the user. + +**`Notice`** + +This method may take up to 1 minute to return a result + +#### Defined in + +[index.ts:488](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L488) + +--- + +### autoOffsetExactOutToken + +▸ **autoOffsetExactOutToken**(`swapToken`, `pool`, `amount`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :---------- | :----------- | :--------------------------------------------------------------------------------- | +| `swapToken` | `string` | portal for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC) | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `amount` | `BigNumber` | The amount of CO2 tons to offset | + +#### Returns + +`Promise`<`ContractReceipt`\> + +The offset transaction. + +**`Description`** + +retires a specified amount of carbon credits using the lowest +quality (oldest) TCO2 tokens available from the specified Toucan token pool by sending ERC20 +tokens (cUSD, USDC, WETH, WMATIC). + +**`Notice`** + +this method needs two different actions signed and may take up to 1 minute to return a result + +#### Defined in + +[index.ts:424](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L424) + +--- + +### autoOffsetPoolToken + +▸ **autoOffsetPoolToken**(`pool`, `amount`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :------- | :----------- | :----------------------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool token to offset, e.g., NCT | +| `amount` | `BigNumber` | The amount of of TCO2 to offset. | + +#### Returns + +`Promise`<`ContractReceipt`\> + +The offset transaction. + +**`Description`** + +retires carbon credits using the oldest TCO2 +tokens available by sending pool tokens, e.g., NCT. + +**`Notice`** + +This method may take up to 1 minute to return a result + +#### Defined in + +[index.ts:402](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L402) + +--- + +### calculateExpectedPoolTokenForETH + +▸ **calculateExpectedPoolTokenForETH**(`pool`, `amount`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | Description | +| :------- | :----------- | :--------------------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `amount` | `BigNumber` | The amount of native tokens to swap for, e.g., MATIC | + +#### Returns + +`Promise`<`BigNumber`\> + +amount The expected amount of Pool token that can be acquired. + +**`Description`** + +Calculates the expected amount of Toucan Pool token that can be +acquired by swapping the provided amount of native tokens e.g., MATIC. + +#### Defined in + +[index.ts:621](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L621) + +--- + +### calculateExpectedPoolTokenForToken + +▸ **calculateExpectedPoolTokenForToken**(`swapToken`, `pool`, `amount`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | Description | +| :---------- | :----------- | :------------------------------------------------------- | +| `swapToken` | `string` | The ERC20 token used for the swap | +| `pool` | `PoolSymbol` | The pool symbol of the pool token to swap for, e.g., NCT | +| `amount` | `BigNumber` | The amount of ERC20 token to swap | + +#### Returns + +`Promise`<`BigNumber`\> + +amount The expected amount of Pool token that can be acquired. + +**`Description`** + +Calculates the expected amount of Toucan Pool token that can be +acquired by swapping the provided amount of ERC20 token. + +#### Defined in + +[index.ts:592](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L592) + +--- + +### calculateNeededETHAmount + +▸ **calculateNeededETHAmount**(`pool`, `amount`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | Description | +| :------- | :----------- | :------------------------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool token to swap for, e.g., NCT | +| `amount` | `BigNumber` | The desired amount of pool token to receive | + +#### Returns + +`Promise`<`BigNumber`\> + +amount of native tokens, e.g., MATIC required in order to swap for +the specified amount of the pool token. + +**`Description`** + +Calculates the amount of native tokens e.g, MATIC is required in order to swap for the +desired amount of a Toucan pool token, e.g., NCT. + +#### Defined in + +[index.ts:565](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L565) + +--- + +### calculateNeededTokenAmount + +▸ **calculateNeededTokenAmount**(`swapToken`, `pool`, `amount`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | Description | +| :---------- | :----------- | :------------------------------------------------------- | +| `swapToken` | `string` | The ERC20 token used for the swap | +| `pool` | `PoolSymbol` | The pool symbol of the pool token to swap for, e.g., NCT | +| `amount` | `BigNumber` | The desired amount of pool token to receive | + +#### Returns + +`Promise`<`BigNumber`\> + +amount of the ERC20 token required in order to +swap for the specified amount of the pool token. + +**`Description`** + +Calculates how much of the specified ERC20 token is required in +order to swap for the desired amount of a Toucan pool token, for +example, e.g., NCT. + +#### Defined in + +[index.ts:535](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L535) + +--- + +### calculateRedeemFees + +▸ **calculateRedeemFees**(`pool`, `tco2s`, `amounts`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | Description | +| :-------- | :------------ | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `tco2s` | `string`[] | array of TCO2 contract addresses | +| `amounts` | `BigNumber`[] | array of amounts to redeem for each tco2s | + +#### Returns + +`Promise`<`BigNumber`\> + +amount of fees it will cost to redeem. + +**`Description`** + +calculates the fees to selectively redeem pool tokens for TCO2s + +**`Notice`** + +tco2s must match amounts; amounts[0] is the amount of tco2[0] token to redeem for + +#### Defined in + +[index.ts:272](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L272) + +--- + +### checkEligible + +▸ **checkEligible**(`pool`, `tco2`): `Promise`<`boolean`\> + +#### Parameters + +| Name | Type | Description | +| :----- | :----------- | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `tco2` | `string` | address of TCO2 to deposit | + +#### Returns + +`Promise`<`boolean`\> + +boolean + +**`Description`** + +checks if TCO2 is eligible for pool + +#### Defined in + +[index.ts:252](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L252) + +--- + +### checkIfTCO2 + +▸ **checkIfTCO2**(`address`): `Promise`<`boolean`\> + +#### Parameters + +| Name | Type | Description | +| :-------- | :------- | :--------------------------- | +| `address` | `string` | address of contract to check | + +#### Returns + +`Promise`<`boolean`\> + +boolean + +**`Description`** + +checks if an address represents a TCO2 + +#### Defined in + +[index.ts:379](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L379) + +--- + +### depositTCO2 + +▸ **depositTCO2**(`pool`, `amount`, `tco2Address`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :------------ | :----------- | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `amount` | `BigNumber` | The amount of TCO2s to deposit | +| `tco2Address` | `string` | address of the TCO2 token to deposit\* | + +#### Returns + +`Promise`<`ContractReceipt`\> + +deposit transaction + +**`Description`** + +deposits TCO2s in the pool which mints a pool token for the user + +#### Defined in + +[index.ts:229](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L229) + +--- + +### fetchTokenPriceOnDex + +▸ **fetchTokenPriceOnDex**(`pool`): `Promise`<{ `liquidityUSD`: `null` \| `number` ; `price`: `null` \| `number` ; `url`: `null` \| `string` ; `volumeUSD`: `null` \| `number` }\> + +#### Parameters + +| Name | Type | +| :----- | :----------- | +| `pool` | `PoolSymbol` | + +#### Returns + +`Promise`<{ `liquidityUSD`: `null` \| `number` ; `price`: `null` \| `number` ; `url`: `null` \| `string` ; `volumeUSD`: `null` \| `number` }\> + +#### Defined in + +[index.ts:830](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L830) + +--- + +### getAttributes + +▸ **getAttributes**(`tco2Address`): `Promise`<[[`string`, `string`, `string`, `string`, `string`, `string`, `string`, `string`, `string`, `string`] & { `category`: `string` ; `controller`: `string` ; `emissionType`: `string` ; `method`: `string` ; `methodology`: `string` ; `projectId`: `string` ; `region`: `string` ; `standard`: `string` ; `storageMethod`: `string` ; `uri`: `string` }, [`string`, `BigNumber`, `BigNumber`, `BigNumber`, `BigNumber`, `boolean`, `boolean`, `string`, `string`, `string`, `string`] & { `additionalCertification`: `string` ; `coBenefits`: `string` ; `correspAdjustment`: `string` ; `endTime`: `BigNumber` ; `isCCPcompliant`: `boolean` ; `isCorsiaCompliant`: `boolean` ; `name`: `string` ; `projectTokenId`: `BigNumber` ; `startTime`: `BigNumber` ; `totalVintageQuantity`: `BigNumber` ; `uri`: `string` }]\> + +#### Parameters + +| Name | Type | Description | +| :------------ | :------- | :------------------------ | +| `tco2Address` | `string` | address of the TCO2 token | + +#### Returns + +`Promise`<[[`string`, `string`, `string`, `string`, `string`, `string`, `string`, `string`, `string`, `string`] & { `category`: `string` ; `controller`: `string` ; `emissionType`: `string` ; `method`: `string` ; `methodology`: `string` ; `projectId`: `string` ; `region`: `string` ; `standard`: `string` ; `storageMethod`: `string` ; `uri`: `string` }, [`string`, `BigNumber`, `BigNumber`, `BigNumber`, `BigNumber`, `boolean`, `boolean`, `string`, `string`, `string`, `string`] & { `additionalCertification`: `string` ; `coBenefits`: `string` ; `correspAdjustment`: `string` ; `endTime`: `BigNumber` ; `isCCPcompliant`: `boolean` ; `isCorsiaCompliant`: `boolean` ; `name`: `string` ; `projectTokenId`: `BigNumber` ; `startTime`: `BigNumber` ; `totalVintageQuantity`: `BigNumber` ; `uri`: `string` }]\> + +an array of attributes + +**`Description`** + +gets the attributes of the project represented by the TCO2 + +#### Defined in + +[index.ts:190](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L190) + +--- + +### getDepositCap + +▸ **getDepositCap**(`tco2Address`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | Description | +| :------------ | :------- | :------------------------ | +| `tco2Address` | `string` | address of the TCO2 token | + +#### Returns + +`Promise`<`BigNumber`\> + +**`Description`** + +gets the cap for TCO2s based on `totalVintageQuantity` + +#### Defined in + +[index.ts:174](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L174) + +--- + +### getOffsetHelperContract + +▸ **getOffsetHelperContract**(): `OffsetHelper` + +#### Returns + +`OffsetHelper` + +a ethers.contract to interact with the OffsetHelper + +**`Description`** + +gets the contract of a the OffsetHelper contract + +#### Defined in + +[index.ts:899](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L899) + +--- + +### getPoolAddress + +▸ **getPoolAddress**(`pool`): `string` + +#### Parameters + +| Name | Type | Description | +| :----- | :----------- | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | + +#### Returns + +`string` + +a ethers.contract to interact with the pool + +**`Description`** + +gets the contract of a pool token based on the symbol + +#### Defined in + +[index.ts:851](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L851) + +--- + +### getPoolContract + +▸ **getPoolContract**(`pool`): `IToucanPoolToken` + +#### Parameters + +| Name | Type | +| :----- | :----------- | +| `pool` | `PoolSymbol` | + +#### Returns + +`IToucanPoolToken` + +a ethers.contract to interact with the pool + +**`Dev`** + +**`Description`** + +gets the contract of a pool token based on the symbol + +#### Defined in + +[index.ts:862](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L862) + +--- + +### getPoolRemaining + +▸ **getPoolRemaining**(`pool`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | +| :----- | :----------- | +| `pool` | `PoolSymbol` | + +#### Returns + +`Promise`<`BigNumber`\> + +BigNumber representing the remaining space + +**`Description`** + +gets the remaining space in pool contract before hitting the cap + +#### Defined in + +[index.ts:347](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L347) + +--- + +### getRegistryContract + +▸ **getRegistryContract**(): `IToucanContractRegistry` + +#### Returns + +`IToucanContractRegistry` + +a ethers.contract to interact with the contract registry + +**`Description`** + +gets the contract of a the Toucan contract registry + +#### Defined in + +[index.ts:887](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L887) + +--- + +### getScoredTCO2s + +▸ **getScoredTCO2s**(`pool`): `Promise`<`string`[]\> + +#### Parameters + +| Name | Type | Description | +| :----- | :----------- | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | + +#### Returns + +`Promise`<`string`[]\> + +array of TCO2 addresses by rank + +**`Description`** + +gets an array of scored TCO2s; scoredTCO2s[0] is lowest ranked + +#### Defined in + +[index.ts:360](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L360) + +--- + +### getTCO2Contract + +▸ **getTCO2Contract**(`address`): `IToucanCarbonOffsets` + +#### Parameters + +| Name | Type | Description | +| :-------- | :------- | :-------------------------------------------- | +| `address` | `string` | address of TCO2 ethers.Contract to insantiate | + +#### Returns + +`IToucanCarbonOffsets` + +a ethers.contract to interact with the token + +**`Description`** + +gets the contract of a TCO2 token based on the address + +#### Defined in + +[index.ts:875](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L875) + +--- + +### getTCO2Remaining + +▸ **getTCO2Remaining**(`tco2Address`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | Description | +| :------------ | :------- | :------------------------ | +| `tco2Address` | `string` | address of the TCO2 token | + +#### Returns + +`Promise`<`BigNumber`\> + +BigNumber representing the remaining space + +**`Description`** + +gets the remaining space in TCO2 contract before hitting the cap + +#### Defined in + +[index.ts:206](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L206) + +--- + +### redeemAuto + +▸ **redeemAuto**(`pool`, `amount`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :------- | :----------- | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `amount` | `BigNumber` | amount to redeem | + +#### Returns + +`Promise`<`ContractReceipt`\> + +redeem transaction + +**`Description`** + +automatically redeems pool tokens for TCO2s + +#### Defined in + +[index.ts:314](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L314) + +--- + +### redeemAuto2 + +▸ **redeemAuto2**(`pool`, `amount`): `Promise`<{ `address`: `string` ; `amount`: `BigNumber` }[]\> + +#### Parameters + +| Name | Type | Description | +| :------- | :----------- | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `amount` | `BigNumber` | amount to redeem | + +#### Returns + +`Promise`<{ `address`: `string` ; `amount`: `BigNumber` }[]\> + +array containing tco2 addresses (string) and amounts (BigNumber) + +**`Description`** + +automatically redeems pool tokens for TCO2s + +#### Defined in + +[index.ts:331](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L331) + +--- + +### redeemMany + +▸ **redeemMany**(`pool`, `tco2s`, `amounts`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :-------- | :------------ | :----------------------------------------- | +| `pool` | `PoolSymbol` | The pool symbol of the pool (token) to use | +| `tco2s` | `string`[] | array of TCO2 contract addresses | +| `amounts` | `BigNumber`[] | array of amounts to redeem for each tco2s | + +#### Returns + +`Promise`<`ContractReceipt`\> + +redeem transaction + +**`Description`** + +selectively redeems pool tokens for TCO2s + +#### Defined in + +[index.ts:296](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L296) + +--- + +### retire + +▸ **retire**(`amount`, `tco2Address`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :------------ | :---------- | :------------------------------------ | +| `amount` | `BigNumber` | The amount of TCO2 to retire | +| `tco2Address` | `string` | address of the TCO2 token to retire\* | + +#### Returns + +`Promise`<`ContractReceipt`\> + +retirement transaction + +**`Description`** + +retires/burns an amount of TCO2s (each represents 1 ton of CO2) to achieve offset + +#### Defined in + +[index.ts:102](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L102) + +--- + +### retireAndMintCertificate + +▸ **retireAndMintCertificate**(`retirementEntityName`, `beneficiaryAddress`, `beneficiaryName`, `retirementMessage`, `amount`, `tco2Address`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :--------------------- | :---------- | :-------------------------------------------------------------------- | +| `retirementEntityName` | `string` | name of the entity that does the retirement (you) | +| `beneficiaryAddress` | `string` | address of the beneficiary (in case you're retiring for someone else) | +| `beneficiaryName` | `string` | name of the beneficiary | +| `retirementMessage` | `string` | retirement message | +| `amount` | `BigNumber` | The amount of TCO2 to retire | +| `tco2Address` | `string` | address of the TCO2 token to retire\* | + +#### Returns + +`Promise`<`ContractReceipt`\> + +retirement transaction + +**`Description`** + +retires/burns an amount of TCO2s & mints the NFT certificate for it within the same transaction + +#### Defined in + +[index.ts:122](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L122) + +--- + +### retireFrom + +▸ **retireFrom**(`amount`, `address`, `tco2Address`): `Promise`<`ContractReceipt`\> + +#### Parameters + +| Name | Type | Description | +| :------------ | :---------- | :------------------------------------ | +| `amount` | `BigNumber` | The amount of TCO2 to retire | +| `address` | `string` | address of the account to retire from | +| `tco2Address` | `string` | address of the TCO2 token to retire\* | + +#### Returns + +`Promise`<`ContractReceipt`\> + +retirement transaction + +**`Description`** + +retires/burns an amount of TCO2s from a different address/wallet + +**`Notice`** + +requires approval from the address you're trying to retire from + +#### Defined in + +[index.ts:152](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L152) + +--- + +### setProvider + +▸ **setProvider**(`provider`): `void` + +#### Parameters + +| Name | Type | +| :--------- | :--------- | +| `provider` | `Provider` | + +#### Returns + +`void` + +#### Defined in + +[index.ts:86](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L86) + +--- + +### setSigner + +▸ **setSigner**(`signer`): `void` + +#### Parameters + +| Name | Type | +| :------- | :------- | +| `signer` | `Signer` | + +#### Returns + +`void` + +#### Defined in + +[index.ts:82](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/index.ts#L82) diff --git a/docs/modules.md b/docs/modules.md new file mode 100644 index 0000000..694d37c --- /dev/null +++ b/docs/modules.md @@ -0,0 +1,105 @@ +[toucan-sdk](README.md) / Exports + +# toucan-sdk + +## Table of contents + +### Classes + +- [default](classes/default.md) + +### Type Aliases + +- [BalanceResponse](modules.md#balanceresponse) +- [BridgedBatchTokensResponse](modules.md#bridgedbatchtokensresponse) +- [PoolContentsResponse](modules.md#poolcontentsresponse) +- [ProjectResponse](modules.md#projectresponse) +- [RedeemsResponse](modules.md#redeemsresponse) +- [TCO2TokenResponse](modules.md#tco2tokenresponse) +- [UserBatchesResponse](modules.md#userbatchesresponse) +- [UserRetirementsResponse](modules.md#userretirementsresponse) + +## Type Aliases + +### BalanceResponse + +Ƭ **BalanceResponse**: `Pick`<`TCO2BalanceSchema`, ``"balance"``\> & { `token`: `Pick`<`TCO2TokenSchema`, ``"symbol"``\> } + +#### Defined in + +[types/responses.ts:147](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L147) + +___ + +### BridgedBatchTokensResponse + +Ƭ **BridgedBatchTokensResponse**: `Pick`<`BatchTokenSchema`, ``"id"`` \| ``"serialNumber"`` \| ``"quantity"`` \| ``"timestamp"`` \| ``"tx"``\> & { `creator`: `Pick`<`UserSchema`, ``"id"``\> } + +#### Defined in + +[types/responses.ts:75](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L75) + +___ + +### PoolContentsResponse + +Ƭ **PoolContentsResponse**: `Pick`<`PooledTCO2TokenSchema`, ``"amount"``\> & { `token`: `Pick`<`TCO2TokenSchema`, ``"name"``\> & { `projectVintage`: `Pick`<`ProjectVintageSchema`, ``"id"``\> & { `project`: `Pick`<`ProjectSchema`, ``"methodology"`` \| ``"standard"``\> } } } + +#### Defined in + +[types/responses.ts:126](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L126) + +___ + +### ProjectResponse + +Ƭ **ProjectResponse**: `Pick`<`ProjectSchema`, ``"projectId"`` \| ``"region"`` \| ``"standard"`` \| ``"methodology"``\> & { `vintages`: `Pick`<`ProjectVintageSchema`, ``"id"``\> } + +#### Defined in + +[types/responses.ts:138](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L138) + +___ + +### RedeemsResponse + +Ƭ **RedeemsResponse**: `Pick`<`RedeemSchema`, ``"id"`` \| ``"amount"`` \| ``"timestamp"``\> & { `creator`: `Pick`<`UserSchema`, ``"id"``\> ; `token`: `Pick`<`TCO2TokenSchema`, ``"symbol"`` \| ``"name"`` \| ``"address"``\> & { `projectVintage`: `Pick`<`ProjectVintageSchema`, ``"name"``\> & { `project`: `Pick`<`ProjectSchema`, ``"projectId"``\> } } } + +#### Defined in + +[types/responses.ts:110](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L110) + +___ + +### TCO2TokenResponse + +Ƭ **TCO2TokenResponse**: `Pick`<`TCO2TokenSchema`, ``"id"`` \| ``"name"`` \| ``"symbol"`` \| ``"address"``\> & { `projectVintage`: `Pick`<`ProjectVintageSchema`, ``"name"``\> & { `project`: `Pick`<`ProjectSchema`, ``"projectId"``\> } } + +#### Defined in + +[types/responses.ts:62](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L62) + +___ + +### UserBatchesResponse + +Ƭ **UserBatchesResponse**: `Pick`<`BatchTokenSchema`, ``"id"`` \| ``"tx"`` \| ``"serialNumber"`` \| ``"quantity"`` \| ``"confirmationStatus"``\> & { `comments`: `Pick`<`BatchCommentSchema`, ``"id"`` \| ``"comment"``\> & { `sender`: `Pick`<`UserSchema`, ``"id"``\> }[] ; `creator`: `Pick`<`UserSchema`, ``"id"``\> }[] + +I have decided to separated the types for the subgraph methods here as using Pick to separate +the needed properties from the schemas can become verbose as you will see below. + +See types/schemas.ts for more information on why I decided to use Pick in the first place. + +#### Defined in + +[types/responses.ts:44](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L44) + +___ + +### UserRetirementsResponse + +Ƭ **UserRetirementsResponse**: `Pick`<`RetirementSchema`, ``"id"`` \| ``"creationTx"`` \| ``"amount"`` \| ``"timestamp"``\> & { `certificate`: `Pick`<`RetirementCertificateSchema`, ``"id"`` \| ``"retiringEntityString"`` \| ``"beneficiaryString"`` \| ``"retirementMessage"`` \| ``"createdAt"``\> & { `beneficiary`: `Pick`<`UserSchema`, ``"id"``\> ; `retiringEntity`: `Pick`<`UserSchema`, ``"id"``\> } ; `token`: `Pick`<`TCO2TokenSchema`, ``"symbol"`` \| ``"name"`` \| ``"address"``\> & { `projectVintage`: `Pick`<`ProjectVintageSchema`, ``"name"``\> & { `project`: `Pick`<`ProjectSchema`, ``"projectId"``\> } } } + +#### Defined in + +[types/responses.ts:84](https://github.com/GigaHierz/toucan-sdk/blob/b837065/src/types/responses.ts#L84) diff --git a/package.json b/package.json index 37cdece..947e8b8 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "toucan-sdk", - "version": "1.0.4-beta", + "version": "1.0.5-beta", "description": "A JavaScript SDK for Toucan Protocol. Works in the web browser and Node.js.", "main": "./dist/index.js", "scripts": { "build": "tsc", "clean": "rimraf dist", "build:clean": "yarn clean && yarn build", + "docs": "typedoc --plugin typedoc-plugin-markdown --out docs src/index.ts", "format:check": "prettier --check \"**/*.ts\"", "format:write": "prettier --write \"**/*.ts\"", "lint": "eslint '**/*.ts'", @@ -27,7 +28,9 @@ "@urql/core": "^2.5.0", "ethers": "^5.6.4", "graphql": "^16.5.0", - "isomorphic-unfetch": "^4.0.2" + "isomorphic-unfetch": "^4.0.2", + "typedoc": "^0.25.1", + "typedoc-plugin-markdown": "^3.16.0" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.0", @@ -37,7 +40,6 @@ "@typechain/hardhat": "^6.0.0", "@types/chai": "^4.2.21", "@types/mocha": "^9.0.0", - "@types/node": "^17.0.34", "@typescript-eslint/eslint-plugin": "^5.25.0", "@typescript-eslint/parser": "^5.25.0", "chai": "^4.2.0", diff --git a/src/index.ts b/src/index.ts index 87d0c0a..b9cdd30 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,24 +1,25 @@ /** -The OffsetHelper's purpose is to simplify the carbon offsetting process. -Copyright (C) 2022 Toucan Labs + The OffsetHelper's purpose is to simplify the carbon offsetting process. + Copyright (C) 2022 Toucan Labs This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ import "isomorphic-unfetch"; -import { BigNumber, Contract, ContractReceipt, ethers } from "ethers"; +import { BigNumber, ContractReceipt, ethers } from "ethers"; +import { FormatTypes, Interface } from "ethers/lib/utils"; import ContractInteractions from "./subclasses/ContractInteractions"; import SubgraphInteractions from "./subclasses/SubgraphInteractions"; @@ -44,6 +45,9 @@ import { UserRetirementsMethod, } from "./types/methods"; import { RedeemAutoResponse } from "./types/responses"; +import { ERC20ABI } from "./utils/ABIs"; + +export * from "./types/responses"; /** * @@ -87,14 +91,14 @@ export default class ToucanClient { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // TCO2 related methods + // TCO2 related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- /** * * @description retires/burns an amount of TCO2s (each represents 1 ton of CO2) to achieve offset - * @param amount amount of TCO2 to retire + * @param amount The amount of TCO2 to retire * @param tco2Address address of the TCO2 token to retire* @returns retirement transaction */ retire = async ( @@ -114,7 +118,7 @@ export default class ToucanClient { * @param beneficiaryAddress address of the beneficiary (in case you're retiring for someone else) * @param beneficiaryName name of the beneficiary * @param retirementMessage retirement message - * @param amount amount of TCO2 to retire + * @param amount The amount of TCO2 to retire * @param tco2Address address of the TCO2 token to retire* @returns retirement transaction */ retireAndMintCertificate = async ( @@ -143,7 +147,7 @@ export default class ToucanClient { * * @description retires/burns an amount of TCO2s from a different address/wallet * @notice requires approval from the address you're trying to retire from - * @param amount amount of TCO2 to retire + * @param amount The amount of TCO2 to retire * @param address address of the account to retire from * @param tco2Address address of the TCO2 token to retire* @returns retirement transaction */ @@ -213,15 +217,15 @@ export default class ToucanClient { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // Pool related methods + // Pool related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- /** * * @description deposits TCO2s in the pool which mints a pool token for the user - * @param pool symbol of the pool (token) to use - * @param amount amount of TCO2s to deposit + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of TCO2s to deposit * @param tco2Address address of the TCO2 token to deposit* @returns deposit transaction */ depositTCO2 = async ( @@ -243,7 +247,7 @@ export default class ToucanClient { /** * * @description checks if TCO2 is eligible for pool - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param tco2 address of TCO2 to deposit * @returns boolean */ @@ -261,11 +265,11 @@ export default class ToucanClient { /** * * @description calculates the fees to selectively redeem pool tokens for TCO2s - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param tco2s array of TCO2 contract addresses * @param amounts array of amounts to redeem for each tco2s * @notice tco2s must match amounts; amounts[0] is the amount of tco2[0] token to redeem for - * @returns amount (BigNumber) of fees it will cost to redeem + * @returns amount of fees it will cost to redeem. */ calculateRedeemFees = async ( pool: PoolSymbol, @@ -286,7 +290,7 @@ export default class ToucanClient { /** * * @description selectively redeems pool tokens for TCO2s - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param tco2s array of TCO2 contract addresses * @param amounts array of amounts to redeem for each tco2s * @returns redeem transaction @@ -305,7 +309,7 @@ export default class ToucanClient { /** * * @description automatically redeems pool tokens for TCO2s - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param amount amount to redeem * @returns redeem transaction */ @@ -323,7 +327,7 @@ export default class ToucanClient { * * @deprecated This function is deprecated. Please use `redeemAuto` instead. * @description automatically redeems pool tokens for TCO2s - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param amount amount to redeem * @returns array containing tco2 addresses (string) and amounts (BigNumber) */ @@ -353,7 +357,7 @@ export default class ToucanClient { /** * * @description gets an array of scored TCO2s; scoredTCO2s[0] is lowest ranked - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @returns array of TCO2 addresses by rank */ getScoredTCO2s = async (pool: PoolSymbol): Promise => { @@ -365,7 +369,7 @@ export default class ToucanClient { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // Contract registry related methods + // Contract registry related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- @@ -384,25 +388,91 @@ export default class ToucanClient { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // OffsetHelper related methods + // OffsetHelper related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- /** * - * @description allows user to retire carbon using carbon pool tokens from his wallet - * @notice this method may take up to even 1 minute to give a result - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to offset* @returns offset transaction + * @description retires carbon credits using the oldest TCO2 + * tokens available by sending pool tokens, e.g., NCT. + * @notice This method may take up to 1 minute to return a result + * @param pool The pool symbol of the pool token to offset, + * e.g., NCT + * @param amount The amount of of TCO2 to offset. + * @returns The offset transaction. + */ + autoOffsetPoolToken = async ( + pool: PoolSymbol, + amount: BigNumber + ): Promise => { + if (!this.signer) throw new Error("No signer set"); + + const signer = this.signer; + + return this.contractInteractions.autoOffsetPoolToken(pool, amount, signer); + }; + + /** + * + * @description retires a specified amount of carbon credits using the lowest + * quality (oldest) TCO2 tokens available from the specified Toucan token pool by sending ERC20 + * tokens (cUSD, USDC, WETH, WMATIC). + * @notice this method needs two different actions signed and may take up to 1 minute to return a result + * @param swapToken portal for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC) + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of CO2 tons to offset + * @returns The offset transaction. */ - autoOffsetUsingPoolToken = async ( + autoOffsetExactOutToken = async ( + swapToken: string, + pool: PoolSymbol, + amount: BigNumber + ): Promise => { + if (!this.signer) throw new Error("No signer set"); + + const signer = this.signer; + + const iface = new Interface(ERC20ABI); + iface.format(FormatTypes.full); + const token = new ethers.Contract(swapToken, iface, signer); + + return this.contractInteractions.autoOffsetExactOutToken( + token, + pool, + amount, + signer + ); + }; + + /** +/** + * + * @description retires carbon credits using the oldest TCO2 tokens available from the specified Toucan token pool by sending ERC20 + * tokens (cUSD, USDC, WETH, WMATIC). All provided tokens are consumed for offsetting. + * @notice this method needs two different actions signed and may take up to 1 minute to return a result + * @dev When automatically redeeming pool tokens for the oldest ones + * TCO2s there are no fees and you receive exactly 1 TCO2 token for 1 pool + * token. + * @param swapToken portal for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC) + * @param pool The pool symbol of the pool (token) to use + * @param amount the amount of ERC20 token to swap into Toucan pool token. Full amount will be used for offsetting. + * @returns The offset transaction. + */ + autoOffsetExactInToken = async ( + swapToken: string, pool: PoolSymbol, amount: BigNumber ): Promise => { if (!this.signer) throw new Error("No signer set"); const signer = this.signer; - return this.contractInteractions.autoOffsetUsingPoolToken( + const iface = new Interface(ERC20ABI); + iface.format(FormatTypes.full); + const token = new ethers.Contract(swapToken, iface, signer); + + return this.contractInteractions.autoOffsetExactInToken( + token, pool, amount, signer @@ -411,81 +481,97 @@ export default class ToucanClient { /** * - * @description swaps given token for carbon pool tokens and uses them to retire carbon - * @notice this method may take up to even 1 minute to give a result - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to offset - * @param swapToken portal for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC)* @returns offset transaction + * @description retires a specified amount of carbon credits using the oldest TCO2 tokens available from the specified Toucan token pool by sending a native token e.g. MATIC. + * @dev Use `calculateNeededETHAmount()` first in order to find out how much of the native token e.g. MATIC is required to retire the specified quantity of TCO2. If the user sends much native token e.g. MATIC, the leftover amount will be sent back to the user. + * @notice This method may take up to 1 minute to return a result + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of CO2 tons to offset + * @returns The offset transaction. */ - autoOffsetUsingSwapToken = async ( + autoOffsetExactOutETH = async ( pool: PoolSymbol, - amount: BigNumber, - swapToken: Contract + amount: BigNumber ): Promise => { + if (this.network === "celo") + throw new Error("The function is not available on Celo."); if (!this.signer) throw new Error("No signer set"); const signer = this.signer; - return this.contractInteractions.autoOffsetUsingSwapToken( + return this.contractInteractions.autoOffsetExactOutETH( pool, amount, - swapToken, signer ); }; - /** * - * @description swaps ETH for carbon pool tokens and uses them to retire carbon - * @notice this method may take up to even 1 minute to give a result - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to offset* @returns offset transaction + * @description Swaps ETH for carbon pool tokens and uses them to retire carbon + * @notice This method may take up to 1 minute to return a result + * @param pool The pool symbol of the pool (token) to use e.g., "NCT" + * @param amount the amount of native tokens e.g., MATIC to swap into Toucan pool token. Full amount will be used for offsetting. + * @returns The offset transaction. */ - autoOffsetUsingETH = async ( + autoOffsetExactInETH = async ( pool: PoolSymbol, amount: BigNumber ): Promise => { + if (this.network === "celo") + throw new Error("The function is not available on Celo."); if (!this.signer) throw new Error("No signer set"); const signer = this.signer; - return this.contractInteractions.autoOffsetUsingETH(pool, amount, signer); + return this.contractInteractions.autoOffsetExactInETH(pool, amount, signer); }; /** * - * @description calculates the needed amount of tokens to send to offset - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to calculate for - * @param swapToken contract of the token to use in swap - * @returns amount (BigNumber) of swapToken needed to deposit + * @description Calculates how much of the specified ERC20 token is required in + * order to swap for the desired amount of a Toucan pool token, for + * example, e.g., NCT. + * @param swapToken The ERC20 token used for the swap + * @param pool The pool symbol of the pool token to swap for, + * e.g., NCT + * @param amount The desired amount of pool token to receive + * @returns amount of the ERC20 token required in order to + * swap for the specified amount of the pool token. */ calculateNeededTokenAmount = async ( + swapToken: string, pool: PoolSymbol, - amount: BigNumber, - swapToken: Contract + amount: BigNumber ): Promise => { const signerOrProvider = this.signer ? this.signer : this.provider; if (!signerOrProvider) throw new Error("No signer or provider set"); + const iface = new Interface(ERC20ABI); + iface.format(FormatTypes.full); + const token = new ethers.Contract(swapToken, iface, signerOrProvider); + return this.contractInteractions.calculateNeededTokenAmount( + token, pool, amount, - swapToken, signerOrProvider ); }; /** * - * @description calculates the needed amount of ETH to send to offset; ETH = native currency of network you are on - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to calculate for - * @returns amount (BigNumber) of ETH needed to deposit; ETH = native currency of network you are on + * @description Calculates the amount of native tokens e.g, MATIC is required in order to swap for the + * desired amount of a Toucan pool token, e.g., NCT. + * @param pool The pool symbol of the pool token to swap for, + * e.g., NCT + * @param amount The desired amount of pool token to receive + * @returns amount of native tokens, e.g., MATIC required in order to swap for + * the specified amount of the pool token. */ calculateNeededETHAmount = async ( pool: PoolSymbol, amount: BigNumber ): Promise => { const signerOrProvider = this.signer ? this.signer : this.provider; + if (this.network === "celo") + throw new Error("The function is not available on Celo."); if (!signerOrProvider) throw new Error("No signer or provider set"); return this.contractInteractions.calculateNeededETHAmount( @@ -495,6 +581,62 @@ export default class ToucanClient { ); }; + /** + * + * @description Calculates the expected amount of Toucan Pool token that can be + * acquired by swapping the provided amount of ERC20 token. + * + * @param swapToken The ERC20 token used for the swap + * @param pool The pool symbol of the pool token to swap for, + * e.g., NCT + * @param amount The amount of ERC20 token to swap + * @returns amount The expected amount of Pool token that can be acquired. + */ + calculateExpectedPoolTokenForToken = async ( + swapToken: string, + pool: PoolSymbol, + amount: BigNumber + ): Promise => { + const signerOrProvider = this.signer ? this.signer : this.provider; + if (!signerOrProvider) throw new Error("No signer or provider set"); + + const iface = new Interface(ERC20ABI); + iface.format(FormatTypes.full); + const token = new ethers.Contract(swapToken, iface, signerOrProvider); + + return this.contractInteractions.calculateExpectedPoolTokenForToken( + token, + pool, + amount, + signerOrProvider + ); + }; + + /** + * + * @description Calculates the expected amount of Toucan Pool token that can be + * acquired by swapping the provided amount of native tokens e.g., MATIC. + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of native tokens to swap for, + * e.g., MATIC + * @returns amount The expected amount of Pool token that can be acquired. + */ + calculateExpectedPoolTokenForETH = async ( + pool: PoolSymbol, + amount: BigNumber + ): Promise => { + const signerOrProvider = this.signer ? this.signer : this.provider; + if (this.network === "celo") + throw new Error("The function is not available on Celo."); + if (!signerOrProvider) throw new Error("No signer or provider set"); + + return this.contractInteractions.calculateExpectedPoolTokenForETH( + pool, + amount, + signerOrProvider + ); + }; + // -------------------------------------------------------------------------------- // Batches Subgraph Methods // -------------------------------------------------------------------------------- @@ -588,7 +730,7 @@ export default class ToucanClient { /** * * @description fetches redeems of a given pool - * @param pool symbol of pool to fetch for + * @param pool The pool symbol of pool to fetch for * @param first how many redeems you want fetched; defaults to 100 * @param skip how many (if any) redeems you want skipped; defaults to 0 * @returns an array of objects with properties of the redeems like id, amount, timestamp and more @@ -601,7 +743,7 @@ export default class ToucanClient { * * @description fetches redeems of a given pool and user * @param walletAddress address of the user/wallet to query for - * @param pool symbol of pool to fetch for + * @param pool The pool symbol of pool to fetch for * @param first how many redeems you want fetched; defaults to 100 * @param skip how many (if any) redeems you want skipped; defaults to 0 * @returns an array of objects with properties of the redeems like id, amount, timestamp and more @@ -627,7 +769,7 @@ export default class ToucanClient { /** * * @description fetches TCO2 tokens that are part of the given pool - * @param pool symbol of the pool to fetch for + * @param pool The pool symbol of the pool to fetch for * @param first how many TCO2 tokens you want fetched; defaults to 1000 * @param skip how many (if any) retirements you want skipped; defaults to 0 * @returns an array of objects representing TCO2 tokens and containing properties like name, amount, methodology and more @@ -684,7 +826,7 @@ export default class ToucanClient { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // Price / Sushiswap related methods + // Price / Sushiswap related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- @@ -706,7 +848,7 @@ export default class ToucanClient { /** * * @description gets the contract of a pool token based on the symbol - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @returns a ethers.contract to interact with the pool */ public getPoolAddress = (pool: PoolSymbol): string => { diff --git a/src/subclasses/ContractInteractions.ts b/src/subclasses/ContractInteractions.ts index 99b9b45..346ff48 100644 --- a/src/subclasses/ContractInteractions.ts +++ b/src/subclasses/ContractInteractions.ts @@ -1,6 +1,6 @@ /** The OffsetHelper's purpose is to simplify the carbon offsetting process. - Copyright (C) 2022 Toucan Labs + Copyright (C) 2022 Toucan Labs This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -9,11 +9,11 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . */ import { @@ -34,11 +34,12 @@ import { Network, PoolSymbol } from "../types"; import { RedeemAutoResponse } from "../types/responses"; import { GAS_LIMIT } from "../utils"; import { + offsetHelperABI, poolTokenABI, tco2ABI, toucanContractRegistryABI, } from "../utils/ABIs"; -import addresses, { IfcOneNetworksAddresses } from "../utils/addresses"; +import addresses, { INetworkTokenAddresses } from "../utils/addresses"; /** * @class ContractInteractions @@ -46,7 +47,7 @@ import addresses, { IfcOneNetworksAddresses } from "../utils/addresses"; */ class ContractInteractions { network: Network; - addresses: IfcOneNetworksAddresses; + addresses: INetworkTokenAddresses; /** * @@ -59,14 +60,16 @@ class ContractInteractions { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // TCO2 related methods + // TCO2 related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- /** * - * @description retires/burns an amount of TCO2s (each represents 1 ton of CO2) to achieve offset - * @param amount amount of TCO2 to retire + * @description retires/offset/burns an amount of TCO2s (each represents 1 ton of CO2). + * If you don't own any TCO2s you need to buy pool tokens, e.g., + * NCTs on a DEX and redeem these first. + * @param amount The amount of TCO2 to retire * @param tco2Address address of the TCO2 token to retire * @param signer this being a write transaction, we need a signer * @returns retirement transaction @@ -87,12 +90,13 @@ class ContractInteractions { /** * - * @description retires/burns an amount of TCO2s & mints the NFT certificate for it within the same transaction + * @description retires/offset/burns an amount of TCO2s & mints the NFT certificate for it within the same transaction. If you don't own any TCO2s you need to buy pool tokens, e.g., + * NCTs on a DEX and redeem these first. * @param retirementEntityName name of the entity that does the retirement (you) * @param beneficiaryAddress address of the beneficiary (in case you're retiring for someone else) * @param beneficiaryName name of the beneficiary * @param retirementMessage retirement message - * @param amount amount of TCO2 to retire + * @param amount The amount of TCO2 to retire * @param tco2Address address of the TCO2 token to retire * @param signer this being a write transaction, we need a signer * @returns retirement transaction @@ -114,17 +118,17 @@ class ContractInteractions { beneficiaryAddress, beneficiaryName, retirementMessage, - amount, - { gasLimit: GAS_LIMIT } + amount ); return await retirementTxn.wait(); }; /** * - * @description retires/burns an amount of TCO2s from a different address/wallet + * @description retires/offset/burns an amount of TCO2s from a different address/wallet. If you don't own any TCO2s you need to buy pool tokens, e.g., + * NCTs on a DEX and redeem these first. * @notice requires approval from the address you're trying to retire from - * @param amount amount of TCO2 to retire + * @param amount The amount of TCO2 to retire * @param address address of the account to retire from * @param tco2Address address of the TCO2 token to retire * @param signer this being a write transaction, we need a signer @@ -197,15 +201,15 @@ class ContractInteractions { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // Pool related methods + // Pool related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- /** * * @description deposits TCO2s in the pool which mints a pool token for the user - * @param pool symbol of the pool (token) to use - * @param amount amount of TCO2s to deposit + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of TCO2s to deposit * @param tco2Address address of the TCO2 token to deposit * @param signer this being a write transaction, we need a signer * @returns deposit transaction @@ -228,8 +232,7 @@ class ContractInteractions { const depositTxn: ContractTransaction = await poolToken.deposit( tco2Address, - amount, - { gasLimit: GAS_LIMIT } + amount ); return await depositTxn.wait(); }; @@ -237,7 +240,7 @@ class ContractInteractions { /** * * @description checks if TCO2 is eligible for pool - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param tco2 address of TCO2 to deposit * @returns boolean */ @@ -253,22 +256,12 @@ class ContractInteractions { /** * * @description calculates the fees to selectively redeem pool tokens for TCO2s - * @param pool symbol of the pool (token) to use - * @param tco2s array of TCO2 contract addresses - * @param amounts array of amounts to redeem for each tco2s - * @notice tco2s must match amounts; amounts[0] is the amount of tco2[0] token to redeem for - * @returns amount (BigNumber) of fees it will cost to redeem - */ - - /** - * - * @description calculates the fees to selectively redeem pool tokens for TCO2s - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param tco2s array of TCO2 contract addresses * @param amounts array of amounts to redeem for each tco2s * @notice tco2s must match amounts; amounts[0] is the amount of tco2[0] token to redeem for * @param signerOrProvider this being a read transaction, we need a signer or provider - * @returns amount (BigNumber) of fees it will cost to redeem + * @returns amount The amount of fees it will cost to redeem */ calculateRedeemFees = async ( pool: PoolSymbol, @@ -283,7 +276,7 @@ class ContractInteractions { /** * * @description selectively redeems pool tokens for TCO2s - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param tco2s array of TCO2 contract addresses * @param amounts array of amounts to redeem for each tco2s * @param signer this being a write transaction, we need a signer @@ -299,8 +292,7 @@ class ContractInteractions { const redeemTxn: ContractTransaction = await poolToken.redeemMany( tco2s, - amounts, - { gasLimit: GAS_LIMIT } + amounts ); return await redeemTxn.wait(); }; @@ -308,8 +300,8 @@ class ContractInteractions { /** * * @description automatically redeems pool tokens for TCO2s - * @param pool symbol of the pool (token) to use - * @param amount amount to redeem + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount to redeem * @param signer this being a write transaction, we need a signer * @returns redeem transaction */ @@ -345,8 +337,8 @@ class ContractInteractions { /** * @deprecated This function is deprecated. Please use `redeemAuto` instead. * @description automatically redeems pool tokens for TCO2s - * @param pool symbol of the pool (token) to use - * @param amount amount to redeem + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount to redeem * @param signer this being a write transaction, we need a signer * @returns array containing tco2 addresses (string) and amounts (BigNumber) */ @@ -356,9 +348,7 @@ class ContractInteractions { signer: ethers.Signer ): Promise => { const poolToken = this.getPoolContract(pool, signer); - const redeemReceipt = await ( - await poolToken.redeemAuto2(amount, { gasLimit: GAS_LIMIT }) - ).wait(); + const redeemReceipt = await (await poolToken.redeemAuto2(amount)).wait(); if (!redeemReceipt.events) { throw new Error("No events to get tco2 addresses and amounts from"); @@ -397,7 +387,7 @@ class ContractInteractions { /** * * @description gets an array of scored TCO2s; scoredTCO2s[0] is lowest ranked - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @param signerOrProvider this being a read transaction, we need a signer or provider * @returns array of TCO2 addresses by rank */ @@ -411,7 +401,7 @@ class ContractInteractions { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // Contract registry related methods + // Contract registry related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- @@ -432,20 +422,21 @@ class ContractInteractions { // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- - // OffsetHelper related methods + // OffsetHelper related functions // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- /** * - * @description allows user to retire carbon using carbon pool tokens from his wallet - * @notice this method may take up to even 1 minute to give a result - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to offset + * @description retires carbon credits using the oldest TCO2 + * tokens available by sending pool tokens, e.g., NCT. + * @param pool The pool symbol of the pool token to offset, + * e.g., NCT + * @param amount The amount of TCO2s to deposit * @param signer this being a write transaction, we need a signer - * @returns offset transaction + * @returns The offset transaction. */ - autoOffsetUsingPoolToken = async ( + autoOffsetPoolToken = async ( pool: PoolSymbol, amount: BigNumber, signer: ethers.Signer @@ -461,7 +452,7 @@ class ContractInteractions { const offsetHelper = this.getOffsetHelperContract(signer); const offsetTxn: ContractTransaction = - await offsetHelper.autoOffsetUsingPoolToken(this.addresses.nct, amount, { + await offsetHelper.autoOffsetPoolToken(this.addresses.nct, amount, { gasLimit: GAS_LIMIT, }); return await offsetTxn.wait(); @@ -469,18 +460,19 @@ class ContractInteractions { /** * - * @description swaps given token for carbon pool tokens and uses them to retire carbon - * @notice this method may take up to even 1 minute to give a result - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to offset + * @description Retire a specified amount of carbon credits using the oldest TCO2 tokens available from the specified pool by sending ERC20 + * tokens (cUSD, USDC, WETH, WMATIC). + * @notice This method needs two different actions signed and may take up to 1 minute to return a result * @param swapToken portal for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC) + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of CO2 tons to offset * @param signer this being a write transaction, we need a signer * @returns offset transaction */ - autoOffsetUsingSwapToken = async ( + autoOffsetExactOutToken = async ( + swapToken: Contract, pool: PoolSymbol, amount: BigNumber, - swapToken: Contract, signer: ethers.Signer ): Promise => { const poolAddress = this.getPoolAddress(pool); @@ -497,25 +489,63 @@ class ContractInteractions { await approveTxn.wait(); const offsetTxn: ContractTransaction = - await offsetHelper.autoOffsetUsingToken( + await offsetHelper.autoOffsetExactOutToken( swapToken.address, poolAddress, - amount, - { gasLimit: GAS_LIMIT } + amount ); return await offsetTxn.wait(); }; /** * - * @description swaps ETH for carbon pool tokens and uses them to retire carbon - * @notice this method may take up to even 1 minute to give a result - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to offset + * @description retire carbon credits using the oldest TCO2 tokens available from the specified pool by sending ERC20 + * tokens (cUSD, USDC, WETH, WMATIC). All provided tokens are consumed for offsetting. + * @notice This method needs two different actions signed and may take up to 1 minute to return a result + * @dev When automatically redeeming pool tokens for the oldest ones + * TCO2s there are no fees and you receive exactly 1 TCO2 token for 1 pool + * token. + * @param swapToken portal for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC) + * @param pool The pool symbol of the pool (token) to use + * @param amount the amount of ERC20 token to swap into Toucan pool token. Full amount will be used for offsetting. + * @param signer this being a write transaction, we need a signer + * @returns offset transaction + */ + autoOffsetExactInToken = async ( + swapToken: Contract, + pool: PoolSymbol, + amount: BigNumber, + signer: ethers.Signer + ): Promise => { + const poolAddress = this.getPoolAddress(pool); + const offsetHelper = this.getOffsetHelperContract(signer); + + const approveTxn: ContractTransaction = await swapToken.approve( + this.addresses.offsetHelper, + amount + ); + await approveTxn.wait(); + + const offsetTxn: ContractTransaction = + await offsetHelper.autoOffsetExactInToken( + swapToken.address, + poolAddress, + amount + ); + return await offsetTxn.wait(); + }; + + /** + * + * @description Retire a specified amount of carbon credits using the oldest TCO2 tokens available from the specified pool by sending a native token e.g. MATIC. + * @dev Use `calculateNeededETHAmount()` first in order to find out how much of the native token e.g. MATIC is required to retire the specified quantity of TCO2. If the user sends much native token e.g. MATIC, the leftover amount will be sent back to the user. + * @notice This method may take up to 1 minute to return a result + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of CO2 tons to offset * @param signer this being a write transaction, we need a signer * @returns offset transaction */ - autoOffsetUsingETH = async ( + autoOffsetExactOutETH = async ( pool: PoolSymbol, amount: BigNumber, signer: ethers.Signer @@ -524,7 +554,7 @@ class ContractInteractions { const poolAddress = this.getPoolAddress(pool); const offsetTxn: ContractTransaction = - await offsetHelper.autoOffsetUsingETH(poolAddress, amount, { + await offsetHelper.autoOffsetExactOutETH(poolAddress, amount, { gasLimit: GAS_LIMIT, value: await offsetHelper.calculateNeededETHAmount(poolAddress, amount), }); @@ -533,17 +563,46 @@ class ContractInteractions { /** * - * @description calculates the needed amount of tokens to send to offset - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to calculate for - * @param swapToken contract of the token to use in swap + * @description swaps ETH for carbon pool tokens and uses them to retire carbon + * @notice This method may take up to 1 minute to return a result + * @param pool The pool symbol of the pool (token) to use e.g., "NCT" + * @param amount the amount of native tokens e.g., MATIC to swap into Toucan pool token. Full amount will be used for offsetting. + * @param signer this being a write transaction, we need a signer + * @returns offset transaction + */ + autoOffsetExactInETH = async ( + pool: PoolSymbol, + amount: BigNumber, + signer: ethers.Signer + ): Promise => { + const offsetHelper = this.getOffsetHelperContract(signer); + const poolAddress = this.getPoolAddress(pool); + + const offsetTxn: ContractTransaction = + await offsetHelper.autoOffsetExactInETH(poolAddress, { + gasLimit: GAS_LIMIT, + value: amount, + }); + return await offsetTxn.wait(); + }; + + /** + * + * @description Calculates how much of the specified ERC20 token is required in + * order to swap for the desired amount of a Toucan pool token, for + * example, e.g., NCT. + * @param swapToken The ERC20 token used for the swap + * @param pool The pool symbol of the pool token to swap for, + * e.g., NCT + * @param amount The desired amount of pool token to receive * @param signerOrProvider this being a read transaction, we need a signer or provider - * @returns amount (BigNumber) of swapToken needed to deposit + * @returns amount The amount of the ERC20 token required in order to + * swap for the specified amount of the pool token */ calculateNeededTokenAmount = async ( + swapToken: Contract, pool: PoolSymbol, amount: BigNumber, - swapToken: Contract, signerOrProvider: ethers.Signer | ethers.providers.Provider ): Promise => { const offsetHelper = this.getOffsetHelperContract(signerOrProvider); @@ -556,11 +615,14 @@ class ContractInteractions { /** * - * @description calculates the needed amount of ETH to send to offset; ETH = native currency of network you are on - * @param pool symbol of the pool (token) to use - * @param amount amount of CO2 tons to calculate for + * @description Calculates the amount of native tokens e.g, MATIC is required in order to swap for the + * desired amount of a Toucan pool token, e.g., NCT. + * @param pool The pool symbol of the pool token to swap for, + * e.g., NCT + * @param amount The desired amount of pool token to receive * @param signerOrProvider this being a read transaction, we need a signer or provider - * @returns amount (BigNumber) of ETH needed to deposit; ETH = native currency of network you are on + * @returns amount The amount of native tokens, e.g., MATIC required in order to swap for + * the specified amount of the pool token */ calculateNeededETHAmount = async ( pool: PoolSymbol, @@ -574,6 +636,54 @@ class ContractInteractions { ); }; + /** + * + * @description Calculates the expected amount of Toucan Pool token that can be + * acquired by swapping the provided amount of ERC20 token. + * + * @param swapToken The ERC20 token used for the swap + * @param pool The pool symbol of the pool token to swap for, + * e.g., NCT + * @param amount The amount of ERC20 token to swap + * @param signerOrProvider this being a read transaction, we need a signer or provider + * @returns amount The amount The expected amount of Pool token that can be acquired + */ + calculateExpectedPoolTokenForToken = async ( + swapToken: Contract, + pool: PoolSymbol, + amount: BigNumber, + signerOrProvider: ethers.Signer | ethers.providers.Provider + ): Promise => { + const offsetHelper = this.getOffsetHelperContract(signerOrProvider); + return await offsetHelper.calculateExpectedPoolTokenForToken( + swapToken.address, + this.getPoolAddress(pool), + amount + ); + }; + + /** + * + * @description Calculates the expected amount of Toucan Pool token that can be + * acquired by swapping the provided amount of native tokens e.g., MATIC. + * @param pool The pool symbol of the pool (token) to use + * @param amount The amount of native tokens to swap for, + * e.g., MATIC + * @param signerOrProvider this being a read transaction, we need a signer or provider + * @returns amount The amount The expected amount of Pool token that can be acquired + */ + calculateExpectedPoolTokenForETH = async ( + pool: PoolSymbol, + amount: BigNumber, + signerOrProvider: ethers.Signer | ethers.providers.Provider + ): Promise => { + const offsetHelper = this.getOffsetHelperContract(signerOrProvider); + return await offsetHelper.calculateExpectedPoolTokenForETH( + this.getPoolAddress(pool), + amount + ); + }; + // -------------------------------------------------------------------------------- // Internal methods // -------------------------------------------------------------------------------- @@ -581,7 +691,7 @@ class ContractInteractions { /** * * @description gets the contract of a pool token based on the symbol - * @param pool symbol of the pool (token) to use + * @param pool The pool symbol of the pool (token) to use * @returns a ethers.contract to interact with the pool */ public getPoolAddress = (pool: PoolSymbol): string => { @@ -657,7 +767,12 @@ class ContractInteractions { public getOffsetHelperContract = ( signerOrProvider: ethers.Signer | ethers.providers.Provider ): OffsetHelper => { - throw new Error("OffsetHelper is not supported yet"); + const OffsetHelper = new ethers.Contract( + this.addresses.offsetHelper, + offsetHelperABI, + signerOrProvider + ) as OffsetHelper; + return OffsetHelper; }; } diff --git a/src/subclasses/SubgraphInteractions.ts b/src/subclasses/SubgraphInteractions.ts index faf2485..df3e76f 100644 --- a/src/subclasses/SubgraphInteractions.ts +++ b/src/subclasses/SubgraphInteractions.ts @@ -39,7 +39,7 @@ import { TCO2TokenResponse, } from "../types/responses"; import { PairSchema } from "../types/schemas"; -import addresses, { IfcOneNetworksAddresses } from "../utils/addresses"; +import addresses, { INetworkTokenAddresses } from "../utils/addresses"; import { getDexGraphClient, getToucanGraphClient } from "../utils/graphClients"; /** @@ -48,7 +48,7 @@ import { getDexGraphClient, getToucanGraphClient } from "../utils/graphClients"; */ class SubgraphInteractions { network: Network; - addresses: IfcOneNetworksAddresses; + addresses: INetworkTokenAddresses; TCO2: IToucanCarbonOffsets | undefined; graphClient: Client; @@ -80,7 +80,11 @@ class SubgraphInteractions { * @param walletAddress address of user to query for * @returns an array of BatchTokens (they contain different properties of the Batch) */ - fetchUserBatches: UserBatchesMethod = async (walletAddress) => { + fetchUserBatches: UserBatchesMethod = async ( + walletAddress, + first = 100, + skip = 0 + ) => { const query = gql` query ($walletAddress: String) { users(id: $walletAddress) { @@ -106,7 +110,7 @@ class SubgraphInteractions { `; const result = await this.graphClient - .query(query, { walletAddress: walletAddress }) + .query(query, { walletAddress, first, skip }) .toPromise(); if (result.error) throw result.error; @@ -143,7 +147,7 @@ class SubgraphInteractions { } `; - const result = await this.graphClient.query(query, { id: id }).toPromise(); + const result = await this.graphClient.query(query, { id }).toPromise(); if (result.error) throw result.error; if (result.data?.tco2Tokens) return result.data.tco2Tokens; @@ -190,10 +194,8 @@ class SubgraphInteractions { * @description fetches TCO2Details of all TCO2s * @returns an array of TCO2Detail objects with properties of the TCO2s (name, address, etc) */ - fetchAllTCO2Tokens: AllTCO2TokensMethod = async () => { + fetchAllTCO2Tokens: AllTCO2TokensMethod = async (first = 1000, skip = 0) => { let TCO2Tokens: TCO2TokenResponse[] = []; - let skip = 0; - const first = 1000; for (;;) { const query = gql` query ($first: Int, $skip: Int) { @@ -211,7 +213,7 @@ class SubgraphInteractions { } `; const result = await this.graphClient - .query(query, { first: first, skip: skip }) + .query(query, { first, skip }) .toPromise(); if (result.error) throw result.error; @@ -238,10 +240,12 @@ class SubgraphInteractions { * @description fetches data about BatchTokens that have been bridged * @returns an array of BatchTokens containing different properties like id, serialNumber or quantity */ - fetchBridgedBatchTokens: BridgedBatchTokensMethod = async () => { + fetchBridgedBatchTokens: BridgedBatchTokensMethod = async ( + first = 1000, + skip = 0 + ) => { let BridgedBatchTokens: BridgedBatchTokensResponse[] = []; - let skip = 0; - const first = 1000; + for (;;) { const query = gql` query ($retirementStatus: Int, $first: Int, $skip: Int) { @@ -266,8 +270,8 @@ class SubgraphInteractions { const result = await this.graphClient .query(query, { retirementStatus: 2, // RetirementStatus.Confirmed = 2 - first: first, - skip: skip, + first, + skip, }) .toPromise(); @@ -346,7 +350,7 @@ class SubgraphInteractions { `; const result = await this.graphClient - .query(query, { walletAddress: walletAddress, first: first, skip: skip }) + .query(query, { walletAddress: walletAddress, first, skip }) .toPromise(); if (result.error) throw result.error; @@ -401,7 +405,7 @@ class SubgraphInteractions { `; const result = await this.graphClient - .query(query, { poolAddress: poolAddress, first: first, skip: skip }) + .query(query, { poolAddress, first, skip }) .toPromise(); if (result.error) throw result.error; @@ -465,10 +469,10 @@ class SubgraphInteractions { const result = await this.graphClient .query(query, { - walletAddress: walletAddress, - poolAddress: poolAddress, - first: first, - skip: skip, + walletAddress, + poolAddress, + first, + skip, }) .toPromise(); @@ -523,9 +527,9 @@ class SubgraphInteractions { const result = await this.graphClient .query(query, { - poolAddress: poolAddress, - first: first, - skip: skip, + poolAddress, + first, + skip, }) .toPromise(); @@ -559,7 +563,7 @@ class SubgraphInteractions { } `; - const result = await this.graphClient.query(query, { id: id }).toPromise(); + const result = await this.graphClient.query(query, { id }).toPromise(); if (result.error) throw result.error; if (result.data?.project) return result.data.project; diff --git a/src/typechain/OffsetHelper.d.ts b/src/typechain/OffsetHelper.d.ts index ce82d6a..1a2eda5 100644 --- a/src/typechain/OffsetHelper.d.ts +++ b/src/typechain/OffsetHelper.d.ts @@ -22,15 +22,19 @@ import type { TypedEventFilter, TypedEvent, TypedListener } from "./common"; interface OffsetHelperInterface extends ethers.utils.Interface { functions: { - "autoOffsetUsingETH(address,uint256)": FunctionFragment; - "autoOffsetUsingPoolToken(address,uint256)": FunctionFragment; - "autoOffsetUsingToken(address,address,uint256)": FunctionFragment; + "addPath(string,address[])": FunctionFragment; + "addPoolToken(address)": FunctionFragment; + "autoOffsetExactInETH(address)": FunctionFragment; + "autoOffsetExactInToken(address,address,uint256)": FunctionFragment; + "autoOffsetExactOutETH(address,uint256)": FunctionFragment; + "autoOffsetExactOutToken(address,address,uint256)": FunctionFragment; + "autoOffsetPoolToken(address,uint256)": FunctionFragment; "autoRedeem(address,uint256)": FunctionFragment; "autoRetire(address[],uint256[])": FunctionFragment; - "balances(address,address)": FunctionFragment; + "calculateExpectedPoolTokenForETH(address,uint256)": FunctionFragment; + "calculateExpectedPoolTokenForToken(address,address,uint256)": FunctionFragment; "calculateNeededETHAmount(address,uint256)": FunctionFragment; "calculateNeededTokenAmount(address,address,uint256)": FunctionFragment; - "deposit(address,uint256)": FunctionFragment; "dexRouterAddress()": FunctionFragment; "eligibleSwapPaths(address,uint256)": FunctionFragment; "eligibleSwapPathsBySymbol(string,uint256)": FunctionFragment; @@ -48,21 +52,36 @@ interface OffsetHelperInterface extends ethers.utils.Interface { "swapExactOutToken(address,address,uint256)": FunctionFragment; "tokenSymbolsForPaths(uint256)": FunctionFragment; "transferOwnership(address)": FunctionFragment; - "withdraw(address,uint256)": FunctionFragment; }; encodeFunctionData( - functionFragment: "autoOffsetUsingETH", - values: [string, BigNumberish] + functionFragment: "addPath", + values: [string, string[]] + ): string; + encodeFunctionData( + functionFragment: "addPoolToken", + values: [string] ): string; encodeFunctionData( - functionFragment: "autoOffsetUsingPoolToken", + functionFragment: "autoOffsetExactInETH", + values: [string] + ): string; + encodeFunctionData( + functionFragment: "autoOffsetExactInToken", + values: [string, string, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "autoOffsetExactOutETH", values: [string, BigNumberish] ): string; encodeFunctionData( - functionFragment: "autoOffsetUsingToken", + functionFragment: "autoOffsetExactOutToken", values: [string, string, BigNumberish] ): string; + encodeFunctionData( + functionFragment: "autoOffsetPoolToken", + values: [string, BigNumberish] + ): string; encodeFunctionData( functionFragment: "autoRedeem", values: [string, BigNumberish] @@ -72,8 +91,12 @@ interface OffsetHelperInterface extends ethers.utils.Interface { values: [string[], BigNumberish[]] ): string; encodeFunctionData( - functionFragment: "balances", - values: [string, string] + functionFragment: "calculateExpectedPoolTokenForETH", + values: [string, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "calculateExpectedPoolTokenForToken", + values: [string, string, BigNumberish] ): string; encodeFunctionData( functionFragment: "calculateNeededETHAmount", @@ -83,10 +106,6 @@ interface OffsetHelperInterface extends ethers.utils.Interface { functionFragment: "calculateNeededTokenAmount", values: [string, string, BigNumberish] ): string; - encodeFunctionData( - functionFragment: "deposit", - values: [string, BigNumberish] - ): string; encodeFunctionData( functionFragment: "dexRouterAddress", values?: undefined @@ -121,7 +140,6 @@ interface OffsetHelperInterface extends ethers.utils.Interface { functionFragment: "removePoolToken", values: [string] ): string; - encodeFunctionData(functionFragment: "owner", values?: undefined): string; encodeFunctionData( functionFragment: "renounceOwnership", values?: undefined @@ -150,26 +168,42 @@ interface OffsetHelperInterface extends ethers.utils.Interface { functionFragment: "transferOwnership", values: [string] ): string; - encodeFunctionData( - functionFragment: "withdraw", - values: [string, BigNumberish] - ): string; + decodeFunctionResult(functionFragment: "addPath", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "addPoolToken", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "autoOffsetExactInETH", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "autoOffsetExactInToken", + data: BytesLike + ): Result; decodeFunctionResult( - functionFragment: "autoOffsetUsingETH", + functionFragment: "autoOffsetExactOutETH", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "autoOffsetUsingPoolToken", + functionFragment: "autoOffsetExactOutToken", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "autoOffsetUsingToken", + functionFragment: "autoOffsetPoolToken", data: BytesLike ): Result; decodeFunctionResult(functionFragment: "autoRedeem", data: BytesLike): Result; decodeFunctionResult(functionFragment: "autoRetire", data: BytesLike): Result; - decodeFunctionResult(functionFragment: "balances", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "calculateExpectedPoolTokenForETH", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "calculateExpectedPoolTokenForToken", + data: BytesLike + ): Result; decodeFunctionResult( functionFragment: "calculateNeededETHAmount", data: BytesLike @@ -178,9 +212,16 @@ interface OffsetHelperInterface extends ethers.utils.Interface { functionFragment: "calculateNeededTokenAmount", data: BytesLike ): Result; - decodeFunctionResult(functionFragment: "deposit", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "eligibleTokenAddresses", + functionFragment: "dexRouterAddress", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "eligibleSwapPaths", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "eligibleSwapPathsBySymbol", data: BytesLike ): Result; decodeFunctionResult( @@ -199,11 +240,11 @@ interface OffsetHelperInterface extends ethers.utils.Interface { ): Result; decodeFunctionResult(functionFragment: "removePath", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "renounceOwnership", + functionFragment: "removePoolToken", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "setEligibleTokenAddress", + functionFragment: "renounceOwnership", data: BytesLike ): Result; decodeFunctionResult( @@ -222,7 +263,6 @@ interface OffsetHelperInterface extends ethers.utils.Interface { functionFragment: "swapExactOutToken", data: BytesLike ): Result; - decodeFunctionResult(functionFragment: "swap", data: BytesLike): Result; decodeFunctionResult( functionFragment: "tokenSymbolsForPaths", data: BytesLike @@ -231,7 +271,6 @@ interface OffsetHelperInterface extends ethers.utils.Interface { functionFragment: "transferOwnership", data: BytesLike ): Result; - decodeFunctionResult(functionFragment: "withdraw", data: BytesLike): Result; events: { "OwnershipTransferred(address,address)": EventFragment; @@ -248,7 +287,7 @@ export type OwnershipTransferredEvent = TypedEvent< export type RedeemedEvent = TypedEvent< [string, string, string[], BigNumber[]] & { - who: string; + sender: string; poolToken: string; tco2s: string[]; amounts: BigNumber[]; @@ -299,20 +338,43 @@ export class OffsetHelper extends BaseContract { interface: OffsetHelperInterface; functions: { - autoOffsetUsingETH( + addPath( + _tokenSymbol: string, + _path: string[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + addPoolToken( + _poolToken: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInETH( + _poolToken: string, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInToken( + _fromToken: string, + _poolToken: string, + _amountToSwap: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactOutETH( _poolToken: string, _amountToOffset: BigNumberish, overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - autoOffsetUsingPoolToken( + autoOffsetExactOutToken( + _fromToken: string, _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; - autoOffsetUsingToken( - _depositedToken: string, + autoOffsetPoolToken( _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } @@ -330,12 +392,6 @@ export class OffsetHelper extends BaseContract { overrides?: Overrides & { from?: string | Promise } ): Promise; - balances( - arg0: string, - arg1: string, - overrides?: CallOverrides - ): Promise<[BigNumber]>; - calculateExpectedPoolTokenForETH( _poolToken: string, _fromTokenAmount: BigNumberish, @@ -350,31 +406,29 @@ export class OffsetHelper extends BaseContract { ): Promise<[BigNumber] & { amountOut: BigNumber }>; calculateNeededETHAmount( - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise<[BigNumber] & { amountIn: BigNumber }>; calculateNeededTokenAmount( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise<[BigNumber] & { amountIn: BigNumber }>; - deleteEligibleTokenAddress( - _tokenSymbol: string, - overrides?: Overrides & { from?: string | Promise } - ): Promise; + dexRouterAddress(overrides?: CallOverrides): Promise<[string]>; - deposit( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } - ): Promise; + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides + ): Promise<[string]>; - eligibleTokenAddresses( + eligibleSwapPathsBySymbol( arg0: string, + arg1: BigNumberish, overrides?: CallOverrides ): Promise<[string]>; @@ -420,10 +474,23 @@ export class OffsetHelper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - "swap(address,address,uint256)"( + swapExactInToken( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _fromAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + swapExactOutETH( + _poolToken: string, + _toAmount: BigNumberish, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + swapExactOutToken( + _fromToken: string, + _poolToken: string, + _toAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -436,28 +503,45 @@ export class OffsetHelper extends BaseContract { newOwner: string, overrides?: Overrides & { from?: string | Promise } ): Promise; - - withdraw( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } - ): Promise; }; - autoOffsetUsingETH( + addPath( + _tokenSymbol: string, + _path: string[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + addPoolToken( + _poolToken: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInETH( + _poolToken: string, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInToken( + _fromToken: string, + _poolToken: string, + _amountToSwap: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactOutETH( _poolToken: string, _amountToOffset: BigNumberish, overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - autoOffsetUsingPoolToken( + autoOffsetExactOutToken( + _fromToken: string, _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; - autoOffsetUsingToken( - _depositedToken: string, + autoOffsetPoolToken( _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } @@ -475,33 +559,43 @@ export class OffsetHelper extends BaseContract { overrides?: Overrides & { from?: string | Promise } ): Promise; - balances( - arg0: string, - arg1: string, + calculateExpectedPoolTokenForETH( + _poolToken: string, + _fromTokenAmount: BigNumberish, + overrides?: CallOverrides + ): Promise; + + calculateExpectedPoolTokenForToken( + _fromToken: string, + _poolToken: string, + _fromAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededETHAmount( - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededTokenAmount( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; - deposit( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } - ): Promise; + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides + ): Promise; - eligibleTokenAddresses( + eligibleSwapPathsBySymbol( arg0: string, + arg1: BigNumberish, overrides?: CallOverrides ): Promise; @@ -544,10 +638,23 @@ export class OffsetHelper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - "swap(address,address,uint256)"( + swapExactInToken( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _fromAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + swapExactOutETH( + _poolToken: string, + _toAmount: BigNumberish, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + swapExactOutToken( + _fromToken: string, + _poolToken: string, + _toAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -561,14 +668,32 @@ export class OffsetHelper extends BaseContract { overrides?: Overrides & { from?: string | Promise } ): Promise; - withdraw( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } - ): Promise; - callStatic: { - autoOffsetUsingETH( + addPath( + _tokenSymbol: string, + _path: string[], + overrides?: CallOverrides + ): Promise; + + addPoolToken(_poolToken: string, overrides?: CallOverrides): Promise; + + autoOffsetExactInETH( + _poolToken: string, + overrides?: CallOverrides + ): Promise< + [string[], BigNumber[]] & { tco2s: string[]; amounts: BigNumber[] } + >; + + autoOffsetExactInToken( + _fromToken: string, + _poolToken: string, + _amountToSwap: BigNumberish, + overrides?: CallOverrides + ): Promise< + [string[], BigNumber[]] & { tco2s: string[]; amounts: BigNumber[] } + >; + + autoOffsetExactOutETH( _poolToken: string, _amountToOffset: BigNumberish, overrides?: CallOverrides @@ -576,7 +701,8 @@ export class OffsetHelper extends BaseContract { [string[], BigNumber[]] & { tco2s: string[]; amounts: BigNumber[] } >; - autoOffsetUsingPoolToken( + autoOffsetExactOutToken( + _fromToken: string, _poolToken: string, _amountToOffset: BigNumberish, overrides?: CallOverrides @@ -584,8 +710,7 @@ export class OffsetHelper extends BaseContract { [string[], BigNumber[]] & { tco2s: string[]; amounts: BigNumber[] } >; - autoOffsetUsingToken( - _depositedToken: string, + autoOffsetPoolToken( _poolToken: string, _amountToOffset: BigNumberish, overrides?: CallOverrides @@ -607,33 +732,43 @@ export class OffsetHelper extends BaseContract { overrides?: CallOverrides ): Promise; - balances( - arg0: string, - arg1: string, + calculateExpectedPoolTokenForETH( + _poolToken: string, + _fromTokenAmount: BigNumberish, + overrides?: CallOverrides + ): Promise; + + calculateExpectedPoolTokenForToken( + _fromToken: string, + _poolToken: string, + _fromAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededETHAmount( - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededTokenAmount( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; - deposit( - _erc20Addr: string, - _amount: BigNumberish, + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, overrides?: CallOverrides - ): Promise; + ): Promise; - eligibleTokenAddresses( + eligibleSwapPathsBySymbol( arg0: string, + arg1: BigNumberish, overrides?: CallOverrides ): Promise; @@ -662,9 +797,8 @@ export class OffsetHelper extends BaseContract { removePath(_tokenSymbol: string, overrides?: CallOverrides): Promise; - setEligibleTokenAddress( - _tokenSymbol: string, - _address: string, + removePoolToken( + _poolToken: string, overrides?: CallOverrides ): Promise; @@ -688,10 +822,10 @@ export class OffsetHelper extends BaseContract { overrides?: CallOverrides ): Promise; - "swap(address,address,uint256)"( + swapExactOutToken( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; @@ -704,12 +838,6 @@ export class OffsetHelper extends BaseContract { newOwner: string, overrides?: CallOverrides ): Promise; - - withdraw( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: CallOverrides - ): Promise; }; filters: { @@ -730,41 +858,74 @@ export class OffsetHelper extends BaseContract { >; "Redeemed(address,address,address[],uint256[])"( - who?: null, + sender?: null, poolToken?: null, tco2s?: null, amounts?: null ): TypedEventFilter< [string, string, string[], BigNumber[]], - { who: string; poolToken: string; tco2s: string[]; amounts: BigNumber[] } + { + sender: string; + poolToken: string; + tco2s: string[]; + amounts: BigNumber[]; + } >; Redeemed( - who?: null, + sender?: null, poolToken?: null, tco2s?: null, amounts?: null ): TypedEventFilter< [string, string, string[], BigNumber[]], - { who: string; poolToken: string; tco2s: string[]; amounts: BigNumber[] } + { + sender: string; + poolToken: string; + tco2s: string[]; + amounts: BigNumber[]; + } >; }; estimateGas: { - autoOffsetUsingETH( + addPath( + _tokenSymbol: string, + _path: string[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + addPoolToken( + _poolToken: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInETH( + _poolToken: string, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInToken( + _fromToken: string, + _poolToken: string, + _amountToSwap: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactOutETH( _poolToken: string, _amountToOffset: BigNumberish, overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - autoOffsetUsingPoolToken( + autoOffsetExactOutToken( + _fromToken: string, _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; - autoOffsetUsingToken( - _depositedToken: string, + autoOffsetPoolToken( _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } @@ -782,33 +943,43 @@ export class OffsetHelper extends BaseContract { overrides?: Overrides & { from?: string | Promise } ): Promise; - balances( - arg0: string, - arg1: string, + calculateExpectedPoolTokenForETH( + _poolToken: string, + _fromTokenAmount: BigNumberish, + overrides?: CallOverrides + ): Promise; + + calculateExpectedPoolTokenForToken( + _fromToken: string, + _poolToken: string, + _fromAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededETHAmount( - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededTokenAmount( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; - deposit( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides ): Promise; - eligibleTokenAddresses( + eligibleSwapPathsBySymbol( arg0: string, + arg1: BigNumberish, overrides?: CallOverrides ): Promise; @@ -854,10 +1025,23 @@ export class OffsetHelper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - "swap(address,address,uint256)"( + swapExactInToken( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _fromAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + swapExactOutETH( + _poolToken: string, + _toAmount: BigNumberish, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + swapExactOutToken( + _fromToken: string, + _poolToken: string, + _toAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -870,29 +1054,46 @@ export class OffsetHelper extends BaseContract { newOwner: string, overrides?: Overrides & { from?: string | Promise } ): Promise; - - withdraw( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } - ): Promise; }; populateTransaction: { - autoOffsetUsingETH( + addPath( + _tokenSymbol: string, + _path: string[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + addPoolToken( + _poolToken: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInETH( + _poolToken: string, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactInToken( + _fromToken: string, + _poolToken: string, + _amountToSwap: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + autoOffsetExactOutETH( _poolToken: string, _amountToOffset: BigNumberish, overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - autoOffsetUsingPoolToken( + autoOffsetExactOutToken( + _fromToken: string, _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; - autoOffsetUsingToken( - _depositedToken: string, + autoOffsetPoolToken( _poolToken: string, _amountToOffset: BigNumberish, overrides?: Overrides & { from?: string | Promise } @@ -910,33 +1111,43 @@ export class OffsetHelper extends BaseContract { overrides?: Overrides & { from?: string | Promise } ): Promise; - balances( - arg0: string, - arg1: string, + calculateExpectedPoolTokenForETH( + _poolToken: string, + _fromTokenAmount: BigNumberish, + overrides?: CallOverrides + ): Promise; + + calculateExpectedPoolTokenForToken( + _fromToken: string, + _poolToken: string, + _fromAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededETHAmount( - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; calculateNeededTokenAmount( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _toAmount: BigNumberish, overrides?: CallOverrides ): Promise; - deposit( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides ): Promise; - eligibleTokenAddresses( + eligibleSwapPathsBySymbol( arg0: string, + arg1: BigNumberish, overrides?: CallOverrides ): Promise; @@ -982,10 +1193,23 @@ export class OffsetHelper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - "swap(address,address,uint256)"( + swapExactInToken( _fromToken: string, - _toToken: string, - _amount: BigNumberish, + _poolToken: string, + _fromAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + swapExactOutETH( + _poolToken: string, + _toAmount: BigNumberish, + overrides?: PayableOverrides & { from?: string | Promise } + ): Promise; + + swapExactOutToken( + _fromToken: string, + _poolToken: string, + _toAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -998,11 +1222,5 @@ export class OffsetHelper extends BaseContract { newOwner: string, overrides?: Overrides & { from?: string | Promise } ): Promise; - - withdraw( - _erc20Addr: string, - _amount: BigNumberish, - overrides?: Overrides & { from?: string | Promise } - ): Promise; }; } diff --git a/src/typechain/Swapper.d.ts b/src/typechain/Swapper.d.ts index dbb5756..c7435c7 100644 --- a/src/typechain/Swapper.d.ts +++ b/src/typechain/Swapper.d.ts @@ -22,9 +22,10 @@ import type { TypedEventFilter, TypedEvent, TypedListener } from "./common"; interface SwapperInterface extends ethers.utils.Interface { functions: { "calculateNeededETHAmount(address,uint256)": FunctionFragment; - "sushiRouterAddress()": FunctionFragment; + "dexRouterAddress()": FunctionFragment; + "eligibleSwapPaths(address,uint256)": FunctionFragment; "swap(address,uint256)": FunctionFragment; - "tokenAddresses(string)": FunctionFragment; + "swapToken()": FunctionFragment; }; encodeFunctionData( @@ -32,31 +33,33 @@ interface SwapperInterface extends ethers.utils.Interface { values: [string, BigNumberish] ): string; encodeFunctionData( - functionFragment: "sushiRouterAddress", + functionFragment: "dexRouterAddress", values?: undefined ): string; encodeFunctionData( - functionFragment: "swap", + functionFragment: "eligibleSwapPaths", values: [string, BigNumberish] ): string; encodeFunctionData( - functionFragment: "tokenAddresses", - values: [string] + functionFragment: "swap", + values: [string, BigNumberish] ): string; + encodeFunctionData(functionFragment: "swapToken", values?: undefined): string; decodeFunctionResult( functionFragment: "calculateNeededETHAmount", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "sushiRouterAddress", + functionFragment: "dexRouterAddress", data: BytesLike ): Result; - decodeFunctionResult(functionFragment: "swap", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "tokenAddresses", + functionFragment: "eligibleSwapPaths", data: BytesLike ): Result; + decodeFunctionResult(functionFragment: "swap", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "swapToken", data: BytesLike): Result; events: {}; } @@ -111,7 +114,13 @@ export class Swapper extends BaseContract { overrides?: CallOverrides ): Promise<[BigNumber]>; - sushiRouterAddress(overrides?: CallOverrides): Promise<[string]>; + dexRouterAddress(overrides?: CallOverrides): Promise<[string]>; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides + ): Promise<[string]>; swap( _toToken: string, @@ -119,7 +128,7 @@ export class Swapper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - tokenAddresses(arg0: string, overrides?: CallOverrides): Promise<[string]>; + swapToken(overrides?: CallOverrides): Promise<[string]>; }; calculateNeededETHAmount( @@ -128,7 +137,13 @@ export class Swapper extends BaseContract { overrides?: CallOverrides ): Promise; - sushiRouterAddress(overrides?: CallOverrides): Promise; + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides + ): Promise; swap( _toToken: string, @@ -136,7 +151,7 @@ export class Swapper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - tokenAddresses(arg0: string, overrides?: CallOverrides): Promise; + swapToken(overrides?: CallOverrides): Promise; callStatic: { calculateNeededETHAmount( @@ -145,7 +160,13 @@ export class Swapper extends BaseContract { overrides?: CallOverrides ): Promise; - sushiRouterAddress(overrides?: CallOverrides): Promise; + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides + ): Promise; swap( _toToken: string, @@ -153,7 +174,7 @@ export class Swapper extends BaseContract { overrides?: CallOverrides ): Promise; - tokenAddresses(arg0: string, overrides?: CallOverrides): Promise; + swapToken(overrides?: CallOverrides): Promise; }; filters: {}; @@ -165,7 +186,13 @@ export class Swapper extends BaseContract { overrides?: CallOverrides ): Promise; - sushiRouterAddress(overrides?: CallOverrides): Promise; + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, + overrides?: CallOverrides + ): Promise; swap( _toToken: string, @@ -173,7 +200,7 @@ export class Swapper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - tokenAddresses(arg0: string, overrides?: CallOverrides): Promise; + swapToken(overrides?: CallOverrides): Promise; }; populateTransaction: { @@ -183,7 +210,11 @@ export class Swapper extends BaseContract { overrides?: CallOverrides ): Promise; - sushiRouterAddress( + dexRouterAddress(overrides?: CallOverrides): Promise; + + eligibleSwapPaths( + arg0: string, + arg1: BigNumberish, overrides?: CallOverrides ): Promise; @@ -193,9 +224,6 @@ export class Swapper extends BaseContract { overrides?: PayableOverrides & { from?: string | Promise } ): Promise; - tokenAddresses( - arg0: string, - overrides?: CallOverrides - ): Promise; + swapToken(overrides?: CallOverrides): Promise; }; } diff --git a/src/utils/ABIs.ts b/src/utils/ABIs.ts index eea0ef1..3da0d9a 100644 --- a/src/utils/ABIs.ts +++ b/src/utils/ABIs.ts @@ -2019,15 +2019,25 @@ export const poolTokenABI = [ export const offsetHelperABI = [ { inputs: [ + { + internalType: "address[]", + name: "_poolAddresses", + type: "address[]", + }, { internalType: "string[]", - name: "_eligibleTokenSymbols", + name: "_tokenSymbolsForPaths", type: "string[]", }, { - internalType: "address[]", - name: "_eligibleTokenAddresses", - type: "address[]", + internalType: "address[][]", + name: "_paths", + type: "address[][]", + }, + { + internalType: "address", + name: "_dexRouterAddress", + type: "address", }, ], stateMutability: "nonpayable", @@ -2071,7 +2081,7 @@ export const offsetHelperABI = [ { indexed: false, internalType: "address", - name: "who", + name: "sender", type: "address", }, { @@ -2100,11 +2110,129 @@ export const offsetHelperABI = [ stateMutability: "payable", type: "fallback", }, + { + inputs: [ + { + internalType: "string", + name: "_tokenSymbol", + type: "string", + }, + { + internalType: "address[]", + name: "_path", + type: "address[]", + }, + ], + name: "addPath", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_poolToken", + type: "address", + }, + ], + name: "addPoolToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_poolToken", + type: "address", + }, + ], + name: "autoOffsetExactInETH", + outputs: [ + { + internalType: "address[]", + name: "tco2s", + type: "address[]", + }, + { + internalType: "uint256[]", + name: "amounts", + type: "uint256[]", + }, + ], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_fromToken", + type: "address", + }, + { + internalType: "address", + name: "_poolToken", + type: "address", + }, + { + internalType: "uint256", + name: "_amountToSwap", + type: "uint256", + }, + ], + name: "autoOffsetExactInToken", + outputs: [ + { + internalType: "address[]", + name: "tco2s", + type: "address[]", + }, + { + internalType: "uint256[]", + name: "amounts", + type: "uint256[]", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_poolToken", + type: "address", + }, + { + internalType: "uint256", + name: "_amountToOffset", + type: "uint256", + }, + ], + name: "autoOffsetExactOutETH", + outputs: [ + { + internalType: "address[]", + name: "tco2s", + type: "address[]", + }, + { + internalType: "uint256[]", + name: "amounts", + type: "uint256[]", + }, + ], + stateMutability: "payable", + type: "function", + }, { inputs: [ { internalType: "address", - name: "_depositedToken", + name: "_fromToken", type: "address", }, { @@ -2236,22 +2364,22 @@ export const offsetHelperABI = [ }, { inputs: [ - { - internalType: "uint256", - name: "_fromMaticAmount", - type: "uint256", - }, { internalType: "address", - name: "_toToken", + name: "_poolToken", type: "address", }, + { + internalType: "uint256", + name: "_fromTokenAmount", + type: "uint256", + }, ], name: "calculateExpectedPoolTokenForETH", outputs: [ { internalType: "uint256", - name: "", + name: "amountOut", type: "uint256", }, ], @@ -2265,22 +2393,22 @@ export const offsetHelperABI = [ name: "_fromToken", type: "address", }, + { + internalType: "address", + name: "_poolToken", + type: "address", + }, { internalType: "uint256", name: "_fromAmount", type: "uint256", }, - { - internalType: "address", - name: "_toToken", - type: "address", - }, ], name: "calculateExpectedPoolTokenForToken", outputs: [ { internalType: "uint256", - name: "", + name: "amountOut", type: "uint256", }, ], @@ -2291,7 +2419,7 @@ export const offsetHelperABI = [ inputs: [ { internalType: "address", - name: "_toToken", + name: "_poolToken", type: "address", }, { @@ -2304,7 +2432,7 @@ export const offsetHelperABI = [ outputs: [ { internalType: "uint256", - name: "", + name: "amountIn", type: "uint256", }, ], @@ -2320,7 +2448,7 @@ export const offsetHelperABI = [ }, { internalType: "address", - name: "_toToken", + name: "_poolToken", type: "address", }, { @@ -2333,7 +2461,7 @@ export const offsetHelperABI = [ outputs: [ { internalType: "uint256", - name: "", + name: "amountIn", type: "uint256", }, ], @@ -2341,47 +2469,58 @@ export const offsetHelperABI = [ type: "function", }, { - inputs: [], - name: "contractRegistryAddress", - outputs: [ + inputs: [ { internalType: "address", - name: "", + name: "_erc20Addr", type: "address", }, + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, ], - stateMutability: "view", + name: "deposit", + outputs: [], + stateMutability: "nonpayable", type: "function", }, { - inputs: [ + inputs: [], + name: "dexRouterAddress", + outputs: [ { - internalType: "string", - name: "_tokenSymbol", - type: "string", + internalType: "address", + name: "", + type: "address", }, ], - name: "deleteEligibleTokenAddress", - outputs: [], - stateMutability: "nonpayable", + stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", - name: "_erc20Addr", + name: "", type: "address", }, { internalType: "uint256", - name: "_amount", + name: "", type: "uint256", }, ], - name: "deposit", - outputs: [], - stateMutability: "nonpayable", + name: "eligibleSwapPaths", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", type: "function", }, { @@ -2391,21 +2530,13 @@ export const offsetHelperABI = [ name: "", type: "string", }, - ], - name: "eligibleTokenAddresses", - outputs: [ { - internalType: "address", + internalType: "uint256", name: "", - type: "address", + type: "uint256", }, ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "owner", + name: "eligibleSwapPathsBySymbol", outputs: [ { internalType: "address", @@ -2418,87 +2549,115 @@ export const offsetHelperABI = [ }, { inputs: [], - name: "renounceOwnership", + name: "initialize", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ - { - internalType: "string", - name: "_tokenSymbol", - type: "string", - }, { internalType: "address", - name: "_address", + name: "_erc20Address", type: "address", }, ], - name: "setEligibleTokenAddress", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ + name: "isERC20AddressEligible", + outputs: [ { - internalType: "address", - name: "_address", - type: "address", + internalType: "address[]", + name: "_path", + type: "address[]", }, ], - name: "setToucanContractRegistry", - outputs: [], - stateMutability: "nonpayable", + stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", - name: "_toToken", + name: "_poolToken", type: "address", }, ], - name: "swapExactInETH", + name: "isPoolAddressEligible", outputs: [ { - internalType: "uint256", - name: "", - type: "uint256", + internalType: "bool", + name: "_isEligible", + type: "bool", }, ], - stateMutability: "payable", + stateMutability: "view", type: "function", }, { - inputs: [ + inputs: [], + name: "owner", + outputs: [ { internalType: "address", - name: "_fromToken", + name: "", type: "address", }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ { internalType: "uint256", - name: "_fromAmount", + name: "", type: "uint256", }, { - internalType: "address", - name: "_toToken", - type: "address", - }, + internalType: "uint256", + name: "", + type: "uint256", + }, ], - name: "swapExactInToken", + name: "paths", outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ { internalType: "uint256", name: "", type: "uint256", }, ], + name: "poolAddresses", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "_tokenSymbol", + type: "string", + }, + ], + name: "removePath", + outputs: [], stateMutability: "nonpayable", type: "function", }, @@ -2506,17 +2665,38 @@ export const offsetHelperABI = [ inputs: [ { internalType: "address", - name: "_toToken", + name: "_poolToken", + type: "address", + }, + ], + name: "removePoolToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_poolToken", type: "address", }, + ], + name: "swapExactInETH", + outputs: [ { internalType: "uint256", - name: "_toAmount", + name: "amountOut", type: "uint256", }, ], - name: "swapExactOutETH", - outputs: [], stateMutability: "payable", type: "function", }, @@ -2529,7 +2709,31 @@ export const offsetHelperABI = [ }, { internalType: "address", - name: "_toToken", + name: "_poolToken", + type: "address", + }, + { + internalType: "uint256", + name: "_fromAmount", + type: "uint256", + }, + ], + name: "swapExactInToken", + outputs: [ + { + internalType: "uint256", + name: "amountOut", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_poolToken", type: "address", }, { @@ -2538,37 +2742,66 @@ export const offsetHelperABI = [ type: "uint256", }, ], - name: "swapExactOutToken", + name: "swapExactOutETH", outputs: [], - stateMutability: "nonpayable", + stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", - name: "newOwner", + name: "_fromToken", + type: "address", + }, + { + internalType: "address", + name: "_poolToken", type: "address", }, + { + internalType: "uint256", + name: "_toAmount", + type: "uint256", + }, ], - name: "transferOwnership", + name: "swapExactOutToken", outputs: [], stateMutability: "nonpayable", type: "function", }, { - inputs: [], - name: "ubeswapRouterAddress", + inputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "tokenSymbolsForPaths", outputs: [ { - internalType: "address", + internalType: "string", name: "", - type: "address", + type: "string", }, ], stateMutability: "view", type: "function", }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [ { @@ -2596,34 +2829,102 @@ export const offsetHelperABI = [ export const swapperABI = [ { inputs: [ - { internalType: "string[]", name: "_tokenSymbols", type: "string[]" }, - { internalType: "address[]", name: "_tokenAddresses", type: "address[]" }, + { + internalType: "address[][]", + name: "_paths", + type: "address[][]", + }, + { + internalType: "address", + name: "_swapToken", + type: "address", + }, + { + internalType: "address", + name: "_dexRouterAddress", + type: "address", + }, ], stateMutability: "nonpayable", type: "constructor", }, - { stateMutability: "payable", type: "fallback" }, + { + stateMutability: "payable", + type: "fallback", + }, { inputs: [ - { internalType: "address", name: "_toToken", type: "address" }, - { internalType: "uint256", name: "_amount", type: "uint256" }, + { + internalType: "address", + name: "_toToken", + type: "address", + }, + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, ], name: "calculateNeededETHAmount", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], stateMutability: "view", type: "function", }, { inputs: [], - name: "sushiRouterAddress", - outputs: [{ internalType: "address", name: "", type: "address" }], + name: "dexRouterAddress", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "eligibleSwapPaths", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], stateMutability: "view", type: "function", }, { inputs: [ - { internalType: "address", name: "_toToken", type: "address" }, - { internalType: "uint256", name: "_amount", type: "uint256" }, + { + internalType: "address", + name: "_toToken", + type: "address", + }, + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, ], name: "swap", outputs: [], @@ -2631,13 +2932,22 @@ export const swapperABI = [ type: "function", }, { - inputs: [{ internalType: "string", name: "", type: "string" }], - name: "tokenAddresses", - outputs: [{ internalType: "address", name: "", type: "address" }], + inputs: [], + name: "swapToken", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], stateMutability: "view", type: "function", }, - { stateMutability: "payable", type: "receive" }, + { + stateMutability: "payable", + type: "receive", + }, ]; export const tco2ABI = [ @@ -4068,3 +4378,398 @@ export const toucanContractRegistryABI = [ type: "function", }, ]; + +export const ERC20ABI = [ + { + inputs: [ + { internalType: "address", name: "childChainManager", type: "address" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "addr2", + 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: false, + internalType: "address", + name: "userAddress", + type: "address", + }, + { + indexed: false, + internalType: "address payable", + name: "relayerAddress", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "functionSignature", + type: "bytes", + }, + ], + name: "MetaTransactionExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + 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", + }, + { + inputs: [], + name: "CHILD_CHAIN_ID", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CHILD_CHAIN_ID_BYTES", + outputs: [{ internalType: "bytes", name: "", type: "bytes" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEPOSITOR_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "ERC712_VERSION", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "ROOT_CHAIN_ID", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "ROOT_CHAIN_ID_BYTES", + outputs: [{ internalType: "bytes", name: "", type: "bytes" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "addr2", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "subtractedValue", type: "uint256" }, + ], + name: "decreaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "user", type: "address" }, + { internalType: "bytes", name: "depositData", type: "bytes" }, + ], + name: "deposit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "userAddress", type: "address" }, + { internalType: "bytes", name: "functionSignature", type: "bytes" }, + { internalType: "bytes32", name: "sigR", type: "bytes32" }, + { internalType: "bytes32", name: "sigS", type: "bytes32" }, + { internalType: "uint8", name: "sigV", type: "uint8" }, + ], + name: "executeMetaTransaction", + outputs: [{ internalType: "bytes", name: "", type: "bytes" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [], + name: "getChainId", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "getDomainSeperator", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "user", type: "address" }], + name: "getNonce", + outputs: [{ internalType: "uint256", name: "nonce", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleAdmin", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "uint256", name: "index", type: "uint256" }, + ], + name: "getRoleMember", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleMemberCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasRole", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "addedValue", type: "uint256" }, + ], + name: "increaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "recipient", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + 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" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "amount", type: "uint256" }], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; diff --git a/src/utils/addresses.ts b/src/utils/addresses.ts index 05a79ae..538bdb7 100644 --- a/src/utils/addresses.ts +++ b/src/utils/addresses.ts @@ -1,4 +1,4 @@ -export interface IfcOneNetworksAddresses { +export interface INetworkTokenAddresses { bct: string; nct: string; offsetHelper: string; @@ -7,26 +7,26 @@ export interface IfcOneNetworksAddresses { toucanContractRegistry: string; } -export interface IfcAddresses { - celo: IfcOneNetworksAddresses; - alfajores: IfcOneNetworksAddresses; - polygon: IfcOneNetworksAddresses; - mumbai: IfcOneNetworksAddresses; +export interface INetworkAddresses { + celo: INetworkTokenAddresses; + alfajores: INetworkTokenAddresses; + polygon: INetworkTokenAddresses; + mumbai: INetworkTokenAddresses; } -const addresses: IfcAddresses = { +const addresses: INetworkAddresses = { celo: { bct: "0x0CcB0071e8B8B716A2a5998aB4d97b83790873Fe", nct: "0x02De4766C272abc10Bc88c220D214A26960a7e92", - offsetHelper: "", + offsetHelper: "0x4242829D15434Fea6606CF995f1BEd68a18C37d1", weth: "0x122013fd7dF1C6F636a5bb8f03108E876548b455", - swapper: "", + swapper: "0x7B99c68012F78f9D15BA9EA4121aB3e09914Be70", toucanContractRegistry: "0xa30589F50b9641dacCB98AA2B4A8F24739c5B007", }, alfajores: { bct: "0x4c5f90C50Ca9F849bb75D93a393A4e1B6E68Accb", nct: "0xfb60a08855389F3c0A66b29aB9eFa911ed5cbCB5", - offsetHelper: "0xAcf9FD890F06e6F200339193a64c0952a164Cb9d", + offsetHelper: "0x0CcB0071e8B8B716A2a5998aB4d97b83790873Fe", weth: "", swapper: "0xa12A728656Fbc82dC25515b548b328E63B556572", toucanContractRegistry: "0x48E04110aa4691ec3E9493187e6e9A3dB613e6e4", @@ -34,16 +34,16 @@ const addresses: IfcAddresses = { polygon: { bct: "0x2f800db0fdb5223b3c3f354886d907a671414a7f", nct: "0xd838290e877e0188a4a44700463419ed96c16107", - offsetHelper: "0xFAFcCd01C395e4542BEed819De61f02f5562fAEa", - swapper: "0x1C7f2CCa1Cd52Aae8A25B7BA4b7800c153F48D70", + offsetHelper: "0x7cB7C0484d4F2324F51d81E2368823c20AEf8072", + swapper: "0xfca57EE8B62d8e4b9792bd68095c2520723c306d", weth: "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619", toucanContractRegistry: "0x263fa1c180889b3a3f46330f32a4a23287e99fc9", }, mumbai: { bct: "0xf2438a14f668b1bba53408346288f3d7c71c10a1", nct: "0x7becba11618ca63ead5605de235f6dd3b25c530e", - offsetHelper: "0x30dC279166DCFB69F52C91d6A3380dCa75D0fCa7", - swapper: "0xDd052AcA9AC1492a8b4F1432B68f11989903dE4d", + offsetHelper: "0x66B1B59F9D59413dDC1539122D7d5F6b70869717", + swapper: "0x68DF99A11BD292cB91d3Fb07272062eF339d6dc1", weth: "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", toucanContractRegistry: "0x6739d490670b2710dc7e79bb12e455de33ee1cb6", }, diff --git a/test/index.test.ts b/test/index.test.ts index 64c220c..e8a1c68 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -11,7 +11,7 @@ import { ethers } from "hardhat"; import ToucanClient from "../dist"; import { PoolSymbol } from "../dist/types"; -import { swapperABI } from "../dist/utils/ABIs"; +import { ERC20ABI, swapperABI } from "../dist/utils/ABIs"; import addresses from "../dist/utils/addresses"; const ONE_ETHER = parseEther("1.0"); @@ -22,9 +22,9 @@ describe("Testing Toucan-SDK contract interactions", function () { let toucan: ToucanClient; let swapper: Contract; const provider = new ethers.providers.JsonRpcProvider( - "https://matic-mainnet.chainstacklabs.com" + "https://rpc.ankr.com/polygon" ); - // change these three variables when testing the different networks + // change these two variables when testing the different networks const network = addresses.polygon; const networkName = "polygon"; @@ -104,17 +104,20 @@ describe("Testing Toucan-SDK contract interactions", function () { }); }); - describe.skip("Testing OffsetHelper related methods", function () { - it("Should retire 1 TCO2 using pool token deposit", async function () { + describe("Testing OffsetHelper related methods", function () { + it("Should retire 1 TCO2 using pool token #autoOffsetPoolToken", async function () { const pool = await toucan.getPoolContract("NCT"); - const state: any[] = []; + const state: Array<{ + nctSupply: BigNumber; + nctBalance: BigNumber; + }> = []; state.push({ nctSupply: await pool.totalSupply(), nctBalance: await pool.balanceOf(addr1.address), }); - await toucan.autoOffsetUsingPoolToken("NCT", ONE_ETHER); + await toucan.autoOffsetPoolToken("NCT", ONE_ETHER); state.push({ nctSupply: await pool.totalSupply(), @@ -132,26 +135,28 @@ describe("Testing Toucan-SDK contract interactions", function () { ).to.be.equal(formatEther(state[1].nctBalance)); }); - it("Should retire 1 TCO2 using swap token", async function () { - const iface = new Interface( - '[{"inputs":[{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr2","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":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","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"},{"inputs":[],"name":"CHILD_CHAIN_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHILD_CHAIN_ID_BYTES","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT_CHAIN_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT_CHAIN_ID_BYTES","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr2","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"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"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]' - ); + it("Should retire 1 TCO2 using swap token #autoOffsetExactInToken", async function () { + const iface = new Interface(ERC20ABI); iface.format(FormatTypes.full); const weth = new ethers.Contract(network.weth, iface, addr1); const pool = await toucan.getPoolContract("NCT"); - const state: any[] = []; + const state: Array<{ + nctSupply: BigNumber; + wethBalance: BigNumber; + }> = []; state.push({ nctSupply: await pool.totalSupply(), wethBalance: await weth.balanceOf(addr1.address), }); - const cost = await toucan.calculateNeededTokenAmount( + const cost = await toucan.calculateExpectedPoolTokenForToken( + weth.address, "NCT", - ONE_ETHER, - weth + ONE_ETHER ); - await toucan.autoOffsetUsingSwapToken("NCT", ONE_ETHER, weth); + + await toucan.autoOffsetExactInToken(network.weth, "NCT", ONE_ETHER); state.push({ nctSupply: await pool.totalSupply(), @@ -159,33 +164,88 @@ describe("Testing Toucan-SDK contract interactions", function () { }); expect( - formatEther(state[0].nctSupply.sub(ONE_ETHER)), - `Expect NCT supply to be less by 1.0` + formatEther(state[0].nctSupply.sub(cost)), + `Expect NCT supply to be less by ${formatEther(cost)}` ).to.be.equal(formatEther(state[1].nctSupply)); expect( - formatEther(state[0].wethBalance.sub(cost)), - `Expect addr1's WETH balance to be less by ${formatEther(cost)}` + formatEther(state[0].wethBalance.sub(ONE_ETHER)), + `Expect addr1's WETH balance to be less by 1.0` ).to.be.equal(formatEther(state[1].wethBalance)); }); - it("Should retire 1 TCO2 using ETH deposit", async function () { + it("Should retire 1 TCO2 using ETH (native token) #autoOffsetExactInETH)", async function () { + const pool = await toucan.getPoolContract("NCT"); + + const state: Array<{ + nctSupply: BigNumber; + nativeTokenBalance: BigNumber | any; + }> = []; + state.push({ + nctSupply: await pool.totalSupply(), + nativeTokenBalance: await addr1.getBalance(), + }); + + const cost = await toucan.calculateExpectedPoolTokenForETH( + "NCT", + ONE_ETHER + ); + + await toucan.autoOffsetExactInETH("NCT", ONE_ETHER); + + state.push({ + nctSupply: await pool.totalSupply(), + nativeTokenBalance: await addr1.getBalance(), + }); + + expect( + parseInt(state[0].nativeTokenBalance.sub(cost)), + `Expect native token, e.g., MATIC supply to be less by ${formatEther( + ONE_ETHER + )}` + ) + .to.be.greaterThanOrEqual(parseInt(state[1].nativeTokenBalance)) + .and.to.be.lessThan(parseInt(state[0].nativeTokenBalance)); + + expect( + formatEther(state[0].nctSupply.sub(cost)), + `Expect NCT supply to be less by ${formatEther(cost)}` + ).to.be.equal(formatEther(state[1].nctSupply)); + }); + + it("Should retire 1 TCO2 using ETH (native token) #autoOffsetExactOutETH)", async function () { const pool = await toucan.getPoolContract("NCT"); - const state: any[] = []; + const state: Array<{ + nctSupply: BigNumber; + nativeTokenBalance: BigNumber | any; + }> = []; state.push({ nctSupply: await pool.totalSupply(), + nativeTokenBalance: await addr1.getBalance(), }); - await toucan.autoOffsetUsingETH("NCT", ONE_ETHER); + const cost = await toucan.calculateNeededETHAmount("NCT", ONE_ETHER); + + await toucan.autoOffsetExactOutETH("NCT", ONE_ETHER); state.push({ nctSupply: await pool.totalSupply(), + nativeTokenBalance: await addr1.getBalance(), }); + expect( + parseInt(state[0].nativeTokenBalance.sub(cost)), + `Expect native token, e.g., MATIC supply to be less by ${formatEther( + cost + )}` + ) + .to.be.greaterThanOrEqual(parseInt(state[1].nativeTokenBalance)) + .and.to.be.lessThan(parseInt(state[0].nativeTokenBalance)); + expect( formatEther(state[0].nctSupply.sub(ONE_ETHER)), - `Expect NCT supply to be less by 1.0` + `Expect NCT supply to be less by ${formatEther(ONE_ETHER)}` ).to.be.equal(formatEther(state[1].nctSupply)); }); }); @@ -352,7 +412,10 @@ describe("Testing Toucan-SDK contract interactions", function () { const { address, amount } = tco2s[0]; const tco2 = toucan.getTCO2Contract(address); - const state: any[] = []; + const state: Array<{ + tco2Supply: BigNumber; + tco2Balance: BigNumber; + }> = []; state.push({ tco2Supply: await tco2.totalSupply(), tco2Balance: await tco2.balanceOf(addr1.address), @@ -387,7 +450,10 @@ describe("Testing Toucan-SDK contract interactions", function () { const { address, amount } = tco2s[0]; const tco2 = toucan.getTCO2Contract(address); - const state: any[] = []; + const state: Array<{ + tco2Supply: BigNumber; + tco2Balance: BigNumber; + }> = []; state.push({ tco2Supply: await tco2.totalSupply(), tco2Balance: await tco2.balanceOf(addr1.address), @@ -415,7 +481,10 @@ describe("Testing Toucan-SDK contract interactions", function () { const { address, amount } = tco2s[0]; const tco2 = toucan.getTCO2Contract(address); - const state: any[] = []; + const state: Array<{ + tco2Supply: BigNumber; + tco2Balance: BigNumber; + }> = []; state.push({ tco2Supply: await tco2.totalSupply(), tco2Balance: await tco2.balanceOf(addr1.address), diff --git a/yarn.lock b/yarn.lock index 88cd406..3fb5929 100644 --- a/yarn.lock +++ b/yarn.lock @@ -962,7 +962,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@^17.0.34": +"@types/node@*": version "17.0.34" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.34.tgz#3b0b6a50ff797280b8d000c6281d229f9c538cef" integrity sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA== @@ -1380,6 +1380,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-sequence-parser@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -5165,6 +5170,18 @@ handlebars@^4.0.1: optionalDependencies: uglify-js "^3.1.4" +handlebars@^4.7.7: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -6115,6 +6132,11 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -6589,6 +6611,11 @@ ltgt@~2.1.1: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" @@ -6611,6 +6638,11 @@ markdown-table@^1.1.3: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== +marked@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -6832,6 +6864,13 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" @@ -7093,7 +7132,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.6.0: +neo-async@^2.6.0, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -8569,6 +8608,16 @@ shelljs@^0.8.3: interpret "^1.0.0" rechoir "^0.6.2" +shiki@^0.14.1: + version "0.14.4" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.4.tgz#2454969b466a5f75067d0f2fa0d7426d32881b20" + integrity sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ== + dependencies: + ansi-sequence-parser "^1.1.0" + jsonc-parser "^3.2.0" + vscode-oniguruma "^1.7.0" + vscode-textmate "^8.0.0" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -9522,6 +9571,23 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typedoc-plugin-markdown@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.16.0.tgz#98da250271aafade8b6740a8116a97cd3941abcd" + integrity sha512-eeiC78fDNGFwemPIHiwRC+mEC7W5jwt3fceUev2gJ2nFnXpVHo8eRrpC9BLWZDee6ehnz/sPmNjizbXwpfaTBw== + dependencies: + handlebars "^4.7.7" + +typedoc@^0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.1.tgz#50de2d8fb93623fbfb59e2fa6407ff40e3d3f438" + integrity sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA== + dependencies: + lunr "^2.3.9" + marked "^4.3.0" + minimatch "^9.0.3" + shiki "^0.14.1" + typescript@^4.5.2: version "4.7.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" @@ -9788,6 +9854,16 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vscode-oniguruma@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" + integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== + +vscode-textmate@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" + integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== + web-streams-polyfill@^3.0.3: version "3.2.1" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"