Manage rental agreements between two parties by capturing the agreement and rental payments on the Solana blockchain using a Solana Smart Contract (Program)
cargo build-bpf
Make sure your solana environment is pointing to devnet
solana config set --url https://api.devnet.solana.com
solana config get
solana program deploy ./target/deploy/rentshare.so
Debug messages are written to the solana logs with a [RentShare]
prefix so you can filter messages using:
solana logs | grep "\[RentShare\]"
The examples below show how to call the program with 2 instructions using the @solana/web3.js
library.
Using an externally created "Company" Account to fund the transactions (try Sollet), create a new rental agreement using a unique seed
and the program ID from the Rust BPF output:
const rentAgreementPublicKey = await PublicKey.createWithSeed(
rentCompanyAccountOwner.publicKey,
seed,
programId,
);
const lamports = await connection.getMinimumBalanceForRentExemption(
RENT_AGREEMENT_SCHEMA_SIZE, // Currently 90
);
const transaction = new Transaction().add(
SystemProgram.createAccountWithSeed({
fromPubkey: accountOwner.publicKey,
basePubkey: accountOwner.publicKey,
seed,
newAccountPubkey: rentAgreementPublicKey,
lamports,
space: RENT_AGREEMENT_SCHEMA_SIZE,
programId,
}),
);
await sendAndConfirmTransaction(connection, transaction, [accountOwner]);
Initialize the rent agreement account data using the rental terms - duration, rent amount, and deposit amount - by invoking the program with instruction 0
.
This will also record the payee (owner) and payer (renter) public keys to ensure future transactions are only between these two parties.
const instruction = 0;
const transactionInstruction = new TransactionInstruction({
keys: [
{ pubkey: rentAgreementPublicKey, isSigner: false, isWritable: true },
{ pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
],
programId,
data: Buffer.from(Uint8Array.of(instruction,
...Array.from(payeePublicKey.toBytes()),
...Array.from(payerPublicKey.toBytes()),
...new BN(deposit).toArray("le", 8),
...new BN(rentAmount).toArray("le", 8),
...new BN(duration).toArray("le", 8),
...new BN(durationUnit).toArray("le", 1),
))
})
await sendAndConfirmTransaction(
connection,
new Transaction().add(transactionInstruction),
[rentCompanyAccountOwner],
);
Transfer lamports from the payer (renter) to the payee (owner) for rent due using instruction 1
. This will decrement the remaining_payments
saved
in the rental agreement account data. They payer account must sign the transaction to tranfer funds to the payee.
const instruction = 1;
const transactionInstruction = new TransactionInstruction({
keys: [
{ pubkey: rentAgreementPublicKey, isSigner: false, isWritable: true },
{ pubkey: payeePrivateKey.publicKey, isSigner: false, isWritable: true },
{ pubkey: payerPrivateKey.publicKey, isSigner: true, isWritable: true },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: true },
],
programId,
data: Buffer.from(Uint8Array.of(instruction,
...new BN(rentAmount).toArray("le", 8),
))
})
await sendAndConfirmTransaction(
connection,
new Transaction().add(transactionInstruction),
[payerPrivateKey],
);