@wuwei-labs/srsly
Version:
TypeScript SDK for SRSLY
136 lines • 6.47 kB
JavaScript
"use strict";
/**
* @purpose Simplified closeRental instruction wrapper
*
* Thin convenience wrapper around Codama-generated closeRental instruction.
* Closes a completed rental and returns the fleet to the owner.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.closeRental = closeRental;
const kit_1 = require("@solana/kit");
const kit_2 = require("@solana/kit");
const instructions_1 = require("../generated/codama/instructions");
const config_1 = require("../utils/config");
const signer_1 = require("../utils/signer");
const config_2 = require("../accounts/config");
const contract_1 = require("../accounts/contract");
const fleet_1 = require("../accounts/fleet");
const rental_1 = require("../accounts/rental");
const sage_1 = require("../pda/sage");
const srsly_1 = require("../pda/srsly");
const thread_1 = require("../pda/thread");
const sage_2 = require("../pda/sage");
const token_1 = require("../pda/token");
const instructions_2 = require("../utils/instructions");
/**
* Finalize a completed rental and return the fleet to the owner.
*
* @param params - Rental closure parameters (payer, contract)
* @param config - Optional SDK configuration overrides
* @returns Kit instruction (or web3.js if PublicKey in config)
*
* @example
* ```typescript
* const ix = await closeRental({
* payer: ownerWallet,
* contract: contractAddress
* });
* ```
*/
async function closeRental(params, config) {
// Merge config
const finalConfig = (0, config_1.mergeConfig)(config);
// Validate required params
if (!params.payer) {
throw new Error('payer is required');
}
if (!params.contract) {
throw new Error('contract is required');
}
// Fetch config and contract
const configAccount = await (0, config_2.fetchConfig)(finalConfig.rpcUrl);
const atlasMint = configAccount.data.atlasMint;
const contractAccount = await (0, contract_1.fetchContract)(params.contract, finalConfig.rpcUrl);
const fleet = contractAccount.data.fleet;
const gameId = contractAccount.data.gameId;
// Check if contract has a queued rental waiting to activate
const SYSTEM_PROGRAM_ID = '11111111111111111111111111111111';
const hasQueuedRental = contractAccount.data.queuedRental !== SYSTEM_PROGRAM_ID;
let queuedRentalAddress;
let queuedBorrowerProfileAddress;
let queuedBorrowerProfileFactionAddress;
if (hasQueuedRental) {
queuedRentalAddress = await (0, srsly_1.deriveQueuedRental)(params.contract);
const queuedRentalState = await (0, rental_1.fetchRental)(queuedRentalAddress, finalConfig.rpcUrl);
queuedBorrowerProfileAddress = queuedRentalState.data.borrowerProfile;
queuedBorrowerProfileFactionAddress = await (0, sage_2.deriveProfileFaction)(queuedBorrowerProfileAddress);
}
// Thread accounts needed for inline activation restage
const hasThread = contractAccount.data.thread !== SYSTEM_PROGRAM_ID;
let contractThreadAddress;
let closeRentalFiberAddress;
if (hasQueuedRental && hasThread) {
const rentalAuthority = await (0, srsly_1.deriveRentalAuthority)();
contractThreadAddress = await (0, thread_1.deriveContractThread)(params.contract, rentalAuthority);
closeRentalFiberAddress = await (0, thread_1.deriveFiber)(contractThreadAddress, 1);
}
// Convert payer to transaction signer
const payerSigner = (0, signer_1.toTransactionSigner)(params.payer);
// Derive active rental PDA (no more slot logic)
const rentalState = await (0, srsly_1.deriveActiveRental)(params.contract);
// Fetch rental state for borrower, referrer
let borrower;
let referrer;
const rental = await (0, rental_1.fetchRental)(rentalState, finalConfig.rpcUrl);
borrower = params.borrower ? (0, kit_1.address)(params.borrower) : rental.data.borrower;
referrer = (0, kit_2.isOption)(rental.data.referrer)
? ((0, kit_2.unwrapOption)(rental.data.referrer) ?? undefined)
: undefined;
// Derive borrower state PDA
const borrowerState = await (0, srsly_1.deriveBorrowerState)(borrower);
// Fetch fleet to get faction and derive SAGE accounts
// During an active rental, fleet.subProfile IS the current borrower's profile
const fleetState = await (0, fleet_1.fetchFleet)(fleet, finalConfig.rpcUrl);
const borrowerProfile = fleetState.subProfile.key;
const faction = fleetState.faction;
// Derive SAGE game accounts using borrower's profile
const gameAccounts = await (0, sage_1.deriveGameAccounts)(borrowerProfile, faction, gameId);
// Get addresses
const addresses = (0, config_1.getAddresses)(config);
const sageProgram = (0, kit_1.address)(addresses.sage);
const programAddress = (0, kit_1.address)(addresses.srsly);
const contractAddress = (0, kit_1.address)(params.contract);
// Derive fee flush accounts
const vaultAddress = (0, kit_1.address)(configAccount.data.slyvault);
const vaultTokenAccount = await (0, token_1.deriveAssociatedTokenAccount)(vaultAddress, atlasMint);
const contractTokenAccount = await (0, token_1.deriveAssociatedTokenAccount)(contractAddress, atlasMint);
// Borrower's managed ATA for discount refund
const borrowerTokenAccount = await (0, token_1.deriveAssociatedTokenAccount)(borrowerState, atlasMint);
// Call Codama-generated instruction
const kitInstruction = await (0, instructions_1.getCloseRentalInstructionAsync)({
payer: payerSigner,
borrowerState,
contract: contractAddress,
rentalState,
fleet: (0, kit_1.address)(fleet),
gameId: (0, kit_1.address)(gameId),
starbase: gameAccounts.starbase,
starbasePlayer: gameAccounts.starbasePlayer,
contractTokenAccount,
vault: vaultAddress,
vaultTokenAccount,
referrer,
borrowerTokenAccount,
queuedRental: queuedRentalAddress ?? programAddress,
queuedBorrowerProfile: queuedBorrowerProfileAddress ?? programAddress,
queuedBorrowerProfileFaction: queuedBorrowerProfileFactionAddress ?? programAddress,
contractThread: contractThreadAddress,
closeRentalFiber: closeRentalFiberAddress,
sageProgram,
}, { programAddress });
return (0, instructions_2.prepareInstructions)(kitInstruction, {
computeUnits: params.computeUnits,
PublicKey: finalConfig.PublicKey,
});
}
//# sourceMappingURL=closeRental.js.map