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";45// Program ID (Devnet)6export const PROGRAM_ID = new PublicKey(7 "2yUwGR18L5a8UqfkX49M4SenYCrS4B48chioKWCnMG3y"8);910// Import the IDL (generated by Anchor)11import type { Payflow } from "./idl/payflow";12import idl from "./idl/payflow.json";1314// Initialize program15export function getProgram(provider: AnchorProvider): Program<Payflow> {16 return new Program(idl as Payflow, provider);17}1819// Create provider with wallet20export function createProvider(21 connection: Connection,22 wallet: AnchorWallet23): 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";34const PROGRAM_ID = new PublicKey("2yUwGR18L5a8UqfkX49M4SenYCrS4B48chioKWCnMG3y");56// Protocol Config PDA7export function findProtocolConfigPDA(): [PublicKey, number] {8 return PublicKey.findProgramAddressSync(9 [Buffer.from("protocol_config")],10 PROGRAM_ID11 );12}1314// Yield Deal PDA15export function findYieldDealPDA(dealId: BN): [PublicKey, number] {16 return PublicKey.findProgramAddressSync(17 [Buffer.from("yield_deal"), dealId.toArrayLike(Buffer, "le", 8)],18 PROGRAM_ID19 );20}2122// Vault PDA (holds locked tokens)23export function findVaultPDA(dealPDA: PublicKey): [PublicKey, number] {24 return PublicKey.findProgramAddressSync(25 [Buffer.from("vault"), dealPDA.toBuffer()],26 PROGRAM_ID27 );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";45async 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 USDC13 sellingPrice: number; // UI amount in USDC14 durationDays: number;15 sourceProtocol: string; // "kamino", "marinade", etc.16 }17) {18 const [configPDA] = findProtocolConfigPDA();1920 // Fetch config to get next deal ID21 const config = await program.account.protocolConfig.fetch(configPDA);22 const dealId = new BN(config.dealCounter);2324 const [dealPDA] = findYieldDealPDA(dealId);25 const [vaultPDA] = findVaultPDA(dealPDA);2627 // Get seller's token account28 const sellerTokenAccount = await getAssociatedTokenAddress(29 params.receiptTokenMint,30 wallet.publicKey31 );3233 // 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 );4041 // Map source protocol string to enum42 const sourceProtocolEnum = { [params.sourceProtocol]: {} };4344 const tx = await program.methods45 .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();6061 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: PublicKey6) {7 const [configPDA] = findProtocolConfigPDA();89 // Fetch deal to get payment mint and seller10 const deal = await program.account.yieldDeal.fetch(dealPDA);1112 // Get buyer's payment token account (USDC)13 const buyerPaymentAccount = await getAssociatedTokenAddress(14 deal.paymentMint,15 wallet.publicKey16 );1718 // Get seller's payment token account19 const sellerPaymentAccount = await getAssociatedTokenAddress(20 deal.paymentMint,21 deal.seller22 );2324 const tx = await program.methods25 .buyDeal()26 .accounts({27 buyer: wallet.publicKey,28 deal: dealPDA,29 buyerPaymentAccount,30 sellerPaymentAccount,31 treasuryAccount,32 })33 .rpc();3435 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.