+---------------------+ +------------------------+
| | | |
| Eliza OS Core | | PayID Backend API |
| | | |
+----------+----------+ +-----------+------------+
^ ^
| |
| |
+----------+-----------------+ |
| | |
| PayID Plugin Entry +----------+
| |
+---+---------+--------+-----+
| | |
v v v
+---+---+ +---+---+ +--+----+
| | | | | |
|Actions| |Service| | Types |
| | | | | |
+-------+ +---+---+ +-------+
|
v
+-----+------+
| |
| Events |
| |
+------------+
index.ts)The entry point defines plugin metadata and registers components with the Eliza runtime.
import { ElizaPlugin, PluginContext } from '@eliza/plugin-sdk';
import { PayIDService } from './services/payid.service';
import { registerActions } from './actions';
import { registerEventHandlers } from './events';
import { PayIDPluginConfig } from './types';
export default class PayIDPlugin implements ElizaPlugin {
name = 'payid-plugin';
version = '1.0.0';
description = 'PayID functionality for Eliza OS agents';
async initialize(context: PluginContext): Promise<void> {
// Extract config
const config = context.config as PayIDPluginConfig;
// Validate configuration
if (!config.apiKey) {
throw new Error('PayID API key is required');
}
// Register the PayID service
const payIDService = new PayIDService(config.apiKey, config.baseUrl || '<https://api.reveel.id/v1>');
context.registerService('payid', payIDService);
// Register actions
registerActions(context);
// Register event handlers
registerEventHandlers(context);
console.log('PayID plugin initialized successfully');
}
}
services/payid.service.ts)The core service that handles communication with the PayID API.
import axios, { AxiosInstance } from 'axios';
import {
ClaimPayIdRequest,
SearchPayIdsRequest,
CheckPriceRequest,
InitTransactionRequest,
CreateRouteRequest,
TransactionActivity,
PayIdRoute,
SupportedToken,
SupportedNetwork
} from '../types';
export class PayIDService {
private client: AxiosInstance;
constructor(private apiKey: string, private baseUrl: string) {
this.client = axios.create({
baseURL: baseUrl,
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
}
/**
* Claim a PayID for a user
*/
async claimPayId(params: ClaimPayIdRequest): Promise<any> {
try {
const response = await this.client.post('/pay-ids', {
name: params.name,
userId: params.userId
});
const { data } = response.data;
return data;
} catch (error) {
if (error.response?.status === 409) {
throw new Error('PayID already taken');
}
throw new Error(`Failed to claim PayID: ${error.message}`);
}
}
/**
* Search for PayIDs
*/
async searchPayIds(params: SearchPayIdsRequest): Promise<any> {
try {
const response = await this.client.get('/pay-ids/search', {
params: {
q: params.query,
limit: params.limit || 10,
activeOnly: params.activeOnly || true
}
});
const { data } = response.data;
return data.payIds;
} catch (error) {
throw new Error(`Failed to search for PayIDs: ${error.message}`);
}
}
/**
* Initialize a transaction
*/
async initTransaction(params: InitTransactionRequest): Promise<any> {
try {
const payload: any = {
userId: params.userId,
amount: params.amount,
token: params.token,
network: params.network
};
if (params.recipientPayId) {
payload.recipientPayId = params.recipientPayId;
} else if (params.walletAddress) {
payload.walletAddress = params.walletAddress;
} else {
throw new Error('Either recipientPayId or walletAddress must be provided');
}
if (params.message) {
payload.message = params.message;
}
const response = await this.client.post('/transactions', payload);
const { data } = response.data;
return data;
} catch (error) {
throw new Error(`Failed to initialize transaction: ${error.message}`);
}
}
/**
* Create a payment route
*/
async createRoute(params: CreateRouteRequest): Promise<PayIdRoute> {
try {
const response = await this.client.post('/routes', {
userId: params.userId,
name: params.name,
incomingNetworks: params.incomingNetworks,
incomingTokens: params.incomingTokens,
incomingWallets: params.incomingWallets || [],
swapNetwork: params.swapNetwork || null,
swapToken: params.swapToken || null,
outgoingWallet: params.outgoingWallet
});
const { data } = response.data;
return data.route;
} catch (error) {
throw new Error(`Failed to create route: ${error.message}`);
}
}
/**
* Get routes for a user
*/
async getRoutes(userId: string): Promise<PayIdRoute[]> {
try {
const response = await this.client.get(`/routes/${userId}`);
const { data } = response.data;
return data.routes;
} catch (error) {
throw new Error(`Failed to get routes: ${error.message}`);
}
}
/**
* Get transaction history for a user
*/
async getTransactionHistory(userId: string, page: number = 1, pageSize: number = 10): Promise<{activities: TransactionActivity[], pagination: any}> {
try {
const response = await this.client.get(`/transactions/users/${userId}/activities`, {
params: {
page,
pageSize
}
});
const { data } = response.data;
return data;
} catch (error) {
throw new Error(`Failed to get transaction history: ${error.message}`);
}
}
/**
* Get supported tokens and networks
*/
getSupportedTokens(): SupportedToken[] {
return ['USDT', 'USDC', 'ETH', 'BNB', 'POL'];
}
getSupportedNetworks(): SupportedNetwork[] {
return ['ETH', 'POL', 'OP', 'BNB', 'BASE'];
}
/**
* Validate token/network compatibility
*/
isValidTokenNetworkPair(token: SupportedToken, network: SupportedNetwork): boolean {
// Based on the API documentation, these combinations are not supported
const invalidCombinations = [
{ token: 'POL', network: 'OP' },
{ token: 'BNB', network: 'OP' },
{ token: 'USDT', network: 'BASE' },
{ token: 'BNB', network: 'BASE' },
{ token: 'POL', network: 'BASE' }
];
return !invalidCombinations.some(
combo => combo.token === token && combo.network === network
);
}
}
actions/index.ts)Defines actions that agents can execute through the Eliza runtime.
import { PluginContext } from '@eliza/plugin-sdk';
import {
ClaimPayIdRequest,
SearchPayIdsRequest,
InitTransactionRequest,
CreateRouteRequest
} from '../types';
export function registerActions(context: PluginContext) {
// Action to claim a PayID
context.registerAction('claimPayId', async (params: ClaimPayIdRequest) => {
const payIdService = context.getService('payid');
return await payIdService.claimPayId(params);
});
// Action to search for PayIDs
context.registerAction('searchPayIds', async (params: SearchPayIdsRequest) => {
const payIdService = context.getService('payid');
return await payIdService.searchPayIds(params);
});
// Action to initialize a transaction
context.registerAction('initTransaction', async (params: InitTransactionRequest) => {
const payIdService = context.getService('payid');
return await payIdService.initTransaction(params);
});
// Action to create a payment route
context.registerAction('createRoute', async (params: CreateRouteRequest) => {
const payIdService = context.getService('payid');
return await payIdService.createRoute(params);
});
// Action to get routes for a user
context.registerAction('getRoutes', async (userId: string) => {
const payIdService = context.getService('payid');
return await payIdService.getRoutes(userId);
});
// Action to get transaction history
context.registerAction('getTransactionHistory', async (userId: string, page?: number, pageSize?: number) => {
const payIdService = context.getService('payid');
return await payIdService.getTransactionHistory(userId, page, pageSize);
});
// Utility actions
context.registerAction('getSupportedTokens', () => {
const payIdService = context.getService('payid');
return payIdService.getSupportedTokens();
});
context.registerAction('getSupportedNetworks', () => {
const payIdService = context.getService('payid');
return payIdService.getSupportedNetworks();
});
context.registerAction('validateTokenNetworkPair', (token, network) => {
const payIdService = context.getService('payid');
return payIdService.isValidTokenNetworkPair(token, network);
});
}
events/index.ts)