feat: comprehensive project improvements and fixes
- Fix all TypeScript compilation errors (40+ fixes) - Add missing type definitions (TransactionRequest, SafeInfo) - Fix TransactionRequestStatus vs TransactionStatus confusion - Fix import paths and provider type issues - Fix test file errors and mock providers - Implement comprehensive security features - AES-GCM encryption with PBKDF2 key derivation - Input validation and sanitization - Rate limiting and nonce management - Replay attack prevention - Access control and authorization - Add comprehensive test suite - Integration tests for transaction flow - Security validation tests - Wallet management tests - Encryption and rate limiter tests - E2E tests with Playwright - Add extensive documentation - 12 numbered guides (setup, development, API, security, etc.) - Security documentation and audit reports - Code review and testing reports - Project organization documentation - Update dependencies - Update axios to latest version (security fix) - Update React types to v18 - Fix peer dependency warnings - Add development tooling - CI/CD workflows (GitHub Actions) - Pre-commit hooks (Husky) - Linting and formatting (Prettier, ESLint) - Security audit workflow - Performance benchmarking - Reorganize project structure - Move reports to docs/reports/ - Clean up root directory - Organize documentation - Add new features - Smart wallet management (Gnosis Safe, ERC4337) - Transaction execution and approval workflows - Balance management and token support - Error boundary and monitoring (Sentry) - Fix WalletConnect configuration - Handle missing projectId gracefully - Add environment variable template
This commit is contained in:
104
helpers/relayers/index.ts
Normal file
104
helpers/relayers/index.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { TransactionRequest } from "../../types";
|
||||
|
||||
export interface RelayerService {
|
||||
id: string;
|
||||
name: string;
|
||||
apiUrl: string;
|
||||
apiKey?: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_RELAYERS: RelayerService[] = [
|
||||
{
|
||||
id: "openrelay",
|
||||
name: "OpenRelay",
|
||||
apiUrl: "https://api.openrelay.xyz/v1/relay",
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: "gelato",
|
||||
name: "Gelato",
|
||||
apiUrl: "https://relay.gelato.digital",
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: "custom",
|
||||
name: "Custom Relayer",
|
||||
apiUrl: "",
|
||||
enabled: false,
|
||||
},
|
||||
];
|
||||
|
||||
export async function submitToRelayer(
|
||||
tx: TransactionRequest,
|
||||
relayer: RelayerService
|
||||
): Promise<string> {
|
||||
if (!relayer.enabled || !relayer.apiUrl) {
|
||||
throw new Error(`Relayer ${relayer.name} is not configured`);
|
||||
}
|
||||
|
||||
const payload = {
|
||||
to: tx.to,
|
||||
value: tx.value || "0",
|
||||
data: tx.data || "0x",
|
||||
gasLimit: tx.gasLimit,
|
||||
gasPrice: tx.gasPrice,
|
||||
maxFeePerGas: tx.maxFeePerGas,
|
||||
maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
|
||||
};
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
if (relayer.apiKey) {
|
||||
headers["Authorization"] = `Bearer ${relayer.apiKey}`;
|
||||
}
|
||||
|
||||
const response = await fetch(relayer.apiUrl, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
throw new Error(`Relayer request failed: ${error}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result.txHash || result.hash || result.transactionHash;
|
||||
}
|
||||
|
||||
export async function getRelayerStatus(
|
||||
txHash: string,
|
||||
relayer: RelayerService
|
||||
): Promise<{ status: string; confirmed: boolean }> {
|
||||
if (!relayer.enabled || !relayer.apiUrl) {
|
||||
throw new Error(`Relayer ${relayer.name} is not configured`);
|
||||
}
|
||||
|
||||
const statusUrl = `${relayer.apiUrl}/status/${txHash}`;
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
if (relayer.apiKey) {
|
||||
headers["Authorization"] = `Bearer ${relayer.apiKey}`;
|
||||
}
|
||||
|
||||
const response = await fetch(statusUrl, {
|
||||
method: "GET",
|
||||
headers,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return { status: "unknown", confirmed: false };
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return {
|
||||
status: result.status || "pending",
|
||||
confirmed: result.confirmed || false,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user