forked from elizaOS/eliza
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request elizaOS#3096 from HMXOrg/develop
feat: plugin desk exchange
- Loading branch information
Showing
17 changed files
with
919 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
* | ||
|
||
!dist/** | ||
!package.json | ||
!readme.md | ||
!tsup.config.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# DESK Exchange Plugin for Eliza | ||
|
||
This plugin enables interaction with the DESK Perpetual DEX through Eliza, providing perpetual futures trading capabilities. Visit [DESK Exchange](https://desk.exchange/) for more details. | ||
## Features | ||
- 💱 Perpetual Trading | ||
- Market orders (immediate execution) | ||
- Limit orders (price-specific) | ||
- 🔄 Order Management | ||
- Cancel all open orders | ||
- 🏦 Account summary | ||
- View open orders | ||
- View active positions | ||
- View collateral balances | ||
|
||
## Installation | ||
|
||
Add the plugin to your Eliza configuration: | ||
|
||
```json | ||
{ | ||
"plugins": ["@elizaos/plugin-desk-exchange"] | ||
} | ||
``` | ||
|
||
## Configuration | ||
|
||
Set the following environment variables: | ||
|
||
```env | ||
DESK_EXCHANGE_PRIVATE_KEY=your_private_key # Required for trading and cancelling orders | ||
DESK_EXCHANGE_NETWORK= # "mainnet" or "testnet | ||
``` | ||
|
||
## Available Actions | ||
|
||
### 1. PERP_TRADE | ||
|
||
Place perp market or limit orders. | ||
|
||
Examples: | ||
|
||
``` | ||
# Market Orders | ||
"long 1 BTC" -> Place buy order of 1 BTC at market price | ||
"sell 2 ETH" -> Sells 2 ETH at market price | ||
"market buy 1 ETH" -> Buys 1 ETH at market price | ||
# Limit Orders | ||
"buy 1 SOL at 20 USDC" -> Places buy order for 1 SOL at 20 USDC | ||
"sell 0.5 BASE at 21 USDC" -> Places sell order for 0.5 BASE at 21 USDC | ||
``` | ||
|
||
### 2. CANCEL_ORDERS | ||
|
||
Cancel all your open orders. | ||
|
||
Examples: | ||
|
||
``` | ||
"Cancel all orders" | ||
"Cancel my orders" | ||
``` | ||
|
||
### 3. GET_PERP_ACCOUNT_SUMMARY | ||
|
||
Display the summary of your current account with details on open orders, active position and collateral tokens. | ||
|
||
Examples: | ||
|
||
``` | ||
"Check my account please" | ||
"Here is the summary of your account 0xxxxxxxx | ||
Your positions: | ||
- Long 1.0039 BTCUSD | ||
- Short 10.01 ETHUSD | ||
- Long 135808.80 SOLUSD | ||
Your orders: | ||
- Sell 0/0.0001 BTCUSD @200000.00 | ||
Your collaterals: | ||
- 1382295.125325162 USDC | ||
- 2000000.00 CREDIT" | ||
``` | ||
|
||
## Security Notes | ||
|
||
- Store your private key securely using environment variables | ||
- Test with small amounts first | ||
- Use testnet for initial testing | ||
- Monitor your orders regularly | ||
- Double-check prices before confirming trades | ||
|
||
## License | ||
|
||
MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "@elizaos/plugin-desk-exchange", | ||
"version": "0.1.0", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"zod": "^3.23.8", | ||
"ethers": "^6.13.5", | ||
"axios": "^1.7.9" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.0.0", | ||
"tsup": "8.3.5" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"dev": "tsup --format esm --dts --watch" | ||
} | ||
} |
187 changes: 187 additions & 0 deletions
187
packages/plugin-desk-exchange/src/actions/accountSummary.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
import { | ||
type Action, | ||
type ActionExample, | ||
type IAgentRuntime, | ||
type Memory, | ||
type State, | ||
type HandlerCallback, | ||
composeContext, | ||
elizaLogger, | ||
} from "@elizaos/core"; | ||
import { accountSummaryTemplate } from "../templates"; | ||
import { ethers } from "ethers"; | ||
import { | ||
generateNonce, | ||
generateJwt, | ||
getSubaccount, | ||
getEndpoint, | ||
formatNumber, | ||
} from "../services/utils"; | ||
import { getSubaccountSummary } from "../services/account"; | ||
|
||
export const accountSummary: Action = { | ||
name: "GET_PERP_ACCOUNT_SUMMARY", | ||
similes: [ | ||
"CHECK_ACCOUNT", | ||
"CHECK_PERP_ACCOUNT", | ||
"ACCOUNT_SUMMARY", | ||
"PERP_ACCOUNT_SUMMARY", | ||
], | ||
description: "Get the current account summary", | ||
validate: async (runtime: IAgentRuntime) => { | ||
return !!( | ||
runtime.getSetting("DESK_EXCHANGE_PRIVATE_KEY") && | ||
runtime.getSetting("DESK_EXCHANGE_NETWORK") | ||
); | ||
}, | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State, | ||
options: Record<string, unknown>, | ||
callback?: HandlerCallback | ||
) => { | ||
// Initialize or update state | ||
state = !state | ||
? await runtime.composeState(message) | ||
: await runtime.updateRecentMessageState(state); | ||
|
||
const context = composeContext({ | ||
state, | ||
template: accountSummaryTemplate, | ||
}); | ||
|
||
try { | ||
const endpoint = getEndpoint(runtime); | ||
const wallet = new ethers.Wallet( | ||
runtime.getSetting("DESK_EXCHANGE_PRIVATE_KEY") | ||
); | ||
const jwt = await generateJwt(endpoint, wallet, 0, generateNonce()); | ||
|
||
const response = await getSubaccountSummary( | ||
endpoint, | ||
jwt, | ||
getSubaccount(wallet.address, 0) | ||
); | ||
elizaLogger.info(response.data); | ||
|
||
const subaccountSummaryData = response.data.data; | ||
const positionSummary = | ||
subaccountSummaryData.positions.length > 0 | ||
? subaccountSummaryData.positions | ||
.map((p) => { | ||
return `- ${p.side} ${formatNumber(p.quantity)} ${ | ||
p.symbol | ||
}`; | ||
}) | ||
.join("\n") | ||
: "- No active position"; | ||
const orderSummary = | ||
subaccountSummaryData.open_orders.length > 0 | ||
? subaccountSummaryData.open_orders | ||
.map((o) => { | ||
return `- ${ | ||
o.side === "Long" ? "Buy" : "Sell" | ||
} ${formatNumber( | ||
Number(o.original_quantity) - | ||
Number(o.remaining_quantity) | ||
)}/${formatNumber(o.original_quantity)} ${ | ||
o.symbol | ||
} @${ | ||
Number(o.price) > 0 | ||
? formatNumber(o.price) | ||
: formatNumber(o.trigger_price) | ||
}`; | ||
}) | ||
.join("\n") | ||
: "- No orders"; | ||
const collateralSummary = | ||
subaccountSummaryData.collaterals.length > 0 | ||
? subaccountSummaryData.collaterals | ||
.map((c) => { | ||
return `- ${formatNumber(c.amount, 4)} ${ | ||
c.asset | ||
}`; | ||
}) | ||
.join("\n") | ||
: "- No collateral"; | ||
callback({ | ||
text: | ||
`Here is the summary of your account ${wallet.address}\n` + | ||
`Your positions:\n` + | ||
positionSummary + | ||
`\n` + | ||
`Your orders:\n` + | ||
orderSummary + | ||
`\n` + | ||
`Your collaterals:\n` + | ||
collateralSummary, | ||
content: subaccountSummaryData, | ||
}); | ||
|
||
return true; | ||
} catch (error) { | ||
elizaLogger.error("Error getting account summary:", { | ||
message: error.message, | ||
code: error.code, | ||
data: error.response?.data, | ||
}); | ||
if (callback) { | ||
callback({ | ||
text: `Error getting account summary: ${error.message} ${error.response?.data?.errors}`, | ||
content: { error: error.message }, | ||
}); | ||
} | ||
return false; | ||
} | ||
}, | ||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Check my account please", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Here is the summary of your account", | ||
action: "GET_PERP_ACCOUNT_SUMMARY", | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "How is my account doing?", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Here is the summary of your account", | ||
action: "GET_PERP_ACCOUNT_SUMMARY", | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Account summary", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Here is the summary of your account", | ||
action: "GET_PERP_ACCOUNT_SUMMARY", | ||
}, | ||
}, | ||
], | ||
] as ActionExample[][], | ||
}; | ||
|
||
export default accountSummary; |
Oops, something went wrong.