@wuwei-labs/srsly
Version:
TypeScript SDK for SRSLY
123 lines • 5.31 kB
JavaScript
;
/**
* @purpose SOL + ATLAS cost estimators for SRSLY protocol usage.
*
* Three quotes:
* - Owner setup (contract_create + contract_thread) — recoverable rents + infra + exec budget.
* - Borrower setup (borrower_create) — BorrowerState + managed ATA.
* - Per-rental (rental_accept) — SOL tx fee + ATLAS escrow + service fee.
*
* All functions use `rpc.getMinimumBalanceForRentExemption` so quotes reflect the
* target cluster's rent rate rather than hardcoded lamports.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.estimateOwnerSetupCost = estimateOwnerSetupCost;
exports.estimateBorrowerSetupCost = estimateBorrowerSetupCost;
exports.estimateRentalCost = estimateRentalCost;
exports.tickBudget = tickBudget;
const contract_1 = require("../accounts/contract");
const config_1 = require("../accounts/config");
const config_2 = require("../utils/config");
const rpc_1 = require("../utils/rpc");
const sol_1 = require("../params/sol");
const sizes_1 = require("./sizes");
const constants_1 = require("./constants");
async function minBalance(rpcUrl, size) {
const rpc = (0, rpc_1.createRpc)(rpcUrl ?? (0, config_2.getRpcUrl)());
const response = await rpc.getMinimumBalanceForRentExemption(BigInt(size)).send();
return BigInt(response);
}
async function estimateOwnerSetupCost(opts = {}) {
const executionBudget = opts.executionBudget === undefined
? constants_1.DEFAULT_EXECUTION_BUDGET
: (0, sol_1.convertSol)(opts.executionBudget);
const [contractState, rentalState, ataRent] = await Promise.all([
minBalance(opts.rpcUrl, sizes_1.CONTRACT_STATE_SIZE),
minBalance(opts.rpcUrl, sizes_1.RENTAL_STATE_SIZE),
minBalance(opts.rpcUrl, constants_1.SPL_ATA_SIZE),
]);
const ownerAta = opts.ownerAtaExists ? 0n : ataRent;
const rentLamports = contractState + rentalState + rentalState + ataRent + ownerAta;
const threadLamports = constants_1.MINIMUM_THREAD_FUNDING + executionBudget;
const txFees = constants_1.TX_BASE_FEE_LAMPORTS * 2n; // contract_create + contract_thread
return {
rentLamports,
threadLamports,
txFees,
total: rentLamports + threadLamports + txFees,
breakdown: {
contractState,
rentalStateActive: rentalState,
rentalStateQueued: rentalState,
contractAta: ataRent,
ownerAta,
threadInfraBase: constants_1.MINIMUM_THREAD_FUNDING,
executionBudget,
},
};
}
async function estimateBorrowerSetupCost(rpcUrl) {
const [borrowerState, managedAta] = await Promise.all([
minBalance(rpcUrl, sizes_1.BORROWER_STATE_SIZE),
minBalance(rpcUrl, constants_1.SPL_ATA_SIZE),
]);
const rentLamports = borrowerState + managedAta;
const txFees = constants_1.TX_BASE_FEE_LAMPORTS;
return {
rentLamports,
txFees,
total: rentLamports + txFees,
breakdown: { borrowerState, managedAta },
};
}
/**
* Quote the ATLAS cost a borrower will pay for a given rate + duration.
* Pure helper — does not build a transaction.
*/
async function estimateRentalCost(params) {
const [{ data: contract }, { data: config }] = await Promise.all([
(0, contract_1.fetchContract)(params.contract, params.rpcUrl),
(0, config_1.fetchConfig)(params.rpcUrl),
]);
const duration = BigInt(params.durationSeconds);
const stardustToAtlas = BigInt(config.stardustToAtlas);
const rate = BigInt(contract.rate);
// Mirror on-chain scaling: rate <1 ATLAS is treated as ATLAS-denominated.
const rateStardust = rate < stardustToAtlas ? saturatingMul(rate, stardustToAtlas) : rate;
const atlasEscrow = saturatingDiv(saturatingMul(rateStardust, duration), constants_1.SECONDS_PER_DAY);
const feeBps = BigInt(config.serviceFeeBps);
const baseBps = BigInt(config.baseBps);
const atlasServiceFee = baseBps === 0n ? 0n : saturatingDiv(saturatingMul(atlasEscrow, feeBps), baseBps);
const atlasBid = params.bidStardust ?? 0n;
return {
solTxFees: constants_1.TX_BASE_FEE_LAMPORTS,
atlasEscrow,
atlasServiceFee,
atlasBid,
atlasTotal: atlasEscrow + atlasBid,
serviceFeeBps: Number(feeBps),
};
}
/* -------------------------------------------------------------------------- */
/* Thread burn */
/* -------------------------------------------------------------------------- */
/**
* Lamports burned by a given number of cron ticks at `PER_TICK_LAMPORTS` each.
* Useful for sizing a custom `executionBudget` before calling
* `estimateOwnerSetupCost`.
*/
function tickBudget(ticks) {
return BigInt(ticks) * constants_1.PER_TICK_LAMPORTS;
}
/* -------------------------------------------------------------------------- */
/* u64 helpers */
/* -------------------------------------------------------------------------- */
const MAX_U64 = 18446744073709551615n;
function saturatingMul(a, b) {
const product = a * b;
return product > MAX_U64 ? MAX_U64 : product;
}
function saturatingDiv(a, b) {
return b === 0n ? 0n : a / b;
}
//# sourceMappingURL=estimate.js.map