feat: add optimistic locking and improve type safety
- Implement optimistic locking for deposit balance updates - Prevent race conditions in concurrent deposit requests - Add automatic retry with exponential backoff (max 3 attempts) - Add version column to user_deposits table - Improve type safety across codebase - Add explicit types for Namecheap API responses - Add typed function arguments (ManageDepositArgs, etc.) - Remove `any` types from deposit-agent and tool files - Add reconciliation job for balance integrity verification - Compare user_deposits.balance vs SUM(confirmed transactions) - Alert admin on discrepancy detection - Set up test environment with Vitest + Miniflare - Add 50+ test cases for deposit system - Add helper functions for test data creation - Update documentation - Add migration guide for version columns - Document optimistic locking patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
209
src/types.ts
209
src/types.ts
@@ -111,3 +111,212 @@ export interface BankNotification {
|
||||
transactionTime?: Date;
|
||||
rawMessage: string;
|
||||
}
|
||||
|
||||
// Namecheap API 응답 타입
|
||||
export interface NamecheapPriceResponse {
|
||||
tld: string;
|
||||
krw: number;
|
||||
usd?: number;
|
||||
register_krw?: number;
|
||||
renew_krw?: number;
|
||||
transfer_krw?: number;
|
||||
}
|
||||
|
||||
export interface NamecheapDomainInfo {
|
||||
name: string;
|
||||
created: string;
|
||||
expires: string;
|
||||
is_expired: boolean;
|
||||
auto_renew: boolean;
|
||||
is_locked: boolean;
|
||||
whois_guard: boolean;
|
||||
nameservers?: string[];
|
||||
}
|
||||
|
||||
export interface NamecheapCheckResult {
|
||||
[domain: string]: boolean;
|
||||
}
|
||||
|
||||
export interface NamecheapDomainListItem {
|
||||
name: string;
|
||||
created: string;
|
||||
expires: string;
|
||||
is_expired: boolean;
|
||||
auto_renew: boolean;
|
||||
is_locked: boolean;
|
||||
whois_guard: boolean;
|
||||
}
|
||||
|
||||
// Function Calling 인자 타입
|
||||
export interface ManageDomainArgs {
|
||||
action: 'register' | 'check' | 'whois' | 'list' | 'info' | 'get_ns' | 'set_ns' | 'price' | 'cheapest';
|
||||
domain?: string;
|
||||
nameservers?: string[];
|
||||
tld?: string;
|
||||
}
|
||||
|
||||
export interface ManageDepositArgs {
|
||||
action: 'balance' | 'account' | 'request' | 'history' | 'cancel' | 'pending' | 'confirm' | 'reject';
|
||||
depositor_name?: string;
|
||||
amount?: number;
|
||||
transaction_id?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface SuggestDomainsArgs {
|
||||
keywords: string;
|
||||
}
|
||||
|
||||
export interface SearchWebArgs {
|
||||
query: string;
|
||||
}
|
||||
|
||||
export interface LookupDocsArgs {
|
||||
library: string;
|
||||
query: string;
|
||||
}
|
||||
|
||||
// Deposit Agent 결과 타입
|
||||
export interface DepositBalanceResult {
|
||||
balance: number;
|
||||
formatted: string;
|
||||
}
|
||||
|
||||
export interface DepositAccountInfoResult {
|
||||
bank: string;
|
||||
account: string;
|
||||
holder: string;
|
||||
instruction: string;
|
||||
}
|
||||
|
||||
export interface DepositRequestResult {
|
||||
success: boolean;
|
||||
auto_matched: boolean;
|
||||
transaction_id: number;
|
||||
amount: number;
|
||||
depositor_name: string;
|
||||
status?: string;
|
||||
new_balance?: number;
|
||||
message: string;
|
||||
account_info?: {
|
||||
bank: string;
|
||||
account: string;
|
||||
holder: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DepositTransaction {
|
||||
id: number;
|
||||
type: string;
|
||||
amount: number;
|
||||
status: string;
|
||||
depositor_name: string;
|
||||
description: string | null;
|
||||
created_at: string;
|
||||
confirmed_at: string | null;
|
||||
}
|
||||
|
||||
export interface DepositTransactionsResult {
|
||||
transactions: DepositTransaction[];
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface DepositCancelResult {
|
||||
success: boolean;
|
||||
transaction_id: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface DepositPendingItem {
|
||||
id: number;
|
||||
amount: number;
|
||||
depositor_name: string;
|
||||
created_at: string;
|
||||
user: string;
|
||||
}
|
||||
|
||||
export interface DepositPendingResult {
|
||||
pending: DepositPendingItem[];
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface DepositConfirmResult {
|
||||
success: boolean;
|
||||
transaction_id: number;
|
||||
amount: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface DepositRejectResult {
|
||||
success: boolean;
|
||||
transaction_id: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface DepositErrorResult {
|
||||
error: string;
|
||||
}
|
||||
|
||||
export type DepositFunctionResult =
|
||||
| DepositBalanceResult
|
||||
| DepositAccountInfoResult
|
||||
| DepositRequestResult
|
||||
| DepositTransactionsResult
|
||||
| DepositCancelResult
|
||||
| DepositPendingResult
|
||||
| DepositConfirmResult
|
||||
| DepositRejectResult
|
||||
| DepositErrorResult;
|
||||
|
||||
// Brave Search API 응답 타입
|
||||
export interface BraveSearchResult {
|
||||
title: string;
|
||||
description: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface BraveSearchResponse {
|
||||
web?: {
|
||||
results: BraveSearchResult[];
|
||||
};
|
||||
}
|
||||
|
||||
// OpenAI API 응답 타입
|
||||
export interface OpenAIMessage {
|
||||
role: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface OpenAIChoice {
|
||||
message: OpenAIMessage;
|
||||
}
|
||||
|
||||
export interface OpenAIResponse {
|
||||
choices?: OpenAIChoice[];
|
||||
}
|
||||
|
||||
// Context7 API 응답 타입
|
||||
export interface Context7Library {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Context7SearchResponse {
|
||||
libraries?: Context7Library[];
|
||||
}
|
||||
|
||||
export interface Context7DocsResponse {
|
||||
context?: string;
|
||||
content?: string;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// Telegram Inline Keyboard 데이터
|
||||
export interface DomainRegisterKeyboardData {
|
||||
type: 'domain_register';
|
||||
domain: string;
|
||||
price: number;
|
||||
}
|
||||
|
||||
export type KeyboardData = DomainRegisterKeyboardData;
|
||||
|
||||
Reference in New Issue
Block a user