This library is designed to simplify and standardise the process of fetching data and interacting with various DeFi protocols, which often have unique interfaces and data structures. Our adapters 1) fetch and transform underlying protocol data into a standardised format that can be easily used by portfolio dashboards and 2) generate transaction params to create and update protocol positions.
- Connect users with DeFi protocols
- Benefit the wider ecosystem
- Simplify and standardise adapter building
- Provide the following data in a standardised format:
- DeFi positions by address, including the balance of underlying tokens such as USDC, WETH, etc.
- Total Value Locked (TVL) by pool
- APY/APR by pool
- Daily profit and loss by address
- Unwrap LP tokens to underlying tokens (a.k.a get a price for the LP tokens)
- Deposits by address
- Withdrawals by address
- Crafted transactions params
Check out the tutorial video below for an intro to our library and how to build an adapter:
We offer a variety of templates to streamline the creation of new adapters using the command npm run new-adapter
. Below is a detailed overview of each template available:
- DefaultAdapter Template:
- Provides a basic adapter class framework, including all essential methods that require implementation.
- SimplePoolAdapter Template:
- Generates an adapter class inheriting a set of pre-implemented methods.
- Ideally suited for fungible liquidity pool (LP) tokens.
- UniswapV2PoolForkAdapter:
- Creates an adapter for Uniswap V2 fork projects, with minimal methods needing completion.
- LpStakingAdapter:
- Tailored for reward protocols, such as Convex.
- Ideally suited for fungible staking tokens which are fixed one-to-one to the underlying LP token.
- Supports optional Reward and Extra rewards functionalities.
Each template is designed to facilitate specific scenarios in the development of new adapters, ensuring a streamlined and efficient setup process.
This project requires Node 20. Ensure you're using the correct version (e.g. run nvm use
)
To build an adapter follow these steps:
- Install the necessary packages with
npm i
- Build the project with
npm run build:watch
- To build an adapter run:
npm run new-adapter
- To create a typescript-smart-contract class create a json file with your abi and add it to your ${protocolName}/contracts/abis/ folder, then run:
npm run build-types
- To build metadata files run (replace <protocol-id> with the id of your protocol):
npm run build-metadata -- -p <protocol-id>
- To build snapshot tests run (replace <protocol-id> with the id of your protocol):
npm run build-snapshots -- -p <protocol-id>
- To run tests run:
npm run test
- To test your adapter further you can use the following commands, update userAddress and other params accordingly:
npm run positions 0x6b8Be925ED8277fE4D27820aE4677e76Ebf4c255 -- --protocols stargate --chains 1,arbitrum
npm run profits 0xCEadFdCCd0E8E370D985c49Ed3117b2572243A4a
npm run tvl
npm run prices
npm run apr
npm run apy
npm run deposits 0x30cb2c51fc4f031fa5f326d334e1f5da00e19ab5 18262162 18262164 0xC36442b4a4522E871399CD717aBDD847Ab11FE88 pool uniswap-v3 1 573046
npm run withdrawals 0x4Ffc5F22770ab6046c8D66DABAe3A9CD1E7A03e7 17979753 17979755 0xdf0770df86a8034b3efef0a1bb3c889b8332ff56 pool stargate 1
Detailed documentation on the adapter methods can be found here.
The DeFi adapter library is the engine behind MetaMask's retail and institutional portfolio dashboards π¦.
In this example, the user holds positions in both Stargate and Uniswap.
As a adapter developer,
I want to implement a new DeFi adapter that follows the IProtocolAdapter interface,
So that MMI and MetaMask Portfolio users can view in-depth data related to their positions.
- Multiple Products Consideration: Ensure that protocols with multiple products (e.g., farming, staking, pools) are supported by one adapter each.
- Adapter Implementation: Successfully add a new DeFi adapter implementing the IProtocolAdapter to support the product.
- Add Adapter using CLI:
- Follow instructions in the "Adding a new Adapter (CLI)" section of the readme.
- Ethers Contracts Creation:
- Create ethers contracts to interact with the smart contracts of the protocol.
- Refer to the "Contract Factories" section in the readme for guidance.
- LP Token Metadata Building: Implement the
buildMetadata()
logic in the adapter to retrieve the LP token reference data and runnpm run build-metadata
. (e.g., Check out thebuildMetadata()
method in theStargatePoolAdapter
class. output example).- Testing: Test the adapter(s) using the commands specified in the readme.
The IProtocolAdapter interface has been documented with TSDocs, detailed descriptions of the methods and properties can be found here.
-
What is a DeFi adapter?
A DeFi adapter is code that standardises DeFi protocol data and positions, allowing for consistent data retrieval and interaction. It acts as a connector (a.k.a translator) between our dashboards and your DeFi products.
-
What do these adapters do?
They power the MetaMask portfolio dashboards, displaying users' DeFi positions.
-
What experience do I need to map an adapter?
Ideally experience in Typescript, Ethers library, and be familiar with the DeFi protocol.
-
Are these adapters deployed onchain?
No this adapter library is installed and deployed in microservices. The adapters are written in TypeScript (not solidity).
-
I'm not familiar with the protocol. Can I still map an adapter?
Yes. To assist you refer to the protocol docs, smart contracts, find example open positions and review deposits and withdrawals to the position.
-
How long does it take to map an adapter?
A few hours for those with knowledge of Typescript, Ethers, and the DeFi protocol.
-
How do you calculate profits?
- We capture users' positions from 7 days ago using the
get positions
adapter method with ablocknumber override
. - We then obtain the current positions.
- To account for deposits and withdrawals in this period, we examine
mint
andburn
events of LP tokens and convert these back to underlying tokens. - We found this method works for the majority of protocols. However, adapt as necessary for your protocol. For example, if there are better event logs available for your protocol, use them.
- We capture users' positions from 7 days ago using the
-
Some adapter methods don't make sense for my DeFi-protocol?
Throw an error: new Error('Does not apply').
-
Can I use an API for results?
We recommend getting data directly from the blockchain over centralized APIs.
-
My protocol only has a few pools, can I hardcode the buildMetadata() result?
Yes. Feel free to hardcode this result if it doesn't make sense to fetch pool data on chain.
-
My protocol has more than one product, should I create separate adapters?
Yes. We find this reduces complexity.
-
Im getting
>> TypeError: Cannot read properties of undefined (reading 'F_OK')
error when runningnpm run new-adapter
Make sure you are using Node 20. Run
nvm use
-
How can I share feedback or proposals?
Please reach out to us directly. We value feedback.
From left to right, get-onchain-data and convert to standardise format.
See CONTRIBUTING.md.
- Node v20
To get specific details on available commands, run npm run adapters-cli
. For arguments and options for specific commands, use npm run positions -- --help
.
This project requires Node 18. Ensure you're using the correct version (e.g. run nvm use
)
Run the following command to add a new adapter npm run new-adapter
This will start an interactive process in the command line to create a new adapter. Running npm run new-adapter -- --help
shows available options for defaults.
Add a JSON file with the ABI of any new contract to the folder src/adapter/<protocol-name>/contracts/abis
. Run npm run build-types
to generate factories and ABIs for those contracts automatically.
In order to maintain integrity, it is possible to create test snapshots.
Tests can be added to src/adapters/<protocol-name>/tests/testCases.ts
by adding them to the exported testCases
array. The test object is fully typed.
A test needs to include:
chainId
: Chain for which the test will runmethod
: One of the available public methods of the libraryinput
: If the testmethod
requires input, such as an user address, it needs to be specified here.blockNumber
: For some tests, it is possible to specify which block number should be used. If it's not provided, the snapshot will be created with the latest block number, which will be stored along with the snapshot.key
: When there are multiple tests for the samechainId
andmethod
, but with different inputs (e.g. testing multiple user addresses), a key is necessary for the system to identify them.
Once the tests are DeFined, running npm run build-snapshots -- -p <protocol-name>
will generate snapshots for them.
Running npm run test
validates snapshots match results.
To version and publish:
- Create a pull request with your changes.
- Apply one of the labels:
major
,minor
,patch
,premajor
,preminor
,prepatch
, orprerelease
to the pull request. This label will determine how the package version is bumped. - Once your pull request is approved, merge it into
main
. - The GitHub Action workflow will automatically bump the package version based on the label, push the new version and associated tag, and then publish the package.
Please note: You no longer need to manually bump the package version or push tags.
To update all averages, run npm run adapters-cli block-average
. To update a specific chain, run npm run adapters-cli block-average -- --chain 1
.
Johann |
Bernardo |
JP |