-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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 #2 from APRO-com/20250205
Rename the plugin name from plugin-apro to plugin-ATTPs
- Loading branch information
Showing
17 changed files
with
1,753 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
|
||
# @elizaos/plugin-attps | ||
|
||
Foundation plugin that enables advanced agent interactions, data verification, and price queries on the Eliza OS platform. It streamlines agent creation, verification processes, and provides a flexible framework for building robust agent-based solutions. | ||
|
||
## Overview | ||
|
||
The ATTPs plugin bridges agent-based logic with the Eliza ecosystem. It handles agent registration, data verification, and price queries, empowering both automated and user-driven workflows. | ||
|
||
## Features | ||
|
||
### Agent Operations | ||
- **Agent Creation**: Deploy new agents with custom settings | ||
- **Registration**: Register agents on-chain or via standardized processes | ||
- **Multi-Signer Framework**: Supports threshold-based approval flows | ||
|
||
### Data Verification | ||
- **Chain Validation**: Verify data authenticity on-chain | ||
- **Transaction Execution**: Handle verification logic with built-in security checks | ||
- **Auto-Hashing**: Convert raw data to hashed formats when needed | ||
- **Metadata Parsing**: Validate content type, encoding, and compression | ||
|
||
### Price Queries | ||
- **Live Price Data**: Fetch price information for various pairs | ||
- **Format Validation**: Normalize user query inputs to standard trading-pair formats | ||
- **APIs Integration**: Retrieve real-time or near-real-time pricing information | ||
|
||
## Security Features | ||
|
||
### Access Control | ||
- **Private Key Management**: Safe usage of private keys for transaction signing | ||
- **Environment Variables**: Secure injection of credentials | ||
- **On-Chain Validation**: Leverage on-chain contract checks | ||
|
||
### Verification | ||
- **Input Validation**: Strict schema checks before on-chain operations | ||
- **Transaction Receipts**: Provide verifiable transaction details | ||
- **Error Handling**: Detailed error logs for quick debugging | ||
|
||
## Installation | ||
|
||
```bash | ||
npm install @elizaos/plugin-attps | ||
``` | ||
|
||
## Configuration | ||
|
||
Configure the plugin by setting environment variables or runtime settings: | ||
- ATTPS_RPC_URL | ||
- ATTPS_PROXY_ADDRESS | ||
- ATTPS_PRIVATE_KEY | ||
- ATTPS_CONVERTER_ADDRESS | ||
- ATTPS_AUTO_HASH_DATA | ||
|
||
## Usage | ||
|
||
### Basic Setup | ||
```typescript | ||
import { attpsPlugin } from "@elizaos/plugin-attps"; | ||
|
||
// Initialize the plugin | ||
const runtime = await initializeRuntime({ | ||
plugins: [attpsPlugin], | ||
}); | ||
``` | ||
|
||
### Actions | ||
|
||
#### CREATE_AND_REGISTER_AGENT | ||
Creates and registers an agent using specified settings. | ||
|
||
```typescript | ||
const result = await runtime.executeAction("CREATE_AND_REGISTER_AGENT", { | ||
signers: [...], | ||
threshold: 3, | ||
agentHeader: { ... }, | ||
// ...other fields... | ||
}); | ||
``` | ||
|
||
#### VERIFY | ||
Verifies data on-chain via the Agent SDK. | ||
|
||
```typescript | ||
const result = await runtime.executeAction("VERIFY", { | ||
payload: { | ||
data: "0x...hexData", | ||
signatures: [...], | ||
}, | ||
agent: "0x...agentAddress", | ||
digest: "0x...digestString", | ||
}); | ||
``` | ||
|
||
#### PRICE_QUERY | ||
Fetches live price data for a specified trading pair. | ||
|
||
```typescript | ||
const result = await runtime.executeAction("PRICE_QUERY", { | ||
pair: "BTC/USD", | ||
}); | ||
``` | ||
|
||
## Performance Optimization | ||
|
||
1. **Cache Management** | ||
- Implement caching for frequent queries | ||
- Monitor retrieval times and cache hits | ||
|
||
2. **Network Efficiency** | ||
- Batch requests where possible | ||
- Validate response parsing to reduce overhead | ||
|
||
## System Requirements | ||
- Node.js 16.x or higher | ||
- Sufficient network access to on-chain endpoints | ||
- Basic configuration of environment variables | ||
- Minimum 4GB RAM recommended | ||
|
||
## Troubleshooting | ||
|
||
1. **Invalid Agent Settings** | ||
- Ensure signers and threshold are correct | ||
- Validate agentHeader for proper UUIDs and numeric values | ||
|
||
2. **Verification Failures** | ||
- Check the input data formats | ||
- Confirm environment variables are set | ||
|
||
3. **Price Query Errors** | ||
- Verify the trading pair format | ||
- Check external API availability | ||
|
||
## Safety & Security | ||
|
||
1. **Credential Management** | ||
- Store private keys securely | ||
- Do not commit secrets to version control | ||
|
||
2. **Transaction Limits** | ||
- Configure thresholds to mitigate abuse | ||
- Log transaction attempts and failures | ||
|
||
3. **Monitoring & Logging** | ||
- Track unusual activity | ||
- Maintain detailed audit logs | ||
|
||
## Support | ||
|
||
For issues or feature requests: | ||
1. Check existing documentation | ||
2. Submit a GitHub issue with relevant details | ||
3. Include transaction logs and system info if applicable | ||
|
||
## Contributing | ||
|
||
We welcome pull requests! Refer to the project’s CONTRIBUTING.md and open discussions to coordinate efforts. | ||
|
||
## Credits | ||
|
||
- [APRO](https://www.apro.com/) - Plugin sponsor and partner | ||
- [ai-agent-sdk-js](https://github.com/APRO-com/ai-agent-sdk-js) - Underlying agent SDK | ||
- [ethers.js](https://docs.ethers.io/) - Transaction and contract interaction | ||
- Community contributors for feedback and testing | ||
|
||
For more information about Apro plugin capabilities: | ||
|
||
- [Apro Documentation](https://docs.apro.com/en) | ||
|
||
## License | ||
|
||
This plugin is part of the Eliza project. Refer to the main project repository for licensing details. |
174 changes: 174 additions & 0 deletions
174
packages/plugin-attps/__tests__/actions/attpsPriceQuery.test.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,174 @@ | ||
// Mock declarations must come first | ||
vi.mock('@elizaos/core'); | ||
vi.mock('ai-agent-sdk-js'); | ||
|
||
import { vi, describe, it, expect, beforeEach } from 'vitest'; | ||
import type { IAgentRuntime, Memory, State } from '@elizaos/core'; | ||
import { generateObject } from '@elizaos/core'; | ||
import { attpsPriceQuery } from '../../src/actions/attpsPriceQuery'; | ||
|
||
describe('attpsPriceQuery', () => { | ||
const mockRuntime: IAgentRuntime = { | ||
composeState: vi.fn(), | ||
updateRecentMessageState: vi.fn(), | ||
getSetting: vi.fn() | ||
} as unknown as IAgentRuntime; | ||
|
||
const mockMessage: Memory = { | ||
userId: 'test-user', | ||
agentId: 'test-agent', | ||
roomId: 'test-room', | ||
content: { | ||
text: 'query price' | ||
} | ||
} as Memory; | ||
|
||
const mockState: State = {}; | ||
const mockCallback = vi.fn(); | ||
const mockFetch = vi.fn(); | ||
|
||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
vi.mocked(mockRuntime.composeState).mockResolvedValue(mockState); | ||
vi.mocked(mockRuntime.updateRecentMessageState).mockResolvedValue(mockState); | ||
global.fetch = mockFetch; | ||
}); | ||
|
||
describe('validate', () => { | ||
it('should always return true', async () => { | ||
const result = await attpsPriceQuery.validate(mockRuntime, mockMessage); | ||
expect(result).toBe(true); | ||
}); | ||
}); | ||
|
||
describe('handler', () => { | ||
const mockPriceQuery = { | ||
sourceAgentId: 'test-source-agent', | ||
feedId: 'test-feed' | ||
}; | ||
|
||
const mockPriceResponse = { | ||
code: 0, | ||
message: 'success', | ||
result: { | ||
askPrice: '100.50', | ||
bidPrice: '100.40', | ||
midPrice: '100.45', | ||
validTimeStamp: '1234567890' | ||
} | ||
}; | ||
|
||
it('should successfully fetch price data', async () => { | ||
// Mock generateObject to return price query params | ||
vi.mocked(generateObject).mockResolvedValueOnce({ | ||
object: mockPriceQuery | ||
}); | ||
|
||
// Mock successful API response | ||
mockFetch.mockResolvedValueOnce({ | ||
json: () => Promise.resolve(mockPriceResponse) | ||
}); | ||
|
||
const result = await attpsPriceQuery.handler( | ||
mockRuntime, | ||
mockMessage, | ||
mockState, | ||
{}, | ||
mockCallback | ||
); | ||
|
||
expect(mockCallback).toHaveBeenCalledWith(expect.objectContaining({ | ||
text: expect.stringContaining('Ask price: 100.5') | ||
})); | ||
expect(mockFetch).toHaveBeenCalledWith( | ||
expect.stringContaining('sourceAgentId=test-source-agent') | ||
); | ||
}); | ||
|
||
it('should handle price query params generation failure', async () => { | ||
// Mock generateObject to throw an error | ||
vi.mocked(generateObject).mockRejectedValueOnce( | ||
new Error('Failed to generate params') | ||
); | ||
|
||
await attpsPriceQuery.handler( | ||
mockRuntime, | ||
mockMessage, | ||
mockState, | ||
{}, | ||
mockCallback | ||
); | ||
|
||
expect(mockCallback).toHaveBeenCalledWith({ | ||
text: expect.stringContaining('Failed to generate price query params') | ||
}); | ||
}); | ||
|
||
it('should handle API error response', async () => { | ||
// Mock generateObject to return price query params | ||
vi.mocked(generateObject).mockResolvedValueOnce({ | ||
object: mockPriceQuery | ||
}); | ||
|
||
// Mock API error response | ||
mockFetch.mockResolvedValueOnce({ | ||
json: () => Promise.resolve({ | ||
code: 1, | ||
message: 'API Error' | ||
}) | ||
}); | ||
|
||
await attpsPriceQuery.handler( | ||
mockRuntime, | ||
mockMessage, | ||
mockState, | ||
{}, | ||
mockCallback | ||
); | ||
|
||
expect(mockCallback).toHaveBeenCalledWith({ | ||
text: 'Error fetching price data: API Error' | ||
}); | ||
}); | ||
|
||
it('should handle network failure', async () => { | ||
// Mock generateObject to return price query params | ||
vi.mocked(generateObject).mockResolvedValueOnce({ | ||
object: mockPriceQuery | ||
}); | ||
|
||
// Mock network failure | ||
mockFetch.mockRejectedValueOnce(new Error('Network error')); | ||
|
||
await attpsPriceQuery.handler( | ||
mockRuntime, | ||
mockMessage, | ||
mockState, | ||
{}, | ||
mockCallback | ||
); | ||
|
||
expect(mockCallback).toHaveBeenCalledWith({ | ||
text: 'Error fetching price data: Network error' | ||
}); | ||
}); | ||
}); | ||
|
||
describe('metadata', () => { | ||
it('should have correct name and description', () => { | ||
expect(attpsPriceQuery.name).toBe('ATTPS_PRICE_QUERY'); | ||
expect(attpsPriceQuery.description).toContain('Call remote API to fetch price data'); | ||
}); | ||
|
||
it('should have valid examples', () => { | ||
expect(Array.isArray(attpsPriceQuery.examples)).toBe(true); | ||
expect(attpsPriceQuery.examples.length).toBeGreaterThan(0); | ||
|
||
attpsPriceQuery.examples.forEach(example => { | ||
expect(Array.isArray(example)).toBe(true); | ||
expect(example.length).toBe(2); | ||
expect(example[1].content.action).toBe('ATTPS_PRICE_QUERY'); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.