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#2083 from 0xalank/quai-integration
feat: add Quai integration
- Loading branch information
Showing
10 changed files
with
470 additions
and
1 deletion.
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,22 @@ | ||
{ | ||
"name": "@elizaos/plugin-quai", | ||
"version": "0.0.1", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"quais": "1.0.0-alpha.25", | ||
"tsup": "^8.3.5", | ||
"vitest": "^2.1.4", | ||
"@avnu/avnu-sdk": "^2.1.1", | ||
"@elizaos/plugin-trustdb": "workspace:*" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"test": "vitest" | ||
}, | ||
"peerDependencies": { | ||
"whatwg-url": "7.1.0" | ||
} | ||
} |
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,149 @@ | ||
# @elizaos/plugin-quai | ||
|
||
Quai Network integration plugin for Eliza OS that enables native token transfers and interactions with the Quai blockchain. | ||
|
||
## Overview | ||
|
||
This plugin provides core functionality for interacting with the Quai Network, offering native token transfer capabilities and blockchain interactions through a simple interface. | ||
|
||
## Features | ||
|
||
- Native QUAI token transfers | ||
- Multiple network support | ||
- Secure transaction signing | ||
- Comprehensive error handling | ||
- Built-in address validation | ||
- Automatic gas estimation | ||
- Real-time transaction status | ||
|
||
## Installation | ||
|
||
```bash | ||
pnpm install @elizaos/plugin-quai | ||
``` | ||
|
||
## Configuration | ||
|
||
The plugin requires the following environment variables: | ||
|
||
```env | ||
QUAI_PRIVATE_KEY=your-private-key | ||
QUAI_RPC_URL=https://rpc.quai.network # or your preferred RPC endpoint | ||
``` | ||
|
||
## Usage | ||
|
||
### Token Transfer | ||
|
||
```typescript | ||
import { quaiPlugin } from '@elizaos/plugin-quai'; | ||
|
||
// Send QUAI | ||
const result = await eliza.execute({ | ||
action: 'SEND_TOKEN', | ||
content: { | ||
recipient: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7', | ||
amount: '10' | ||
} | ||
}); | ||
``` | ||
|
||
## API Reference | ||
|
||
### Actions | ||
|
||
#### `SEND_TOKEN` | ||
Transfers QUAI tokens to another address. | ||
|
||
```typescript | ||
{ | ||
action: 'SEND_TOKEN', | ||
content: { | ||
recipient: string, // Recipient's Quai address (42 characters, 0x prefix) | ||
amount: string, // Amount to send (in QUAI) | ||
tokenAddress?: string // Optional: for QRC20 tokens (not implemented yet) | ||
} | ||
} | ||
``` | ||
|
||
### Providers | ||
|
||
The plugin uses Quai's native JsonRpcProvider for blockchain interactions: | ||
|
||
```typescript | ||
const provider = getQuaiProvider(runtime); | ||
// Returns configured JsonRpcProvider instance | ||
``` | ||
|
||
## Troubleshooting | ||
|
||
### Common Issues | ||
|
||
1. **Transaction Failures** | ||
- Check account balance | ||
- Verify recipient address format | ||
- Ensure sufficient gas | ||
- Confirm network connection | ||
|
||
2. **Connection Problems** | ||
- Verify RPC endpoint | ||
- Check network status | ||
- Ensure valid credentials | ||
- Monitor API availability | ||
|
||
3. **Configuration Issues** | ||
- Verify environment variables | ||
- Check address format | ||
- Confirm private key format | ||
- Validate RPC URL | ||
|
||
## Security Best Practices | ||
|
||
1. **Key Management** | ||
- Store private keys securely | ||
- Use environment variables | ||
- Never expose private keys in code | ||
- Monitor account activity | ||
|
||
2. **Transaction Safety** | ||
- Validate all addresses | ||
- Implement amount validation | ||
- Double-check recipients | ||
- Monitor transaction status | ||
|
||
3. **Error Handling** | ||
- Log all transaction attempts | ||
- Handle timeouts gracefully | ||
- Validate all user inputs | ||
- Provide clear error messages | ||
|
||
## Testing | ||
|
||
Run the test suite: | ||
|
||
```bash | ||
pnpm test | ||
``` | ||
|
||
## Dependencies | ||
|
||
- quais: ^1.0.0-alpha.25 | ||
- @elizaos/core: workspace:* | ||
|
||
## Contributing | ||
|
||
Contributions are welcome! Please ensure your code follows the existing patterns and includes appropriate tests. | ||
|
||
## Credits | ||
|
||
This plugin integrates with: | ||
- [Quai Network](https://qu.ai/) | ||
- [Quai JavaScript API](https://www.npmjs.com/package/quais) | ||
|
||
For more information about Quai Network capabilities: | ||
- [Quai Documentation](https://docs.qu.ai/) | ||
- [Quai Network GitHub](https://github.com/dominant-strategies) | ||
|
||
## License | ||
|
||
This plugin is part of the Eliza project. See the main project repository for license information. |
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,176 @@ | ||
import { | ||
ActionExample, | ||
HandlerCallback, | ||
IAgentRuntime, | ||
Memory, | ||
ModelClass, | ||
State, | ||
type Action, | ||
composeContext, | ||
generateObject, | ||
} from "@elizaos/core"; | ||
import { | ||
getQuaiAccount, | ||
isTransferContent, | ||
validateSettings, | ||
} from "../utils"; | ||
import { formatUnits, TransactionRequest } from "quais"; | ||
|
||
const transferTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. | ||
Example response: | ||
\`\`\`json | ||
{ | ||
"tokenAddress": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", | ||
"recipient": "0x0005C06bD1339c79700a8DAb35DE0a1b61dFBD71", | ||
"amount": "0.001" | ||
} | ||
\`\`\` | ||
{{recentMessages}} | ||
Given the recent messages, extract the following information about the requested token transfer: | ||
- Token contract address (if available) | ||
- Recipient wallet address | ||
- Amount to send | ||
Respond with a JSON markdown block containing only the extracted values.`; | ||
|
||
export default { | ||
name: "SEND_TOKEN", | ||
similes: [ | ||
"TRANSFER_TOKEN_ON_QUAI", | ||
"TRANSFER_TOKENS_ON_QUAI", | ||
"SEND_TOKENS_ON_QUAI", | ||
"SEND_QUAI", | ||
"PAY_ON_QUAI", | ||
], | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
return validateSettings(runtime); | ||
}, | ||
description: | ||
"MUST use this action if the user requests send a token or transfer a token, the request might be varied, but it will always be a token transfer. If the user requests a transfer of lords, use this action.", | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State, | ||
_options: { [key: string]: unknown }, | ||
callback?: HandlerCallback | ||
): Promise<boolean> => { | ||
console.log("Starting TRANSFER_TOKEN handler..."); | ||
|
||
// Initialize or update state | ||
if (!state) { | ||
state = (await runtime.composeState(message)) as State; | ||
} else { | ||
state = await runtime.updateRecentMessageState(state); | ||
} | ||
|
||
// Compose transfer context | ||
const transferContext = composeContext({ | ||
state, | ||
template: transferTemplate, | ||
}); | ||
|
||
// Generate transfer content | ||
const content = await generateObject({ | ||
runtime, | ||
context: transferContext, | ||
modelClass: ModelClass.MEDIUM, | ||
}); | ||
|
||
console.log("Transfer content:", content); | ||
|
||
// Validate transfer content | ||
if (!isTransferContent(content)) { | ||
console.error("Invalid content for TRANSFER_TOKEN action."); | ||
if (callback) { | ||
callback({ | ||
text: "Not enough information to transfer tokens. Please respond with token address, recipient, and amount.", | ||
content: { error: "Invalid transfer content" }, | ||
}); | ||
} | ||
return false; | ||
} | ||
|
||
try { | ||
const account = getQuaiAccount(runtime); | ||
const amount = formatUnits(content.amount, "wei"); | ||
|
||
var txObj: TransactionRequest = {}; | ||
if (content.tokenAddress) { | ||
// TODO: transfer QRC20s | ||
} else { | ||
txObj = { | ||
to: content.recipient, | ||
value: amount, | ||
from: account.address, | ||
}; | ||
|
||
console.log( | ||
"Transferring", | ||
amount, | ||
"QUAI", | ||
"to", | ||
content.recipient | ||
); | ||
} | ||
|
||
const tx = await account.sendTransaction(txObj) | ||
|
||
console.log( | ||
"Transfer completed successfully! tx: " + tx.hash | ||
); | ||
if (callback) { | ||
callback({ | ||
text: | ||
"Transfer completed successfully! tx: " + | ||
tx.hash, | ||
content: {}, | ||
}); | ||
} | ||
|
||
return true; | ||
} catch (error) { | ||
console.error("Error during token transfer:", error); | ||
if (callback) { | ||
callback({ | ||
text: `Error transferring tokens: ${error.message}`, | ||
content: { error: error.message }, | ||
}); | ||
} | ||
return false; | ||
} | ||
}, | ||
|
||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Send 10 QUAI to 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "I'll transfer 10 QUAI to that address right away. Let me process that for you.", | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Please send 0.5 QUAI to 0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Got it, initiating transfer of 0.5 QUAI to the provided address. I'll confirm once it's complete.", | ||
}, | ||
}, | ||
], | ||
] as ActionExample[][], | ||
} as Action; |
Oops, something went wrong.