{"id":26054922,"url":"https://github.com/morpho-org/morpho-aavev3-optimizer-sdk","last_synced_at":"2026-02-05T23:32:31.070Z","repository":{"id":165445766,"uuid":"639792548","full_name":"morpho-org/morpho-aavev3-optimizer-sdk","owner":"morpho-org","description":"📚📚 Typescript based package to ease the Morpho-AaveV3 Optimizer integration","archived":false,"fork":false,"pushed_at":"2025-01-08T08:41:02.000Z","size":712,"stargazers_count":2,"open_issues_count":9,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-26T14:37:41.474Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/morpho-org.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-12T08:34:53.000Z","updated_at":"2025-01-08T08:38:23.000Z","dependencies_parsed_at":"2023-08-23T02:10:55.377Z","dependency_job_id":"dd1a553b-7037-42cf-bab8-879712b7fe7a","html_url":"https://github.com/morpho-org/morpho-aavev3-optimizer-sdk","commit_stats":null,"previous_names":["morpho-org/morpho-aavev3-optimizer-sdk","morpho-org/morpho-aave-v3-sdk"],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/morpho-org/morpho-aavev3-optimizer-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morpho-org%2Fmorpho-aavev3-optimizer-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morpho-org%2Fmorpho-aavev3-optimizer-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morpho-org%2Fmorpho-aavev3-optimizer-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morpho-org%2Fmorpho-aavev3-optimizer-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/morpho-org","download_url":"https://codeload.github.com/morpho-org/morpho-aavev3-optimizer-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morpho-org%2Fmorpho-aavev3-optimizer-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29138375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T23:14:48.546Z","status":"ssl_error","status_checked_at":"2026-02-05T23:14:35.724Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-08T10:00:29.292Z","updated_at":"2026-02-05T23:32:31.054Z","avatar_url":"https://github.com/morpho-org.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Morpho's AaveV3-ETH Optimizer SDK\n\nThis repository contains the core typescript features used to build a dapp based on [Morpho-AaveV3 smart contracts](https://github.com/morpho-org/morpho-aave-v3).\n\n\u003e **Warning**  \n\u003e This package is used by the morpho association to build the [morpho-aaveV3 dapp](https://aave-v3.morpho.xyz) but is still **under development** and subject to changes.  \n\u003e **Use at your own risk**. Any feedback is welcome.\n\n## Installation\n\nYou need to use a node version \u003e= `18.0.0`\n\n```bash\nnpm install @morpho-org/morpho-aave-v3-sdk\n```\n\n```bash\nyarn add @morpho-org/morpho-aave-v3-sdk\n```\n\n## Configuration\n\nAt the root of your dapp or your script:\n\n```ts\n/* _app.ts */\nimport sdk from \"@morpho-org/morpho-aave-v3-sdk/configuration\";\n\nsdk.setConfiguration(config);\n```\n\nwhere `config` is an object with the following optional properties:\n\n| property               | type                                 | default                   | description                                                                                                                             |\n|------------------------| ------------------------------------ |---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|\n| `isProd`               | `boolean`                            | `false`                   | _Set to `true` if the dapp is running in production_                                                                                    |\n| `defaultProvider`      | `string`                             | `process.env.RPC_URL`     | _The default provider to use. It fallbacks on the default provider from `ethers`_                                                         |\n| `defaultMaxIterations` | `{ supply: number; borrow: number }` | `{ supply: 4, borrow: 4 }` | _Max number of iterations run by the [matching engine](https://docs.morpho.xyz/concepts-overview/advanced-concepts/matching-engine)_    |\n| `gasLimitPercent`      | `ethers.BigNumber`                   | `11000 (110%)`            | _Percentage of the gas estimation used as the gas limit for transactions (with 4 decimals)_                                             |\n| `percentApproximation` | `ethers.BigNumber`                   | `9900 (99%)`              | _Scaling applied to transactions' amount to prevent reverting due to block inclusion delay_                                             |\n| `txSignature`          | `string`                             | `undefined`               | _If provided, the signature will be appended to the transaction's data to identify the transaction's origin. **It must be in hex format**_ |\n\n## Usage\n\nThe whole sdk is built around the `MorphoAaveV3Adapter` class. This is the core element of the sdk.\n\n### Data structure\n\nWithin the adapter, data are stored in different objects:\n\n| name                  | public\\* | source      | interface                                                             | description                                                              |\n| --------------------- | -------- | ----------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------ |\n| globalData            |   ✅ yes | ⚡️ fetched | [GlobalData](src/types/common.ts#L7)                                  | _Global data about the chain and the protocol_                           |\n| marketsConfigs        |   ✅ yes | ⚡️ fetched | `MarketMapping\u003c`[`MarketConfig`](src/types/markets.ts#L86)`\u003e`         | _Properties of each market that don't (or rarely) change_                |\n| marketsData           |   ✅ yes | ⚙️ computed | `MarketMapping\u003c`[`MarketData`](src/types/markets.ts#L296)`\u003e`          | _Data by market (metrics, apys, ...) that need to be updated frequently_ |\n| marketsList           |   ✅ yes | ⚡️ fetched | `string[]`                                                            | _List of the markets listed on Morpho-AaveV3_                            |\n| userData              |   ✅ yes | ⚙️ computed | [`UserData`](src/types/user.ts#L6)                                    | _User Data that are not specific to a market_                            |\n| userMarketsData       |   ✅ yes | ⚙️ computed | `MarketMapping\u003c`[`UserMarketData`](src/types/user.ts#L262)`\u003e`         | _User Data by market_                                                    |\n| scaledMarketsData     |   ❌ no  | ⚡️ fetched | `MarketMapping\u003c`[`ScaledMarketData`](src/types/markets.ts#L182)`\u003e`    | _Raw data by market, before any processing or computation_               |\n| scaledUserMarketsData |   ❌ no  | ⚡️ fetched | `MarketMapping\u003c`[`ScaledUserMarketData`](src/types/user.ts#L184)`\u003e`   | _Raw user data by market, before any processing or computation_          |\n| rewardsDistribution   |   ❌ no  | ⚡️ fetched | [`MorphoEpochDistribution`](src/helpers/rewards/rewards.types.ts#L66) | _Morpho rewards distribution of the current epoch_                       |\n\n_\\* see [the section about data](#read-data) to see how to access public data_\n\n### Initialization\n\nTo create an adapter, you must provide _fetchers_. These are special entities that are used to fetch [data](#data-structure). For each fetcher, you can use one from this fetchers or use your own one (as long as it matches the interface). You have 5 different fetchers:\n\n| fetcher                                                        | fetched data                                                                             | available                                                                                                           |\n| -------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |\n| [MarketFetcher](src/fetchers/fetchers.interfaces.ts#L20)       | `marketsConfigs`, `marketsList`, `scaledMarketsData`                                     | [chain](src/fetchers/Chain/ChainMarketFetcher.ts), [static](src/fetchers/Static/StaticMarketFetcher.ts)             |\n| [UserFetcher](src/fetchers/fetchers.interfaces.ts#L35)         | `scaledUserMarketsData`, `userData.ethBalance`                                           | [chain](src/fetchers/Chain/ChainUserFetcher.ts), [static](src/fetchers/Static/StaticUserFetcher.ts)                 |\n| [GlobalDataFetcher](src/fetchers/fetchers.interfaces.ts#L48)   | `globalData`                                                                             | [chain](src/fetchers/Chain/ChainGlobalDataFetcher.ts), [static](src/fetchers/Static/StaticGlobalDataFetcher.ts)     |\n| [RewardsFetcher](src/fetchers/fetchers.interfaces.ts#L62)      | `rewardsDistribution`                                                                    | [api](src/fetchers/Api/ApiRewardsFetcher.ts), [static](src/fetchers/Static/StaticRewardsFetcher.ts)                 |\n\n#### From chain\n\nIf you want to fetch all data from the chain, you can use `MorphoAaveV3Adapter.fromChain`\n\n```ts\nconst adapter = MorphoAaveV3Adapter.fromChain();\n```\n\n- you can provide a specific `provider` from `ethers` to use:\n\n```ts\nconst adapter = MorphoAaveV3Adapter.fromChain({ provider: myProvider });\nawait adapter.refreshAll(\"latest\");\n```\n\nby default, the one from the [configuration](#configuration) will be used\n\n- Since some data can't be fetched from chain, you can provide specific fetcher for them:\n\n```ts\nconst adapter = MorphoAaveV3Adapter.fromChain({ extraFetchersConfig });\nawait adapter.refreshAll(\"latest\");\n```\n\nwhere `extraFetchersConfig` has the following interface:\n\n```ts\nconst extraFetchersConfig: {\n  rewards?: \"api\" | RewardsFetcher;\n}\n```\n\nBy default,\n\n- `marketSupply` will be fetched from the morpho-labs subgraph\n- `rewards` will be fetched from morpho API\n\n#### From mock\n\nYou can also provide static data to the adapter to have a static state in the adapter using `MorphoAaveV3Adapter.fromMock`\n\n```ts\nconst adapter = MorphoAaveV3Adapter.fromMock(mock);\nawait adapter.refreshAll(\"latest\");\n```\n\nWhere `mock` can be an [`AdapterMock`](src/mocks/index.ts#L18). If no mock is provided, [this one](src/mocks/mock1.ts#L119) will be used\n\n\u003e **Note**  \n\u003e You can provide loading delays to the `fromMock` function for testing purposes to simulate real conditions\n\n### Read Data\n\n#### RxJs\n\nThe sdk leverages on [RxJS](https://rxjs.dev) to allow you to build highly reactive apps out of the box.\nTo do so, every public data (see [Data structure](#data-structure)) are associated with an rxjs `Subject`:\n\n```ts\nconst adapter = MorphoAaveV3Adapter.fromChain();\nawait adapter.refreshAll(\"latest\");\n\nadapter.marketsConfigs$.subscribe((marketsConfigs) =\u003e ...);\nadapter.marketsData$.subscribe((marketsData) =\u003e ...);\nadapter.userMarketsData$.subscribe((userMarketsData) =\u003e ...);\nadapter.marketsList$.subscribe((marketsList) =\u003e ...);\nadapter.userData$.subscribe((userData) =\u003e ...);\nadapter.globalData$.subscribe((globalData) =\u003e ...);\n```\n\n#### Getters\n\nIf you don't use RxJs, you can access these data using getter functions:\n\n```ts\nconst adapter = MorphoAaveV3Adapter.fromChain();\nawait adapter.refreshAll(\"latest\");\n\nconst marketsConfigs = adapter.getMarketsConfigs();\nconst marketsData = adapter.getMarketsData();\nconst userMarketsData = adapter.getUserMarketsData();\nconst marketsList = adapter.getMarketsList();\nconst userData = adapter.getUserData();\nconst globalData = adapter.getGlobalData();\n```\n\n### Execute a transaction\n\n#### Notifications\n\nTo keep track of what's happening during the transactions' executions, the adapter can be provided with a `notifier`\n\n```ts\nadapter.addNotifier(notifier); // Adds `notifier` to the list of the adapter's notifiers.\nadapter.removeNotifier(notifier); // Removes `notifier` from the list of adapter's notifiers. It needs to be the same object (reference) as the one that has been added\nadapter.resetNotifiers(); // Removes all the notifiers and return them in an array.\n```\n\nA notifier can be any instance/object matching the [`ITransactionNotifier`](src/txHandler/notifiers/TransactionNotifier.interface.ts) interface.\n\nThe handlers are called according to the following timeline:\n\n![transaction flow](doc/ressources/tx-flow.excalidraw.svg)\n\n#### Transactions with Morpho-AaveV3 contract\n\n```ts\nadapter.handleMorphoTransaction(txType, underlyingAddress, amount, options);\n```\n\nwith\n\n| Param               | Type                                                   | Description                                                                            |\n| ------------------- | ------------------------------------------------------ | -------------------------------------------------------------------------------------- |\n| `txType`            | [`TransactionType`](src/types/tx.ts#L34)               | Type of the operation to perfom                                                        |\n| `underlyingAddress` | `string`                                               | Address of the underlying market on which to perform the operation                     |\n| `amount`            | `ethers.BigNumber`                                     | Amount of the transaction. Use `ethers.constants.MaxUint256` to use the maximum amount |\n| `options`           | _optional_, [`TransactionOptions`](src/types/tx.ts#L8) | Transaction options                                                                    |\n\n#### Approval\n\nMorpho-AaveV3 leverages the [Permit2 Approval]() feature, but you can still perform classic approvals.\n\n##### Permit2\n\n```ts\nadapter.handlePermit2Approval(underlyingAddress, deadline, amount, options);\n```\n\n| Param               | Type                                                                                  | Description                                           |\n| ------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------- |\n| `underlyingAddress` | `string`                                                                              | Address of the underlying token you wanna provide     |\n| `deadline`          | `ethers.BigNumber`                                                                    | Deadline after which the approval isn't valid anymore |\n| `amount`            | `ethers.BigNumber`                                                                    | Amount to approve                                     |\n| `options`           | _optional_, [`ApprovalHandlerOptions`](src/txHandler/ApprovalHandler.interface.ts#L5) | Transaction options                                   |\n\n##### Classic\n\n```ts\nadapter.handleApproval(underlyingAddress, amount, options);\n```\n\n| Param               | Type                                                                                  | Description                                       |\n| ------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------- |\n| `underlyingAddress` | `string`                                                                              | Address of the underlying token you wanna provide |\n| `amount`            | `ethers.BigNumber`                                                                    | Amount to approve                                 |\n| `options`           | _optional_, [`ApprovalHandlerOptions`](src/txHandler/ApprovalHandler.interface.ts#L5) | Transaction options                               |\n\n#### Claim Morpho rewards\n\n```ts\nadapter.handleClaimMorpho({ overrides });\n```\n\n#### Wrap ETH\n\n```ts\nadapter.handleWrapEth(amount, { overrides });\n```\n\nWith `amount` being of type `ethers.BigNumber`\n\n#### Connection\n\n- Connect a user to the adapter:\n\n```ts\nadapter.connect(user, signer); // Data will be fetched for `user` and `signer` will be used for transactions\n```\n\n```ts\n// in read-only\n\nadapter.connect(user); // Data will be fetched for `user` but transactions will be ignored\n```\n\n- Disconnect connected user:\n\n```ts\nadapter.disconnect();\n```\n\n- Get the connection state:\n\n```ts\nadapter.isConnected();\n```\n\n#### Refreshing\n\n##### `refreshAll`\n\n```ts\nadapter.refreshAll(\"latest\");\n```\n\nAll the data will be refreshed.\n\n\u003e **Note**\n\u003e If the block is undefined, the data will be fetched at the last fetched block. If `refreshAll` is called for the first time, the data will be fetched at the block \"latest\"\n\n##### `refreshData`\n\n```ts\nadapter.refreshData();\n```\n\nFetch a new block from the chain and update all indexes locally without fetching markets data\nIf the block is not a new block, the update will be ignored.\n\n##### `refetchData`\n\n```ts\nadapter.refetchData();\n```\n\nRefetch the data from the chain and recompute computed data.\n\n\u003e **Note**\n\u003e Only `globalData`, `scaledMarketsData`, `scaledUserMarketsData` and `rewardsDistribution` will be refetched since the others are not likely to change between two blocks\n\n#### Max capacity\n\nYou can use `getUserMaxCapacity` to get the maximum amount for a given operation on a given market.\n\n```ts\nconst { amount, limiter } = adapter.getUserMaxCapacity(underlyingAddress, txType);\n```\n\nThe maximum `amount` is given in underlying and the `limiter` is one of the following (see [MaxCapacityLimiter](src/types/common.ts#L74))\n\n```ts\n\"LIMITED_BY_WALLET_BALANCE\"; // The user can't supply/repay more than his wallet balance\n\"LIMITED_BY_OPERATION_PAUSED\"; // The required operation is paused\n\"LIMITED_BY_ZERO_PRICE\"; // The amount can't be estimated because the fetched price for the given market is zero\n\"LIMITED_BY_BORROW_CAPACITY\"; // The user can't borrow more than his borrow capacity\n\"LIMITED_BY_POOL_LIQUIDITY\"; // The amount is limited by AaveV3 liquidity\n\"LIMITED_BY_CAP\"; // There is a borrow/supply cap on AaveV3 and it limits the operation\n\"LIMITED_BY_BALANCE\"; // The user can't withdraw/repay more than his current balance on Morpho\n```\n\n### Simulation\n\nThe adapter provides a simulation tool that allows you to simulate the impact of a transaction on its data.\n\n```ts\nconst simulator = adapter.getSimulator(timeout);\n```\n\nwith `timeout` being the minimum delay (in ms) between two refresh. Explicitly set to `O` to prevent it from refreshing. The default value is `1000` (1s)\n\n#### Data structure\n\nThe simulator has the same data structure as the adapter. See [Data Structure](#data-structure) for more details.\n\n\u003e **Note**\n\u003e Since the adapter's values are evolving, the simulator will re-run the simulation on the new values when they change.\n\n#### Simulate\n\n```ts\nsimulator.simulate([\n  {\n    type,\n    amount,\n    underlyingAddress\n  },\n  ...\n]);\n```\n\n#### Reset\n\nRun `simulator.reset()` reset the operation list.\n\n\u003e **Note**\n\u003e This is equivalent to `simulator.simulate([])`\n\n#### Close\n\nWhen you don't need the simulator anymore, run `simulator.close()` to free the memory.\n\n\u003e **Warning**\n\u003e Not closing simulators can lead to big performance issues\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorpho-org%2Fmorpho-aavev3-optimizer-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmorpho-org%2Fmorpho-aavev3-optimizer-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorpho-org%2Fmorpho-aavev3-optimizer-sdk/lists"}