You are on Devnet — This is a test environment. Tokens have no real value.

Integration Guide

Learn how to integrate rFlow into your decentralized application using Anchor and the Solana Web3.js SDK.

Installation#

Install the required dependencies:

Terminal
$npm install @coral-xyz/anchor @solana/web3.js @solana/spl-token
Anchor Version
rFlow is built with Anchor 0.32.1. Make sure you use a compatible version.

Setup#

Initialize the Anchor program to interact with rFlow:

lib/rflow.ts
1import { AnchorProvider, Program, BN } from "@coral-xyz/anchor";
2import { Connection, PublicKey } from "@solana/web3.js";
3import { getAssociatedTokenAddress } from "@solana/spl-token";
4
5// Program ID (Devnet)
6export const PROGRAM_ID = new PublicKey(
7 "2yUwGR18L5a8UqfkX49M4SenYCrS4B48chioKWCnMG3y"
8);
9
10// Import the IDL (generated by Anchor)
11import type { Payflow } from "./idl/payflow";
12import idl from "./idl/payflow.json";
13
14// Initialize program
15export function getProgram(provider: AnchorProvider): Program<Payflow> {
16 return new Program(idl as Payflow, provider);
17}
18
19// Create provider with wallet
20export function createProvider(
21 connection: Connection,
22 wallet: AnchorWallet
23): AnchorProvider {
24 return new AnchorProvider(connection, wallet, {
25 commitment: "confirmed",
26 });
27}

PDA Helpers#

Helper functions to derive Program Derived Addresses:

lib/pda.ts
1import { PublicKey } from "@solana/web3.js";
2import { BN } from "@coral-xyz/anchor";
3
4const PROGRAM_ID = new PublicKey("2yUwGR18L5a8UqfkX49M4SenYCrS4B48chioKWCnMG3y");
5
6// Protocol Config PDA
7export function findProtocolConfigPDA(): [PublicKey, number] {
8 return PublicKey.findProgramAddressSync(
9 [Buffer.from("protocol_config")],
10 PROGRAM_ID
11 );
12}
13
14// Yield Deal PDA
15export function findYieldDealPDA(dealId: BN): [PublicKey, number] {
16 return PublicKey.findProgramAddressSync(
17 [Buffer.from("yield_deal"), dealId.toArrayLike(Buffer, "le", 8)],
18 PROGRAM_ID
19 );
20}
21
22// Vault PDA (holds locked tokens)
23export function findVaultPDA(dealPDA: PublicKey): [PublicKey, number] {
24 return PublicKey.findProgramAddressSync(
25 [Buffer.from("vault"), dealPDA.toBuffer()],
26 PROGRAM_ID
27 );
28}

Create a Deal#

Create a yield deal by locking receipt tokens:

services/create-deal.ts
1import { BN } from "@coral-xyz/anchor";
2import { PublicKey } from "@solana/web3.js";
3import { getAssociatedTokenAddress } from "@solana/spl-token";
4
5async function createDeal(
6 program: Program<Payflow>,
7 wallet: AnchorWallet,
8 params: {
9 receiptTokenMint: PublicKey;
10 paymentMint: PublicKey;
11 receiptTokensAmount: number; // UI amount (e.g., 1000)
12 principalValue: number; // UI amount in USDC
13 sellingPrice: number; // UI amount in USDC
14 durationDays: number;
15 sourceProtocol: string; // "kamino", "marinade", etc.
16 }
17) {
18 const [configPDA] = findProtocolConfigPDA();
19
20 // Fetch config to get next deal ID
21 const config = await program.account.protocolConfig.fetch(configPDA);
22 const dealId = new BN(config.dealCounter);
23
24 const [dealPDA] = findYieldDealPDA(dealId);
25 const [vaultPDA] = findVaultPDA(dealPDA);
26
27 // Get seller's token account
28 const sellerTokenAccount = await getAssociatedTokenAddress(
29 params.receiptTokenMint,
30 wallet.publicKey
31 );
32
33 // Convert to raw amounts (6 decimals for USDC)
34 const receiptTokensRaw = new BN(params.receiptTokensAmount * 1e6);
35 const principalRaw = new BN(params.principalValue * 1e6);
36 const sellingPriceRaw = new BN(params.sellingPrice * 1e6);
37 const expectedYield = new BN(
38 principalRaw.toNumber() * 0.05 * (params.durationDays / 365)
39 );
40
41 // Map source protocol string to enum
42 const sourceProtocolEnum = { [params.sourceProtocol]: {} };
43
44 const tx = await program.methods
45 .createDeal({
46 receiptTokensAmount: receiptTokensRaw,
47 principalValueAtLock: principalRaw,
48 expectedYield,
49 sellingPrice: sellingPriceRaw,
50 durationDays: params.durationDays,
51 sourceProtocol: sourceProtocolEnum,
52 })
53 .accounts({
54 seller: wallet.publicKey,
55 sellerTokenAccount,
56 receiptTokenMint: params.receiptTokenMint,
57 paymentMint: params.paymentMint,
58 })
59 .rpc();
60
61 console.log("Deal created!", { dealPDA: dealPDA.toBase58(), tx });
62 return { dealPDA, txSignature: tx };
63}

Buy a Deal#

Purchase an existing deal:

services/buy-deal.ts
1async function buyDeal(
2 program: Program<Payflow>,
3 wallet: AnchorWallet,
4 dealPDA: PublicKey,
5 treasuryAccount: PublicKey
6) {
7 const [configPDA] = findProtocolConfigPDA();
8
9 // Fetch deal to get payment mint and seller
10 const deal = await program.account.yieldDeal.fetch(dealPDA);
11
12 // Get buyer's payment token account (USDC)
13 const buyerPaymentAccount = await getAssociatedTokenAddress(
14 deal.paymentMint,
15 wallet.publicKey
16 );
17
18 // Get seller's payment token account
19 const sellerPaymentAccount = await getAssociatedTokenAddress(
20 deal.paymentMint,
21 deal.seller
22 );
23
24 const tx = await program.methods
25 .buyDeal()
26 .accounts({
27 buyer: wallet.publicKey,
28 deal: dealPDA,
29 buyerPaymentAccount,
30 sellerPaymentAccount,
31 treasuryAccount,
32 })
33 .rpc();
34
35 console.log("Deal purchased!", tx);
36 return tx;
37}
React Hook Example
Check out src/hooks/use-create-deal.ts and src/hooks/use-buy-deal.ts in the rFlow repo for complete React hook implementations with error handling and loading states.

Next Steps#