import { it, describe, } from 'mocha' import { Connection, Keypair, PublicKey, sendAndConfirmTransaction, SystemProgram, Transaction, } from '@solana/web3.js' import { AddCarArgs, Car, RentalOrder, RentalOrderStatus, createAddCarInstruction, createBookRentalInstruction, createPickUpCarInstruction, createReturnCarInstruction, } from './generated' function loadKeypairFromFile(path: string): Keypair { return Keypair.fromSecretKey( Buffer.from(JSON.parse(require('fs').readFileSync(path, "utf-8"))) ) } const carBmw: AddCarArgs = { year: 2020, make: 'BMW', model: 'iX1', } const carMercedes: AddCarArgs = { year: 2019, make: 'Mercedes-Benz', model: 'EQS', } const rentalInfo = { name: "Fred Flinstone", pickUpDate: "01/28/2023 8:00 AM", returnDate: "01/28/2023 10:00 PM", price: 300, } describe("Car Rental Service", () => { const connection = new Connection(`https://api.devnet.solana.com`, 'confirmed') const payer = loadKeypairFromFile(require('os').homedir() + '/.config/solana/id.json') const program = loadKeypairFromFile('./program/target/deploy/car_rental_service-keypair.json') let bmwPublicKey: PublicKey let mercedesPublicKey: PublicKey async function createCar(car: AddCarArgs): Promise { const carAccountPublicKey = PublicKey.findProgramAddressSync( [ Buffer.from('car'), Buffer.from(car.make), Buffer.from(car.model), ], program.publicKey, )[0] const ix = createAddCarInstruction( { carAccount: carAccountPublicKey, payer: payer.publicKey, systemProgram: SystemProgram.programId, }, { addCarArgs: { ...car } }, ) const sx = await sendAndConfirmTransaction( connection, new Transaction().add(ix), [payer], { skipPreflight: true } ) await connection.confirmTransaction(sx) const carData = await Car.fromAccountAddress(connection, carAccountPublicKey) console.log('New car created:') console.log(` Year : ${carData.year}`) console.log(` Make : ${carData.make}`) console.log(` Model : ${carData.model}`) return carAccountPublicKey } it("Create a car that can be rented", async () => { bmwPublicKey = await createCar(carBmw) }) it("Create another car that can be rented", async () => { mercedesPublicKey = await createCar(carMercedes) }) const evaluateStatus = (status: RentalOrderStatus): string => { if (status === RentalOrderStatus.Created) return "Created" if (status === RentalOrderStatus.PickedUp) return "Picked Up" return "Returned" } async function printRentalDetails(rentalPublicKey: PublicKey, carPublicKey: PublicKey) { const rentalData = await RentalOrder.fromAccountAddress(connection, rentalPublicKey) const carData = await Car.fromAccountAddress(connection, carPublicKey) console.log('Rental booked:') console.log(' Vehicle details:') console.log(` Year : ${carData.year}`) console.log(` Make : ${carData.make}`) console.log(` Model : ${carData.model}`) console.log(` Name : ${rentalData.name}`) console.log(` Pick Up : ${rentalData.pickUpDate}`) console.log(` Return : ${rentalData.returnDate}`) console.log(` Price : ${rentalData.price}`) console.log(` Status : ${evaluateStatus(rentalData.status)}`) } it("Book a new rental", async () => { const rentalAccountPublicKey = PublicKey.findProgramAddressSync( [ Buffer.from('rental_order'), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer(), ], program.publicKey, )[0] const ix = createBookRentalInstruction( { rentalAccount: rentalAccountPublicKey, carAccount: bmwPublicKey, payer: payer.publicKey, systemProgram: SystemProgram.programId, }, { bookRentalArgs: { ...rentalInfo } }, ) const sx = await sendAndConfirmTransaction( connection, new Transaction().add(ix), [payer] ) await connection.confirmTransaction(sx) await printRentalDetails(rentalAccountPublicKey, bmwPublicKey) }) it("Pick up your rental car", async () => { const rentalAccountPublicKey = PublicKey.findProgramAddressSync( [ Buffer.from('rental_order'), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer(), ], program.publicKey, )[0] const ix = createPickUpCarInstruction( { rentalAccount: rentalAccountPublicKey, carAccount: bmwPublicKey, payer: payer.publicKey, } ) const sx = await sendAndConfirmTransaction( connection, new Transaction().add(ix), [payer] ) await connection.confirmTransaction(sx) await printRentalDetails(rentalAccountPublicKey, bmwPublicKey) }) it("Return your rental car", async () => { const rentalAccountPublicKey = PublicKey.findProgramAddressSync( [ Buffer.from('rental_order'), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer(), ], program.publicKey, )[0] const ix = createReturnCarInstruction( { rentalAccount: rentalAccountPublicKey, carAccount: bmwPublicKey, payer: payer.publicKey, } ) const sx = await sendAndConfirmTransaction( connection, new Transaction().add(ix), [payer] ) await connection.confirmTransaction(sx) await printRentalDetails(rentalAccountPublicKey, bmwPublicKey) }) })