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.
- Loading branch information
Showing
8 changed files
with
394 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
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,34 @@ | ||
{ | ||
"name": "eliza-convergence-plugin-workspace", | ||
"version": "0.1.0", | ||
"private": true, | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"scripts": { | ||
"build": "tsc", | ||
"clean": "rimraf dist", | ||
"dev": "tsc -w", | ||
"lint": "eslint src --ext .ts", | ||
"test": "jest" | ||
}, | ||
"dependencies": { | ||
"@convergence-rfq/sdk": "^0.1.0", | ||
"@eliza/core": "workspace:*", | ||
"@solana/spl-token": "^0.3.8", | ||
"@solana/web3.js": "^1.78.4", | ||
"bn.js": "^5.2.1", | ||
"decimal.js": "^10.4.3" | ||
}, | ||
"devDependencies": { | ||
"@types/bn.js": "^5.1.1", | ||
"@types/jest": "^29.5.3", | ||
"@types/node": "^20.4.5", | ||
"@typescript-eslint/eslint-plugin": "^6.2.0", | ||
"@typescript-eslint/parser": "^6.2.0", | ||
"eslint": "^8.45.0", | ||
"jest": "^29.6.2", | ||
"rimraf": "^5.0.1", | ||
"ts-jest": "^29.1.1", | ||
"typescript": "^5.1.6" | ||
} | ||
} |
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,219 @@ | ||
import { Plugin } from '@eliza/core'; | ||
import { | ||
Convergence, | ||
RfqState, | ||
MarketMakerState, | ||
CollateralAccount, | ||
QuoteState | ||
} from '@convergence-rfq/sdk'; | ||
import { Connection, PublicKey, Transaction } from '@solana/web3.js'; | ||
import { RfqRequest, QuoteMetadata } from './types'; | ||
|
||
export class ConvergencePlugin implements Plugin { | ||
private convergence: Convergence; | ||
|
||
constructor(config: ConvergencePluginConfig) { | ||
const connection = new Connection(config.endpoint, config.commitment); | ||
this.convergence = new Convergence(connection); | ||
} | ||
|
||
async onMessage(message: string): Promise<string> { | ||
const parts = message.split(' '); | ||
const command = parts[1]?.toLowerCase(); | ||
|
||
switch (command) { | ||
// RFQ Management | ||
case 'create': | ||
return this.handleCreateRfq(parts.slice(2)); | ||
case 'cancel': | ||
return this.handleCancelRfq(parts.slice(2)); | ||
case 'status': | ||
return this.handleStatusCheck(parts[2]); | ||
|
||
// Quote Management | ||
case 'respond': | ||
return this.handleRespond(parts.slice(2)); | ||
case 'revoke': | ||
return this.handleRevokeQuote(parts.slice(2)); | ||
case 'accept': | ||
return this.handleAcceptQuote(parts.slice(2)); | ||
|
||
// Collateral Management | ||
case 'deposit': | ||
return this.handleDeposit(parts.slice(2)); | ||
case 'withdraw': | ||
return this.handleWithdraw(parts.slice(2)); | ||
case 'balance': | ||
return this.handleCheckBalance(parts.slice(2)); | ||
|
||
// Market Maker Management | ||
case 'register': | ||
return this.handleRegisterMM(parts.slice(2)); | ||
case 'verify': | ||
return this.handleVerifyIdentity(parts.slice(2)); | ||
|
||
// Settlement | ||
case 'settle': | ||
return this.handleSettle(parts.slice(2)); | ||
|
||
default: | ||
return this.getHelpMessage(); | ||
} | ||
} | ||
|
||
// RFQ Management Methods | ||
private async handleCreateRfq(args: string[]): Promise<string> { | ||
try { | ||
const [baseToken, quoteToken, amount, side, expiryMins, ...options] = args; | ||
|
||
const request: RfqRequest = { | ||
baseToken: await this.getTokenInfo(baseToken, parseFloat(amount)), | ||
quoteToken: await this.getTokenInfo(quoteToken, 0), | ||
side: side as 'buy' | 'sell', | ||
expiry: Math.floor(Date.now() / 1000) + (parseInt(expiryMins) * 60), | ||
minCompetitors: options.includes('--min-competitors') ? 3 : undefined, | ||
allowPartialFills: options.includes('--partial-fills'), | ||
requireVerifiedIdentity: options.includes('--verified-only') | ||
}; | ||
|
||
const rfq = await this.convergence.createRfq(request); | ||
return `RFQ created with ID: ${rfq.id}`; | ||
} catch (error) { | ||
return `Error creating RFQ: ${error.message}`; | ||
} | ||
} | ||
|
||
private async handleCancelRfq(args: string[]): Promise<string> { | ||
try { | ||
const [rfqId] = args; | ||
await this.convergence.cancelRfq(rfqId); | ||
return `RFQ ${rfqId} cancelled successfully`; | ||
} catch (error) { | ||
return `Error cancelling RFQ: ${error.message}`; | ||
} | ||
} | ||
|
||
// Quote Management Methods | ||
private async handleRespond(args: string[]): Promise<string> { | ||
try { | ||
const [rfqId, price, size] = args; | ||
|
||
const quote = await this.convergence.createQuote({ | ||
rfqId, | ||
price: parseFloat(price), | ||
size: parseFloat(size), | ||
expiresAt: Math.floor(Date.now() / 1000) + 300 // 5 minutes | ||
}); | ||
|
||
return `Quote submitted: ${quote.id}`; | ||
} catch (error) { | ||
return `Error submitting quote: ${error.message}`; | ||
} | ||
} | ||
|
||
private async handleRevokeQuote(args: string[]): Promise<string> { | ||
try { | ||
const [quoteId] = args; | ||
await this.convergence.revokeQuote(quoteId); | ||
return `Quote ${quoteId} revoked successfully`; | ||
} catch (error) { | ||
return `Error revoking quote: ${error.message}`; | ||
} | ||
} | ||
|
||
// Collateral Management Methods | ||
private async handleDeposit(args: string[]): Promise<string> { | ||
try { | ||
const [token, amount] = args; | ||
const tx = await this.convergence.depositCollateral({ | ||
mint: new PublicKey(token), | ||
amount: parseFloat(amount) | ||
}); | ||
return `Deposit successful: ${tx}`; | ||
} catch (error) { | ||
return `Error depositing collateral: ${error.message}`; | ||
} | ||
} | ||
|
||
private async handleWithdraw(args: string[]): Promise<string> { | ||
try { | ||
const [token, amount] = args; | ||
const tx = await this.convergence.withdrawCollateral({ | ||
mint: new PublicKey(token), | ||
amount: parseFloat(amount) | ||
}); | ||
return `Withdrawal successful: ${tx}`; | ||
} catch (error) { | ||
return `Error withdrawing collateral: ${error.message}`; | ||
} | ||
} | ||
|
||
private async handleCheckBalance(args: string[]): Promise<string> { | ||
try { | ||
const [token] = args; | ||
const balance = await this.convergence.getCollateralBalance(new PublicKey(token)); | ||
return `Balance: ${balance.amount} ${balance.symbol}`; | ||
} catch (error) { | ||
return `Error checking balance: ${error.message}`; | ||
} | ||
} | ||
|
||
// Market Maker Methods | ||
private async handleRegisterMM(args: string[]): Promise<string> { | ||
try { | ||
const [identity] = args; | ||
await this.convergence.registerMarketMaker(identity); | ||
return `Successfully registered as market maker`; | ||
} catch (error) { | ||
return `Error registering as market maker: ${error.message}`; | ||
} | ||
} | ||
|
||
private async handleVerifyIdentity(args: string[]): Promise<string> { | ||
try { | ||
const [proof] = args; | ||
await this.convergence.verifyIdentity(proof); | ||
return `Identity verified successfully`; | ||
} catch (error) { | ||
return `Error verifying identity: ${error.message}`; | ||
} | ||
} | ||
|
||
// Settlement Methods | ||
private async handleSettle(args: string[]): Promise<string> { | ||
try { | ||
const [rfqId] = args; | ||
const tx = await this.convergence.settleRfq(rfqId); | ||
return `RFQ settled successfully: ${tx}`; | ||
} catch (error) { | ||
return `Error settling RFQ: ${error.message}`; | ||
} | ||
} | ||
|
||
private getHelpMessage(): string { | ||
return ` | ||
Available commands: | ||
RFQ Management: | ||
/rfq create <base> <quote> <amount> <side> <expiry_mins> [--min-competitors] [--partial-fills] [--verified-only] | ||
/rfq cancel <rfq_id> | ||
/rfq status <rfq_id> | ||
Quote Management: | ||
/rfq respond <rfq_id> <price> <size> | ||
/rfq revoke <quote_id> | ||
/rfq accept <quote_id> | ||
Collateral Management: | ||
/rfq deposit <token> <amount> | ||
/rfq withdraw <token> <amount> | ||
/rfq balance <token> | ||
Market Maker: | ||
/rfq register <identity> | ||
/rfq verify <proof> | ||
Settlement: | ||
/rfq settle <rfq_id> | ||
`; | ||
} | ||
} |
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,31 @@ | ||
import { PublicKey } from '@solana/web3.js'; | ||
|
||
export interface TokenInfo { | ||
mint: PublicKey; | ||
amount: number; | ||
decimals: number; | ||
} | ||
|
||
export interface RfqRequest { | ||
baseToken: TokenInfo; | ||
quoteToken: TokenInfo; | ||
side: 'buy' | 'sell'; | ||
expiry: number; | ||
minCompetitors?: number; | ||
allowPartialFills?: boolean; | ||
requireVerifiedIdentity?: boolean; | ||
} | ||
|
||
export interface MarketMakerInfo { | ||
pubkey: PublicKey; | ||
identity: string; | ||
verified: boolean; | ||
} | ||
|
||
export interface QuoteMetadata { | ||
rfqId: string; | ||
price: number; | ||
size: number; | ||
expiresAt: number; | ||
marketMaker: MarketMakerInfo; | ||
} |
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,18 @@ | ||
import { Connection, PublicKey } from '@solana/web3.js'; | ||
import { TokenInfo } from '../types'; | ||
import { getMint } from '@solana/spl-token'; | ||
|
||
export async function getTokenInfo( | ||
connection: Connection, | ||
mintAddress: string, | ||
amount: number | ||
): Promise<TokenInfo> { | ||
const mint = new PublicKey(mintAddress); | ||
const mintInfo = await getMint(connection, mint); | ||
|
||
return { | ||
mint, | ||
amount, | ||
decimals: mintInfo.decimals | ||
}; | ||
} |
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,11 @@ | ||
import { ConvergencePlugin } from '@eliza/plugin-convergence'; | ||
|
||
export const config = { | ||
plugins: [ | ||
new ConvergencePlugin({ | ||
endpoint: process.env.SOLANA_RPC_ENDPOINT || 'https://api.mainnet-beta.solana.com', | ||
commitment: 'confirmed' | ||
}) | ||
], | ||
// ... other configuration options | ||
}; |
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,12 @@ | ||
{ | ||
"extends": "../../tsconfig.base.json", | ||
"compilerOptions": { | ||
"outDir": "./dist", | ||
"rootDir": "./src", | ||
"composite": true | ||
}, | ||
"include": ["src/**/*"], | ||
"references": [ | ||
{ "path": "../core" } | ||
] | ||
} |
Oops, something went wrong.