@emberai/onchain-actions-registry 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,385 @@
1
+ # @emberai/onchain-actions-registry
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@emberai/onchain-actions-registry.svg)](https://www.npmjs.com/package/@emberai/onchain-actions-registry)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/EmberAGI/arbitrum-vibekit/blob/main/LICENSE)
5
+
6
+ A modular plugin architecture for integrating DeFi protocols into the Ember ecosystem. Build custom protocol plugins with TypeScript support and comprehensive type safety.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @emberai/onchain-actions-registry
12
+ ```
13
+
14
+ ```bash
15
+ pnpm add @emberai/onchain-actions-registry
16
+ ```
17
+
18
+ ```bash
19
+ yarn add @emberai/onchain-actions-registry
20
+ ```
21
+
22
+ ## Overview
23
+
24
+ The Ember Plugin System consists of the following components:
25
+
26
+ ```
27
+ onchain-actions-plugins/
28
+ └── registry/
29
+ ├── src/
30
+ │ ├── core/ # Type definitions, interfaces, and schemas for plugin development.
31
+ │ ├── aave-lending-plugin/ # Complete AAVE V3 lending plugin serving as a development example.
32
+ │ ├── registry.ts # Plugin registration and discovery system.
33
+ │ ├── chainConfig.ts # Chain configuration utilities
34
+ │ └── index.ts # Main registry initialization
35
+ ├── package.json
36
+ ├── tsconfig.json
37
+ └── tsup.config.ts
38
+ ```
39
+
40
+ ### What are Plugins?
41
+
42
+ Plugins are capabilities that expand Ember's functionality by integrating new DeFi protocols. The plugin created by developers must handle all smart contract interactions, from constructing transaction calldata to managing protocol-specific logic. Once a plugin is finalized, updates will be made to Ember's backend to fully integrate the new capabilities.
43
+
44
+ ### Why Build Plugins?
45
+
46
+ The plugin system provides several key advantages for protocol integrations:
47
+
48
+ 1. **Provided Entity Mapping**: Standardized entity mapping ensures consistent data structures across all protocol integrations. Without standardized mapping, each protocol integration would require custom entity definitions, leading to inconsistent data structures and increased complexity when working across multiple protocols.
49
+
50
+ 2. **Faster Protocol Integration**: Building protocol integrations from scratch is time-consuming and error-prone. The plugin system eliminates boilerplate code and provides patterns for common DeFi operations. The pre-built framework and type safety accelerates the integration of new DeFi protocols.
51
+
52
+ 3. **Easier User Consumption and Aggregated/Optimized Results**: Users typically need to interact with each protocol separately, manually compare rates and liquidity, and piece together optimal strategies. The plugin system aggregates protocol data and enables intelligent routing across integrations. This unified interface allows users to interact with multiple protocols seamlessly, with aggregated data and optimized execution paths.
53
+
54
+ 4. **Potential Trailblazer Incentive**: Plugin developers may be eligible for the [Trailblazer Fund 2.0](https://www.emberai.xyz/blog/introducing-arbitrum-vibekit-and-the-trailblazer-fund-2-0) initiative launched by Arbitrum.
55
+
56
+ ### Information Flow
57
+
58
+ Here is how the system's components interact with each other:
59
+
60
+ <p align="left">
61
+ <img src="../../../img/Plugin System.png" width="800px" alt="Plugin System Information Flow Diagram"/>
62
+ </p>
63
+
64
+ ## Plugin Architecture
65
+
66
+ The core framework (`registry/src/core/`) provides the following components:
67
+
68
+ - **actions**: Action type definitions and interfaces for all plugin types
69
+ - **queries**: Query type definitions for retrieving protocol data
70
+ - **schemas**: Zod validation schemas for requests and responses
71
+ - **pluginType.ts**: Core plugin type definitions
72
+ - **index.ts**: Main exports for plugin development
73
+
74
+ These components work together to create a type-safe plugin system: **index.ts** defines the foundational `EmberPlugin` interface, while **pluginType.ts** defines the plugin types (lending, liquidity, swap, perpetuals) and maps each type to its available **actions** and **queries**. The **actions** directory provides the executable operations (supply, borrow, swap, etc.) with their callback signatures, while **queries** enable data retrieval without transactions. All inputs and outputs are validated through **schemas**, ensuring type safety and data consistency across the system.
75
+
76
+ ### Plugin Interface
77
+
78
+ The core framework defines an `EmberPlugin<Type>` interface and each plugin must implement this interface:
79
+
80
+ ```typescript
81
+ interface EmberPlugin<Type extends PluginType> {
82
+ id?: string; // Unique identifier
83
+ type: Type; // Plugin type (lending, liquidity, swap, perpetuals)
84
+ name: string; // Human-readable name
85
+ description?: string; // Optional description
86
+ website?: string; // Official website
87
+ x?: string; // Twitter/X handle
88
+ actions: ActionDefinition<AvailableActions[Type]>[]; // Available actions for this plugin type
89
+ queries: AvailableQueries[Type]; // Data queries for this plugin type
90
+ }
91
+ ```
92
+
93
+ The system supports four main plugin types:
94
+
95
+ - `lending`: Supply, borrow, repay, and withdraw operations
96
+ - `liquidity`: Add and remove liquidity from pools
97
+ - `swap`: Token exchange operations
98
+ - `perpetuals`: Long, short, and close perpetual positions
99
+
100
+ ### Actions
101
+
102
+ Each plugin type defines specific [actions](https://github.com/EmberAGI/arbitrum-vibekit/tree/main/typescript/onchain-actions-plugins/registry/src/core/actions) they can execute. For example, lending plugins can do `lending-supply`, `lending-borrow`, `lending-repay`, and `lending-withdraw`. Each action has callback functions that define its request and response.
103
+
104
+ ```typescript
105
+ interface ActionDefinition<T extends Action> {
106
+ name: string; // Unique action name
107
+ type: T; // Action type
108
+ callback: ActionCallback<T>; // Implementation function
109
+ inputTokens: () => Promise<TokenSet[]>; // Supported input tokens
110
+ outputTokens?: () => Promise<TokenSet[]>; // Optional output tokens
111
+ }
112
+ ```
113
+
114
+ **Input Tokens**: The tokens that the user needs to execute this action. Token sets are organized by chain ID, and each action defines its own input/output token mapping.
115
+
116
+ **Output Tokens**: The tokens that the user receives through this action (optional field). Note that the function doesn't take all tokens, just transforms one of the supported input tokens into one of the supported output tokens.
117
+
118
+ #### Example: AAVE Lending Plugin Actions
119
+
120
+ ```typescript
121
+ // First, fetch protocol data once at the function level
122
+ const reservesResponse = await adapter.getReserves();
123
+ const underlyingAssets = reservesResponse.reservesData.map(
124
+ reserve => reserve.underlyingAsset
125
+ );
126
+ const aTokens = reservesResponse.reservesData.map(
127
+ reserve => reserve.aTokenAddress
128
+ );
129
+ const borrowableAssets = reservesResponse.reservesData
130
+ .filter(reserve => reserve.borrowingEnabled)
131
+ .map(reserve => reserve.underlyingAsset);
132
+
133
+ // Supply Action: Transform underlying assets → aTokens
134
+ {
135
+ type: 'lending-supply',
136
+ name: `AAVE lending pools in chain ${adapter.chain.id}`,
137
+ inputTokens: async () =>
138
+ Promise.resolve([{
139
+ chainId: adapter.chain.id.toString(),
140
+ tokens: underlyingAssets,
141
+ }]),
142
+ outputTokens: async () =>
143
+ Promise.resolve([{
144
+ chainId: adapter.chain.id.toString(),
145
+ tokens: aTokens,
146
+ }]),
147
+ callback: adapter.createSupplyTransaction.bind(adapter)
148
+ }
149
+
150
+ // Borrow Action: Use aTokens as collateral → borrow underlying assets
151
+ {
152
+ type: 'lending-borrow',
153
+ name: `AAVE borrow in chain ${adapter.chain.id}`,
154
+ inputTokens: async () =>
155
+ Promise.resolve([{
156
+ chainId: adapter.chain.id.toString(),
157
+ tokens: aTokens,
158
+ }]),
159
+ outputTokens: async () =>
160
+ Promise.resolve([{
161
+ chainId: adapter.chain.id.toString(),
162
+ tokens: borrowableAssets,
163
+ }]),
164
+ callback: adapter.createBorrowTransaction.bind(adapter)
165
+ }
166
+ ```
167
+
168
+ #### Flexible Action Definition
169
+
170
+ The plugin system offers flexibility in action definitions. For example, AAVE defines multiple repay actions:
171
+
172
+ ```typescript
173
+ // Repay Action #1: Repay with borrowed assets
174
+ {
175
+ type: 'lending-repay',
176
+ name: `AAVE repay in chain ${adapter.chain.id}`,
177
+ inputTokens: async () =>
178
+ Promise.resolve([{
179
+ chainId: adapter.chain.id.toString(),
180
+ tokens: borrowableAssets,
181
+ }]),
182
+ outputTokens: async () => Promise.resolve([]), // No output tokens
183
+ callback: adapter.createRepayTransaction.bind(adapter)
184
+ }
185
+
186
+ // Repay Action #2: Repay with aTokens (collateral)
187
+ {
188
+ type: 'lending-repay',
189
+ name: `AAVE repay with aTokens in chain ${adapter.chain.id}`,
190
+ inputTokens: async () =>
191
+ Promise.resolve([{
192
+ chainId: adapter.chain.id.toString(),
193
+ tokens: aTokens,
194
+ }]),
195
+ outputTokens: async () => Promise.resolve([]), // No output tokens
196
+ callback: adapter.createRepayTransactionWithATokens.bind(adapter)
197
+ }
198
+ ```
199
+
200
+ ### Queries
201
+
202
+ Each plugin type can define queries to retrieve protocol data without executing transactions:
203
+
204
+ ```typescript
205
+ // Query interfaces by plugin type
206
+ type AvailableQueries = {
207
+ lending: { getPositions: LendingGetPositions };
208
+ liquidity: { getWalletPositions: LiquidityGetWalletPositions; getPools: LiquidityGetPools };
209
+ swap: Record<string, never> | undefined; // No queries supported
210
+ perpetuals: {
211
+ getMarkets: PerpetualsGetMarkets;
212
+ getPositions: PerpetualsGetPositions;
213
+ getOrders: PerpetualsGetOrders;
214
+ };
215
+ };
216
+ ```
217
+
218
+ **Query examples:**
219
+
220
+ - Lending: Get user positions, health factors, and borrowing capacity
221
+ - Liquidity: Get wallet LP positions and available pools
222
+ - Perpetuals: Get markets, active positions, and pending orders
223
+ - Swap: No queries (stateless operations)
224
+
225
+ ### Schema Architecture
226
+
227
+ The schema system provides comprehensive type safety with Zod validation:
228
+
229
+ **Core Schemas** (`schemas/core.ts`):
230
+
231
+ - `TokenSchema`: Complete token metadata including native token handling
232
+ - `TransactionPlanSchema`: Standardized transaction format for all chains
233
+ - `FeeBreakdownSchema`: Service fees and slippage cost structure
234
+ - `BalanceSchema`: User wallet balance representation
235
+
236
+ **Action-Specific Schemas**:
237
+
238
+ - **Lending** (`schemas/lending.ts`): Supply, borrow, repay, withdraw operations with comprehensive position tracking
239
+ - **Liquidity** (`schemas/liquidity.ts`): Advanced liquidity provision with discriminated unions for full/limited range positions
240
+ - **Swap** (`schemas/swap.ts`): Token exchange with slippage tolerance and price tracking
241
+ - **Perpetuals** (`schemas/perpetuals.ts`): Integration with GMX SDK for complex derivatives trading
242
+
243
+ ## Plugin Registry
244
+
245
+ The registry ([`registry.ts`](https://github.com/EmberAGI/arbitrum-vibekit/blob/main/typescript/onchain-actions-plugins/registry/src/registry.ts)) manages plugin discovery and registration. You can initialize a registry using [`initializePublicRegistry()`](https://github.com/EmberAGI/arbitrum-vibekit/blob/main/typescript/onchain-actions-plugins/registry/src/index.ts). The registry supports two distinct registration patterns:
246
+
247
+ ### Deferred Registration (Recommended)
248
+
249
+ Use `registerDeferredPlugin()` for plugins requiring async initialization:
250
+
251
+ ```typescript
252
+ // For plugins that need async setup (network calls, contract loading, etc.)
253
+ registry.registerDeferredPlugin(
254
+ getAaveEmberPlugin({
255
+ chainId: 42161,
256
+ rpcUrl: 'https://arb1.arbitrum.io/rpc',
257
+ wrappedNativeToken: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
258
+ }),
259
+ );
260
+ ```
261
+
262
+ ### Synchronous Registration
263
+
264
+ Use `registerPlugin()` for plugins that are already instantiated and ready to use:
265
+
266
+ ```typescript
267
+ // For plugins that are already created and don't require async initialization
268
+ const instantPlugin = {
269
+ type: 'lending',
270
+ name: 'My Protocol',
271
+ actions: [...],
272
+ queries: {...}
273
+ };
274
+
275
+ registry.registerPlugin(instantPlugin);
276
+ ```
277
+
278
+ ### Multiple Plugin Types from One Provider
279
+
280
+ While each plugin can only implement one type (lending, liquidity, swap, or perpetuals), protocol providers can create multiple plugins to support different capabilities:
281
+
282
+ ```typescript
283
+ // Instead of returning one plugin, return a list of plugins
284
+ export async function getProtocolPlugins(
285
+ params: ProtocolParams,
286
+ ): Promise<EmberPlugin<PluginType>[]> {
287
+ return [
288
+ // One plugin for lending
289
+ {
290
+ type: 'lending',
291
+ name: 'Protocol Lending',
292
+ actions: lendingActions,
293
+ queries: lendingQueries,
294
+ },
295
+ // One plugin for swapping
296
+ {
297
+ type: 'swap',
298
+ name: 'Protocol Swapping',
299
+ actions: swapActions,
300
+ queries: {},
301
+ },
302
+ // One plugin for perpetuals
303
+ {
304
+ type: 'perpetuals',
305
+ name: 'Protocol Perpetuals',
306
+ actions: perpetualsActions,
307
+ queries: perpetualsQueries,
308
+ },
309
+ ];
310
+ }
311
+ ```
312
+
313
+ Registry flexibility:
314
+
315
+ ```typescript
316
+ // Instead of registering one plugin
317
+ registry.registerPlugin(plugin);
318
+
319
+ // Iterate over the list and register multiple plugins
320
+ const plugins = await getProtocolPlugins(params);
321
+ plugins.forEach((plugin) => {
322
+ registry.registerPlugin(plugin);
323
+ });
324
+ ```
325
+
326
+ ## Currently Supported Protocols & Features
327
+
328
+ > **Note:**
329
+ > Before creating a new plugin, check if the functionality already exists in the Ember MCP server to avoid duplication.
330
+
331
+ The Ember MCP server already provides comprehensive support for the following protocols:
332
+
333
+ ### Cross-Chain Swapping
334
+
335
+ - **Protocol**: DEX Aggregation across multiple chains
336
+ - **Capabilities**:
337
+ - Cross-chain token swaps with routing optimization
338
+ - Exact input/output amounts with slippage protection
339
+ - Support for major DEXs including **Camelot DEX**
340
+ - **MCP Tools**: `createSwap`, `possibleSwaps`
341
+
342
+ ### Perpetuals Trading
343
+
344
+ - **Protocol**: **GMX** and other perpetual DEXs
345
+ - **Capabilities**:
346
+ - Long/short positions with customizable leverage
347
+ - Limit orders, stop-loss, take-profit orders
348
+ - Position and order management across protocols
349
+ - Market data and liquidity information
350
+ - **MCP Tools**: `createPerpetualLongPosition`, `createPerpetualShortPosition`, `createClosePerpetualsOrders`, `getPerpetualsMarkets`, `getPerpetualsPositions`, `getPerpetualsOrders`
351
+
352
+ ### Multi-Protocol Lending
353
+
354
+ - **Protocols**: **AAVE** and other major lending protocols
355
+ - **Capabilities**:
356
+ - Supply tokens to earn yield across protocols
357
+ - Borrow against collateral with rate optimization
358
+ - Automated repayment and withdrawal strategies
359
+ - Cross-protocol position management
360
+ - **MCP Tools**: `createLendingSupply`, `createLendingBorrow`, `createLendingRepay`, `createLendingWithdraw`, `getWalletLendingPositions`
361
+
362
+ ### Multi-Protocol Liquidity
363
+
364
+ - **Protocols**: **Camelot DEX** and other AMMs
365
+ - **Capabilities**:
366
+ - Add liquidity to pools across multiple DEXs
367
+ - Remove liquidity with optimal timing
368
+ - LP position tracking and management
369
+ - Fee optimization across protocols
370
+ - **MCP Tools**: `createLiquiditySupply`, `createLiquidityWithdraw`, `getLiquidityPools`, `getWalletLiquidityPositions`
371
+
372
+ ## Building Custom Plugins
373
+
374
+ The [`aave-lending-plugin`](https://github.com/EmberAGI/arbitrum-vibekit/tree/main/typescript/onchain-actions-plugins/registry/src/aave-lending-plugin) serves as a comprehensive example that demonstrates the plugin implementation process. Use this plugin as your starting point. For a detailed development guide, see [`DEVELOPMENT.md`](https://github.com/EmberAGI/arbitrum-vibekit/blob/main/typescript/onchain-actions-plugins/registry/DEVELOPMENT.md).
375
+
376
+ ## License
377
+
378
+ MIT © [EmberAGI](https://github.com/EmberAGI/arbitrum-vibekit/blob/main/LICENSE)
379
+
380
+ ## Links
381
+
382
+ - [NPM Package](https://www.npmjs.com/package/@emberai/onchain-actions-registry)
383
+ - [GitHub Repository](https://github.com/EmberAGI/arbitrum-vibekit/tree/main/typescript/onchain-actions-plugins/)
384
+ - [Ember Website](https://www.emberai.xyz/)
385
+ - [Ember X](https://x.com/EmberAGI)