Process Transaction
Endpoint: POST /api/v1/coin/tx
Description
This endpoint processes buy/sell transactions for tokens, updates OHLC (candlestick) data, records transaction details, and updates market cap. It also broadcasts updates through WebSocket for real-time price tracking.
Authentication
Required: Yes
Type: Bearer Token (JWT)
Request
Headers
Content-Type: application/json
Authorization: Bearer <your_jwt_token>
Body Parameters
token
string
Yes
The mint address of the token
txHash
string
Yes
The transaction hash/signature
type
string
Yes
Transaction type ('buy' or 'sell')
isInitial
boolean
No
Flag for initial token creation transaction
Example Request:
{
"token": "TokenMintAddress123...",
"txHash": "TransactionHash456...",
"type": "buy",
"isInitial": false
}
Response
Success Response
Status Code: 200 OK
Content-Type: application/json
interface TransactionResponse {
success: true;
txDetails: {
price: string;
tokenAmount: string;
solAmount: string;
blockTime: number;
metadata: any;
};
message: string;
}
Error Response
Status Code: 500 Internal Server Error
{
"error": "An internal error occurred. Please try again later."
}
Implementation Notes
OHLC Data Processing
interface OHLCData {
coinId: string;
timestamp: Date;
unixTimestamp: string;
open: string;
high: string;
low: string;
close: string;
volume: string;
numberOfTrades: number;
}
// Helper function to get 1-minute bucket timestamp
function get1MinBucketTimestamp(date: Date): Date {
const roundedDate = new Date(date);
roundedDate.setSeconds(0);
roundedDate.setMilliseconds(0);
return roundedDate;
}
// Process OHLC data for a transaction
async function processOHLCData(
coinId: string,
price: number,
quantity: number,
timestamp: Date
): Promise<void> {
const bucketTimestamp = get1MinBucketTimestamp(timestamp);
// Update or create candle logic
// ... implementation details in the code ...
}
Transaction Processing
// Example transaction processor
class TransactionProcessor {
constructor(
private readonly token: string,
private readonly txHash: string,
private readonly type: 'buy' | 'sell'
) {}
async process(): Promise<TransactionResponse> {
// Get current reserves
const reserveDetails = await this.getReserves();
const newPrice = this.calculatePrice(reserveDetails);
// Get transaction details
const txDetails = await this.getTransactionDetails();
// Process OHLC data
await this.updateOHLCData(txDetails, newPrice);
// Record transaction
await this.recordTransaction(txDetails);
// Update market cap
await this.updateMarketCap(newPrice);
return {
success: true,
txDetails,
message: "Transaction processed successfully"
};
}
private async getReserves() {
return await reserves(this.token);
}
private calculatePrice(reserveDetails: any) {
return reserveDetails.reserveTwo / reserveDetails.reserveOne;
}
private async getTransactionDetails() {
return this.type === 'buy'
? await getBuyTokenDetails(this.txHash)
: await getSellTokenDetails(this.txHash);
}
// ... additional helper methods ...
}
WebSocket Updates
// Example WebSocket notification handler
class TransactionNotifier {
private static instance: TransactionNotifier;
private connections: Map<string, Set<WebSocket>> = new Map();
static getInstance(): TransactionNotifier {
if (!TransactionNotifier.instance) {
TransactionNotifier.instance = new TransactionNotifier();
}
return TransactionNotifier.instance;
}
addConnection(tokenId: string, ws: WebSocket) {
if (!this.connections.has(tokenId)) {
this.connections.set(tokenId, new Set());
}
this.connections.get(tokenId)?.add(ws);
}
notifyUpdate(tokenId: string, data: OHLCData) {
const connections = this.connections.get(tokenId);
if (connections) {
connections.forEach(ws => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'OHLC_UPDATE',
data
}));
}
});
}
}
}
Best Practices
1. Transaction Validation
class TransactionValidator {
static validateBuyTransaction(txDetails: any): boolean {
return !!(
txDetails.price &&
txDetails.tokenAmount &&
txDetails.solAmount &&
txDetails.blockTime
);
}
static validateSellTransaction(txDetails: any): boolean {
return !!(
txDetails.price &&
txDetails.tokenAmount &&
txDetails.blockTime
);
}
static async validateReserves(
token: string,
expectedPrice: number
): Promise<boolean> {
const reserveDetails = await reserves(token);
const currentPrice =
reserveDetails.reserveTwo / reserveDetails.reserveOne;
// Allow for 1% price deviation
const deviation = Math.abs(currentPrice - expectedPrice) / expectedPrice;
return deviation <= 0.01;
}
}
Market Cap Updates
async function updateMarketCap(
token: string,
price: number
): Promise<void> {
const marketCap = price * config.constants.tokenSupply;
await db.update(coinsTable)
.set({ marketCap: String(marketCap) })
.where(eq(coinsTable.mintAddress, token));
// Notify subscribers of market cap update
publishMarketCapUpdate(token, marketCap);
}
Error Handling
class TransactionError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly details?: any
) {
super(message);
this.name = 'TransactionError';
}
}
function handleTransactionError(error: any) {
if (error instanceof TransactionError) {
// Handle known error types
console.error(`Transaction Error (${error.code}):`, error.message);
return {
error: error.message,
code: error.code,
details: error.details
};
}
// Handle unknown errors
console.error('Unknown Transaction Error:', error);
return {
error: 'An internal error occurred. Please try again later.',
code: 'UNKNOWN_ERROR'
};
}
Last updated