@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 +385 -0
- package/dist/index.cjs +1518 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1119 -0
- package/dist/index.d.ts +1119 -0
- package/dist/index.js +1433 -0
- package/dist/index.js.map +1 -0
- package/package.json +87 -0
package/README.md
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# @emberai/onchain-actions-registry
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@emberai/onchain-actions-registry)
|
|
4
|
+
[](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)
|