feat: add blockchain booking support#126
Conversation
- Add migration for blockchain fields (blockchain_booking_id, cancelled_at, etc.) - Implement blockchain booking operations (create, cancel, update status) - Add booking endpoints (cancel, availability check, user bookings) - Integrate blockchain services with proper error handling and rollback Signed-off-by: Pushkar Mishra <pushkarmishra029@gmail.com>
|
Warning Rate limit exceeded@pushkarm029 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 21 minutes and 12 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (6)
WalkthroughAdds blockchain-integrated booking flow: DB migration for blockchain/payment fields; new on-chain booking/cancel/status functions; revamped booking service with escrow, availability checks, rollback, and logging; expanded controller with standardized responses and new endpoints; routes updates; logging service signature change; new ConflictingBooking type. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant API as Backend API
participant Svc as BookingService
participant BC as BlockchainServices
participant SC as BookingContract
participant DB as Supabase
Client->>API: POST /bookings (propertyId, dates, totalAmount, guests)
API->>Svc: createBooking(request, userId)
Svc->>BC: checkAvailability({ propertyId, dates })
BC->>SC: simulate availability
SC-->>BC: { isAvailable }
BC-->>Svc: availability result
alt Available
Svc->>BC: createEscrow(propertyOwner, amount)
BC-->>Svc: { escrowId/txHash }
Svc->>SC: createBookingOnChain(...)
SC-->>Svc: { bookingId or txHash }
Svc->>DB: insert booking (with blockchain_booking_id, dates ISO)
alt DB write ok
Svc-->>API: { success, booking }
API-->>Client: 200 { success, data }
else DB write fails
Svc->>SC: cancelBookingOnChain(...)
Svc->>BC: cancelEscrow(...)
Svc-->>API: BookingError(DB_WRITE_FAILED)
API-->>Client: 500 error
end
else Not available
Svc-->>API: BookingError(NOT_AVAILABLE)
API-->>Client: 409 error
end
sequenceDiagram
autonumber
participant Client
participant API
participant Svc as BookingService
participant SC as BookingContract
participant DB as Supabase
Client->>API: PUT /bookings/:id/cancel
API->>Svc: cancelBooking(bookingId, userId)
Svc->>SC: cancelBookingOnChain(propertyId, bookingId, userId)
alt On-chain ok
Svc->>DB: update booking (status=cancelled, cancelled_at)
DB-->>Svc: updated
Svc-->>API: { success, message }
API-->>Client: 200 { success, data }
else On-chain fails
Svc-->>API: BookingError(ONCHAIN_CANCEL_FAILED)
API-->>Client: 502/500 error
end
sequenceDiagram
autonumber
participant Client
participant API
participant Svc as BookingService
participant SC as BookingContract
participant DB as Supabase
Client->>API: PUT /bookings/:id/status { status }
API->>Svc: updateBookingStatus(id, status, userId)
Svc->>SC: updateBookingStatusOnChain(...)
alt On-chain ok
Svc->>DB: set status
DB-->>Svc: updated booking
Svc-->>API: { success, booking }
API-->>Client: 200 { success, data }
else On-chain fails
Svc-->>API: BookingError(ONCHAIN_STATUS_UPDATE_FAILED)
API-->>Client: 502/500 error
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
apps/backend/src/services/logging.service.ts (3)
153-176: Buffer/Map/Set never reached in sanitizeValue; data loss riskThe generic object branch returns before Buffer/Map/Set handling, so Maps/Sets are logged as empty objects and Buffers lose metadata. Reorder checks and thread circular-state through calls.
Apply:
- private sanitizeValue(value: unknown): unknown { + private sanitizeValue(value: unknown, seen?: WeakSet<object>): unknown { try { // Handle primitive types if (value === null || value === undefined) { return value; } if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { return value; } // Handle Date objects if (value instanceof Date) { return value.toISOString(); } // Handle Error objects recursively if (value instanceof Error) { return this.serializeError(value); } // Handle arrays if (Array.isArray(value)) { - return value.map((item) => this.sanitizeValue(item)); + return value.map((item) => this.sanitizeValue(item, seen)); } + // Handle Buffer objects (common in Node.js) + if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + return { + type: 'Buffer', + length: value.length, + preview: value.toString('hex').substring(0, 100) + (value.length > 50 ? '...' : ''), + }; + } + + // Handle Map objects + if (value instanceof Map) { + return { + type: 'Map', + size: value.size, + entries: Array.from(value.entries()).map(([k, v]) => [ + this.sanitizeValue(k, seen), + this.sanitizeValue(v, seen), + ]), + }; + } + + // Handle Set objects + if (value instanceof Set) { + return { + type: 'Set', + size: value.size, + values: Array.from(value.values()).map((v) => this.sanitizeValue(v, seen)), + }; + } + // Handle plain objects if (value && typeof value === 'object') { - return this.sanitizeObject(value as Record<string, unknown>); + return this.sanitizeObject(value as Record<string, unknown>, seen); } - // Handle Buffer objects (common in Node.js) - if (Buffer.isBuffer(value)) { - return { - type: 'Buffer', - length: value.length, - preview: value.toString('hex').substring(0, 100) + (value.length > 50 ? '...' : ''), - }; - } - - // Handle Map objects - if (value instanceof Map) { - return { - type: 'Map', - size: value.size, - entries: Array.from(value.entries()).map(([k, v]) => [ - this.sanitizeValue(k), - this.sanitizeValue(v), - ]), - }; - } - - // Handle Set objects - if (value instanceof Set) { - return { - type: 'Set', - size: value.size, - values: Array.from(value.values()).map((v) => this.sanitizeValue(v)), - }; - } - // For other types, convert to string return String(value); } catch (e) { console.warn('Error sanitizing value:', e); return `[Unserializable: ${typeof value}]`; } }Also applies to: 177-206
118-141: Circular reference guard can throw; seen tracking not propagatedWeakSet.has is called on primitives (TypeError) and each recursive call creates a fresh WeakSet, failing to detect deep cycles. Guard objects first and pass a shared WeakSet through recursion.
Apply:
- private sanitizeObject(obj: Record<string, unknown>): Record<string, unknown> { - const sanitized: Record<string, unknown> = {}; - const seen = new WeakSet(); + private sanitizeObject( + obj: Record<string, unknown>, + seen: WeakSet<object> = new WeakSet<object>() + ): Record<string, unknown> { + const sanitized: Record<string, unknown> = {}; try { for (const [key, value] of Object.entries(obj)) { - if (seen.has(value as object)) { - sanitized[key] = '[Circular Reference]'; - continue; - } - - if (value && typeof value === 'object') { - seen.add(value as object); - } - - sanitized[key] = this.sanitizeValue(value); + if (value && typeof value === 'object') { + const objVal = value as object; + if (seen.has(objVal)) { + sanitized[key] = '[Circular Reference]'; + continue; + } + seen.add(objVal); + } + sanitized[key] = this.sanitizeValue(value, seen); } } catch (e) { console.warn('Error sanitizing object:', e); return { sanitizationError: 'Failed to sanitize object', originalKeys: Object.keys(obj) }; } return sanitized; }
31-41: Use sanitized details for message to avoid JSON.stringify throws and duplicationStringifying raw details can throw on cycles and duplicates work. Reuse sanitized value for both message and data.
private async logToDatabase(log: TransactionLog) { try { + const sanitizedDetails = this.sanitizeValue(log.details); await supabase.from('sync_logs').insert({ operation: log.operation, status: log.status, - message: log.details ? JSON.stringify(log.details) : null, - data: this.sanitizeValue(log.details), - error_details: this.serializeError(log.error), + message: sanitizedDetails ? JSON.stringify(sanitizedDetails) : null, + data: sanitizedDetails, + error_details: this.serializeError(log.error), created_at: log.timestamp, }); } catch (error) { console.error('Failed to log to database:', error); } }apps/backend/src/types/booking.types.ts (2)
59-66: Response schema date validation inverted; always fails valid datesUsing !Number(Date.parse(val)) treats valid dates as false and invalid as true. Also, status enum omits 'ongoing' causing 500s when such records appear.
dates: z.object({ - from: z.string().refine((val) => !Number(Date.parse(val)), { message: 'Invalid from date' }), - to: z.string().refine((val) => !Number(Date.parse(val)), { message: 'Invalid to date' }), + from: z.string().refine((val) => !Number.isNaN(Date.parse(val)), { message: 'Invalid from date' }), + to: z.string().refine((val) => !Number.isNaN(Date.parse(val)), { message: 'Invalid to date' }), }), guests: z.number(), total: z.number(), deposit: z.number(), - status: z.enum(['pending', 'confirmed', 'cancelled', 'completed']), + status: z.enum(['pending', 'confirmed', 'cancelled', 'completed', 'ongoing']),
14-15: Align escrowAddress nullability with DBDB column is nullable; interface should reflect that to prevent unsafe assumptions.
- escrowAddress: string; + escrowAddress: string | null;apps/backend/src/services/booking.service.ts (1)
104-107: Date serialization issue in database insertionThe dates are being stored as an object with ISO strings, but the database migration suggests these should be stored as timestamp columns. This could cause type mismatches or query issues.
Verify the database schema and adjust accordingly:
.insert({ property_id: input.propertyId, user_id: input.userId, - dates: { - from: input.dates.from.toISOString(), - to: input.dates.to.toISOString(), - }, + check_in_date: input.dates.from.toISOString(), + check_out_date: input.dates.to.toISOString(), guests: input.guests,#!/bin/bash # Check the actual bookings table schema to verify column names and types cat apps/backend/database/migrations/*.sql | grep -A 20 "CREATE TABLE.*bookings"
🧹 Nitpick comments (11)
apps/backend/src/services/logging.service.ts (1)
245-255: Normalize error shape in details via serializeErrorKeep error representation consistent and richer (name, cause, etc.). Avoid duplicating raw error structures.
public async logBlockchainError(log: TransactionLog, error: unknown) { const errorLog: TransactionLog = { ...log, status: 'failed', details: { ...(log.details as Record<string, unknown>), - error: error instanceof Error ? { message: error.message, stack: error.stack } : error, + error: this.serializeError(error), failedAt: new Date().toISOString(), }, error, }; await this.logTransaction(errorLog); }apps/backend/database/migrations/00002_add_booking_blockchain_fields.sql (2)
20-25: Consider unique (partial) index on blockchain_booking_idIf on-chain booking IDs are unique, enforce it to prevent duplicates while allowing NULLs.
-- Create index for blockchain booking ID lookups -CREATE INDEX IF NOT EXISTS bookings_blockchain_booking_id_idx ON public.bookings(blockchain_booking_id); +CREATE UNIQUE INDEX IF NOT EXISTS bookings_blockchain_booking_id_uidx + ON public.bookings(blockchain_booking_id) + WHERE blockchain_booking_id IS NOT NULL;
30-36: Schema update aligns with API, but add supporting index for frequent queriesUser bookings endpoint filters by user_id, optional status, and orders by created_at. Add a covering index.
CREATE INDEX IF NOT EXISTS bookings_user_status_created_idx ON public.bookings(user_id, status, created_at DESC);apps/backend/src/types/booking.types.ts (1)
72-74: Include sourcePublicKey in confirmPaymentSchema to match controller checksCatches errors earlier at validation middleware.
export const confirmPaymentSchema = z.object({ transactionHash: z.string().min(10, 'Transaction hash is required and must be valid'), + sourcePublicKey: z.string().min(20, 'Source public key is required'), });apps/backend/src/blockchain/bookingContract.ts (3)
100-106: Availability check “fail-open” may cause double-bookingReturning true on undefined results risks overbooking during RPC/schema changes. Prefer fail-closed or feature-flag this behavior.
- // Fail open: if result is undefined/null, assume available - if (available === undefined || available === null) { - return true; - } + // Fail closed to avoid double-booking on ambiguous results + if (available === undefined || available === null) { + return false; + }
154-163: Re-simulating after a successful send is wasteful and may divergeIf the chain returns a return value, prefer parsing it from sendTransaction’s response; otherwise simulate before sending once and cache. Not blocking.
214-222: Narrow newStatus to BookingStatusPrevents invalid on-chain status writes at compile-time.
-export async function updateBookingStatusOnChain( +export async function updateBookingStatusOnChain( propertyId: string, bookingId: string, - newStatus: string, + newStatus: 'pending' | 'confirmed' | 'cancelled' | 'completed' | 'ongoing', requestorId: string ): Promise<boolean> {apps/backend/src/services/booking.service.ts (1)
318-335: Remove unnecessary try-catch wrapper in checkAvailabilityThe
checkAvailabilityfunction inblockchainServiceshas redundant error handling that just re-wraps the error without adding value.async checkAvailability(request: { propertyId: string; dates: { from: Date; to: Date } }) { - try { // Use existing availability check utility const availabilityResult = await checkAvailability({ propertyId: request.propertyId, dates: request.dates, }); return availabilityResult; - } catch (error) { - console.error('Availability check failed:', error); - throw new BookingError( - 'Failed to check property availability', - 'AVAILABILITY_CHECK_FAIL', - error - ); - } },apps/backend/src/controllers/booking.controller.ts (3)
64-71: Extract common validation pattern into a helper functionThe parameter validation pattern is repeated multiple times across different endpoints. Consider extracting it into a reusable helper.
Create a validation helper:
function validateAndExtract<T>( schema: z.ZodSchema<T>, data: unknown, errorMessage: string ): { success: true; data: T } | { success: false; error: ApiResponse } { const result = schema.safeParse(data); if (!result.success) { return { success: false, error: formatErrorResponse(errorMessage, result.error.errors) }; } return { success: true, data: result.data }; }Then use it:
- const parseResult = BookingParamsSchema.safeParse(req.params); - if (!parseResult.success) { - return res - .status(400) - .json(formatErrorResponse('Invalid booking ID', parseResult.error.errors)); - } - - const { bookingId } = parseResult.data; + const validation = validateAndExtract(BookingParamsSchema, req.params, 'Invalid booking ID'); + if (!validation.success) { + return res.status(400).json(validation.error); + } + const { bookingId } = validation.data;
46-54: Consider adding rate limiting error codeThe error handling maps various error codes to HTTP statuses, but doesn't include rate limiting which might be important for blockchain operations.
Add rate limiting to the status map:
const statusMap: { [key: string]: number } = { UNAVAILABLE: 409, NOT_FOUND: 404, UNAUTHORIZED: 403, + RATE_LIMITED: 429, DB_FAIL: 500, ESCROW_FAIL: 500, BLOCKCHAIN_FAIL: 500, };
243-248: Missing property join in bookings queryThe query fetches bookings but doesn't join with property information, which might be needed for a complete booking list view.
Consider joining with properties table to get property details:
let query = supabase .from('bookings') - .select('*', { count: 'exact' }) + .select(` + *, + properties:property_id ( + title, + address, + city, + images + ) + `, { count: 'exact' }) .eq('user_id', userId)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
apps/backend/database/migrations/00002_add_booking_blockchain_fields.sql(1 hunks)apps/backend/src/blockchain/bookingContract.ts(1 hunks)apps/backend/src/controllers/booking.controller.ts(5 hunks)apps/backend/src/routes/booking.routes.ts(1 hunks)apps/backend/src/services/booking.service.ts(5 hunks)apps/backend/src/services/logging.service.ts(2 hunks)apps/backend/src/types/booking.types.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
apps/backend/src/controllers/booking.controller.ts (7)
apps/backend/src/types/shared.types.ts (1)
formatErrorResponse(43-47)apps/backend/src/types/common.types.ts (1)
BookingError(20-29)apps/backend/src/types/auth.types.ts (1)
AuthRequest(5-7)apps/backend/src/types/booking.types.ts (2)
BookingParamsSchema(51-53)BookingResponseSchema(55-70)apps/backend/src/services/booking.service.ts (4)
getBookingById(420-428)cancelBooking(154-241)bookingService(382-382)updateBookingStatus(243-313)apps/backend/src/config/supabase.ts (1)
supabase(205-217)apps/backend/src/blockchain/bookingContract.ts (1)
checkBookingAvailability(43-107)
apps/backend/src/routes/booking.routes.ts (3)
apps/backend/src/controllers/booking.controller.ts (6)
getBooking(62-103)cancelBooking(174-210)updateBookingStatus(319-366)getUserBookings(213-276)confirmPayment(105-171)checkPropertyAvailability(279-316)apps/backend/src/services/booking.service.ts (2)
cancelBooking(154-241)updateBookingStatus(243-313)apps/backend/src/validators/booking.validator.ts (1)
validateConfirmPayment(6-28)
apps/backend/src/services/logging.service.ts (1)
apps/backend/src/types/common.types.ts (1)
TransactionLog(31-37)
apps/backend/src/services/booking.service.ts (6)
apps/backend/src/types/booking.types.ts (2)
ConflictingBooking(76-82)Booking(6-18)apps/backend/src/blockchain/bookingContract.ts (3)
createBookingOnChain(109-173)cancelBookingOnChain(175-212)updateBookingStatusOnChain(214-259)apps/backend/src/types/common.types.ts (1)
BookingError(20-29)apps/backend/src/config/supabase.ts (1)
supabase(205-217)apps/backend/src/blockchain/trustlessWork.ts (4)
BookingEscrowParams(213-227)createEscrow(122-132)createEscrow(239-309)trustlessWorkClient(398-398)apps/backend/src/services/property.service.ts (1)
getPropertyById(294-385)
🔇 Additional comments (8)
apps/backend/src/services/logging.service.ts (1)
76-76: Cast tweak in serializeError is fineThe adjusted cast avoids TS index errors. No action needed.
apps/backend/database/migrations/00002_add_booking_blockchain_fields.sql (1)
26-29: escrow_address NULLability matches service logicGood change to handle partial/failed escrow flows.
apps/backend/src/types/booking.types.ts (1)
76-82: ConflictingBooking type addition looks goodMatches service usage and keeps dates strongly typed.
apps/backend/src/routes/booking.routes.ts (1)
25-31: Confirm-payment route grouping is fineMiddleware ordering is correct.
apps/backend/src/blockchain/bookingContract.ts (1)
13-41: Env and RPC init flow is solidClear errors on missing env and guarded by USE_MOCK.
apps/backend/src/services/booking.service.ts (1)
188-189: Verify booking ownership before blockchain cancellationThe current implementation checks ownership after fetching the booking but it would be more secure to validate ownership before any blockchain operations.
The authorization check is performed correctly before blockchain operations. The flow looks good.
apps/backend/src/controllers/booking.controller.ts (2)
329-330: No action needed: ‘ongoing’ status is already defined in the database migrations and BookingStatus type.
298-302: Resolved: date conversion correctly uses UTC timestamps
The controller’stoISOString()produces a UTC ISO string andcheckBookingAvailabilityparses it back into aDateand callsgetTime()/1000, so the availability check uses the intended UTC seconds since epoch.
| await this.blockchainServices.cancelEscrow(escrowAddress); | ||
| } catch (rollbackError) { | ||
| await loggingService.logBlockchainError(log, { | ||
| error: rollbackError, | ||
| context: 'Failed to rollback escrow after blockchain booking error', | ||
| originalError: blockchainError, | ||
| }); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Improve error context for escrow rollback failures
The error handling for escrow rollback could be enhanced to provide better debugging information and ensure proper error propagation.
} catch (rollbackError) {
await loggingService.logBlockchainError(log, {
error: rollbackError,
context: 'Failed to rollback escrow after blockchain booking error',
originalError: blockchainError,
+ escrowAddress,
+ propertyId: input.propertyId,
});
+ // Log but don't throw - the original error is more important
+ console.error('Escrow rollback failed:', rollbackError);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await this.blockchainServices.cancelEscrow(escrowAddress); | |
| } catch (rollbackError) { | |
| await loggingService.logBlockchainError(log, { | |
| error: rollbackError, | |
| context: 'Failed to rollback escrow after blockchain booking error', | |
| originalError: blockchainError, | |
| }); | |
| } | |
| await this.blockchainServices.cancelEscrow(escrowAddress); | |
| } catch (rollbackError) { | |
| await loggingService.logBlockchainError(log, { | |
| error: rollbackError, | |
| context: 'Failed to rollback escrow after blockchain booking error', | |
| originalError: blockchainError, | |
| escrowAddress, | |
| propertyId: input.propertyId, | |
| }); | |
| // Log but don't throw - the original error is more important | |
| console.error('Escrow rollback failed:', rollbackError); | |
| } |
🤖 Prompt for AI Agents
In apps/backend/src/services/booking.service.ts around lines 83 to 90, the
rollback catch currently logs only a generic message and the rollback error
which loses key context and may swallow the original blockchain error; update
the logBlockchainError call to include escrowAddress and bookingId (or other
booking identifiers available in scope) in the context payload and attach both
rollbackError and original blockchainError (e.g., originalError field already
present, ensure it is passed through) so logs show both failures and the escrow
address; after logging, rethrow a new Error or an aggregated error that
preserves both errors so the caller can handle the combined failure instead of
silently continuing.
| await updateBookingStatusOnChain( | ||
| booking.property_id, | ||
| booking.blockchain_booking_id, | ||
| newStatus, | ||
| requestorId | ||
| ); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Missing error handling for invalid status transitions
The updateBookingStatus function doesn't validate if the status transition is valid (e.g., can't go from 'cancelled' to 'confirmed').
Add status transition validation before the blockchain update:
if (fetchError || !booking) {
throw new BookingError('Booking not found', 'NOT_FOUND', fetchError);
}
+
+ // Define valid status transitions
+ const validTransitions: Record<string, string[]> = {
+ 'pending': ['confirmed', 'cancelled'],
+ 'confirmed': ['completed', 'cancelled'],
+ 'completed': [],
+ 'cancelled': [],
+ };
+
+ const currentStatus = booking.status;
+ if (!validTransitions[currentStatus]?.includes(newStatus)) {
+ throw new BookingError(
+ `Invalid status transition from ${currentStatus} to ${newStatus}`,
+ 'INVALID_STATUS_TRANSITION'
+ );
+ }
// Update status on blockchain if blockchain booking exists🤖 Prompt for AI Agents
In apps/backend/src/services/booking.service.ts around lines 269 to 274, the
code calls updateBookingStatusOnChain without validating the requested status
transition; add validation that compares booking.status (current) to newStatus
against an explicit allowed-transitions map (e.g., allowed[current] includes
next), and if the transition is invalid, throw a descriptive error or return a
failure before calling updateBookingStatusOnChain; ensure you log the invalid
attempt and avoid making the blockchain call when the transition is not
permitted.
…ices Signed-off-by: Pushkar Mishra <pushkarmishra029@gmail.com>
…NaN for better accuracy Signed-off-by: Pushkar Mishra <pushkarmishra029@gmail.com>
…s retrieval - Added a public route for property availability check - Moved user bookings retrieval route to a more appropriate position in the file Signed-off-by: Pushkar Mishra <pushkarmishra029@gmail.com>
…ue booking ID generation - Added validation for buyer and seller Stellar wallet addresses - Introduced unique booking ID generation for each booking Signed-off-by: Pushkar Mishra <pushkarmishra029@gmail.com>
|
@respp Please review |
LGTM |
Pull Request | StellarRent
📝 Summary
This PR implements complete blockchain integration for the booking system, enabling on-chain booking creation, cancellation, and status management with proper error handling and TypeScript type safety.
🔗 Related Issues
Closes #123
🔄 Changes Made
Implemented a comprehensive booking system that integrates with the existing BookingContract smart contract on Stellar blockchain. The system now supports dual storage (Supabase + blockchain) with proper rollback mechanisms, escrow integration via TrustlessWork API, and complete CRUD operations for bookings.
Key Features:
🖼️ Current Output
API Endpoints Working:
🧪 Testing
NA
✅ Testing Checklist
NA
🚀 Next Steps & Improvements
This change lays a solid foundation for further optimizations. Some areas that could benefit
from future improvements include:
💬 Comments
The implementation follows existing codebase patterns and conventions. All TypeScript errors have been resolved, and proper type definitions have been added throughout the booking system. The blockchain integration is production-ready with comprehensive error handling and logging.
Summary by CodeRabbit
New Features
Refactor