reflink-sdk
Version:
SDK for interacting with the Reflink Solana program via Anchor.
344 lines (343 loc) • 13.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReflinkSDK = void 0;
const anchor_1 = require("@coral-xyz/anchor");
const spl_token_1 = require("@solana/spl-token");
const web3_js_1 = require("@solana/web3.js");
const buffer_1 = require("buffer");
const reflink_json_1 = __importDefault(require("./reflink.json"));
class ReflinkSDK {
constructor(connection, wallet, // Wallet adapter that implements .signTransaction and .publicKey
programId // Optional program ID
) {
this.connection = connection;
this.wallet = wallet;
// Create a provider that will be used to interact with the Solana network
this.provider = new anchor_1.AnchorProvider(connection, wallet, anchor_1.AnchorProvider.defaultOptions());
// Update the IDL address if programId is provided
if (programId) {
reflink_json_1.default.address = programId;
}
// Create the program interface which will be used to invoke the program's instructions
this.program = new anchor_1.Program(reflink_json_1.default, this.provider);
}
/**
* Get the program instance
* @returns The Anchor program instance
*/
getProgram() {
return this.program;
}
/**
* Derive a PDA for an affiliate account
* @param authority The authority address (usually the affiliate's wallet)
* @returns [affiliate PDA, bump]
*/
async findAffiliatePDA(authority) {
return await web3_js_1.PublicKey.findProgramAddress([buffer_1.Buffer.from("affiliate"), authority.toBuffer()], this.program.programId);
}
/**
* Derive a PDA for a merchant account
* @param authority The authority address (usually the merchant's wallet)
* @returns [merchant PDA, bump]
*/
async findMerchantPDA(authority) {
return await web3_js_1.PublicKey.findProgramAddress([buffer_1.Buffer.from("merchant"), authority.toBuffer()], this.program.programId);
}
/**
* Register a new affiliate
* @returns Transaction signature
*/
async registerAffiliate() {
// Create a keypair for the affiliate account
const affiliateKeypair = anchor_1.web3.Keypair.generate();
try {
// Execute the transaction to register an affiliate
const tx = await this.program.methods
.registerAffiliate()
.accounts({
affiliate: affiliateKeypair.publicKey,
authority: this.wallet.publicKey,
})
.signers([affiliateKeypair])
.rpc();
console.log("Affiliate registered with tx:", tx);
console.log("Affiliate account:", affiliateKeypair.publicKey.toString());
return tx;
}
catch (error) {
console.error("Error registering affiliate:", error);
throw error;
}
}
/**
* Register a new merchant
* @param commissionBps The commission rate in basis points (100 = 1%)
* @returns Transaction signature
*/
async registerMerchant(commissionBps) {
// Validate commission rate
if (commissionBps > 10000) {
throw new Error("Commission rate cannot exceed 100% (10000 basis points)");
}
// Create a keypair for the merchant account
const merchantKeypair = anchor_1.web3.Keypair.generate();
try {
// Execute the transaction to register a merchant
const tx = await this.program.methods
.registerMerchant(commissionBps)
.accounts({
merchant: merchantKeypair.publicKey,
authority: this.wallet.publicKey,
})
.signers([merchantKeypair])
.rpc();
console.log("Merchant registered with tx:", tx);
console.log("Merchant account:", merchantKeypair.publicKey.toString());
return tx;
}
catch (error) {
console.error("Error registering merchant:", error);
throw error;
}
}
/**
* Process a referral payment in SOL
* @param merchantPubkey The merchant's account public key
* @param affiliatePubkey The affiliate's account public key
* @param merchantWallet The wallet to receive the merchant's portion
* @param affiliateWallet The wallet to receive the affiliate's commission
* @param amount The amount of SOL to send (in lamports)
* @returns Transaction signature
*/
async processReferralSol(merchantPubkey, affiliatePubkey, merchantWallet, affiliateWallet, amount) {
// Convert number to BN if needed
const paymentAmount = typeof amount === "number" ? new anchor_1.BN(amount) : amount;
// Create a keypair for the referral account
const referralKeypair = anchor_1.web3.Keypair.generate();
try {
// Execute the transaction
const tx = await this.program.methods
.registerReferralSol(paymentAmount)
.accounts({
affiliate: affiliatePubkey,
referral: referralKeypair.publicKey,
merchant: merchantPubkey,
merchantWallet: merchantWallet,
affiliateWallet: affiliateWallet,
payer: this.wallet.publicKey,
})
.signers([referralKeypair])
.rpc();
console.log("SOL referral processed with tx:", tx);
console.log("Referral account:", referralKeypair.publicKey.toString());
return tx;
}
catch (error) {
console.error("Error processing SOL referral:", error);
throw error;
}
}
/**
* Process a referral payment in SPL tokens
* @param merchantPubkey The merchant's account public key
* @param affiliatePubkey The affiliate's account public key
* @param merchantTokenAccount The merchant's token account
* @param affiliateTokenAccount The affiliate's token account
* @param tokenMint The mint address of the token
* @param amount The amount of tokens to send
* @returns Transaction signature
*/
async processReferralToken(merchantPubkey, affiliatePubkey, merchantTokenAccount, affiliateTokenAccount, tokenMint, amount) {
// Convert number to BN if needed
const paymentAmount = typeof amount === "number" ? new anchor_1.BN(amount) : amount;
// Create a keypair for the referral account
const referralKeypair = anchor_1.web3.Keypair.generate();
// Get the payer's token account for this mint
const payerTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMint, this.wallet.publicKey);
try {
// Execute the transaction
const tx = await this.program.methods
.registerReferralToken(paymentAmount)
.accounts({
affiliate: affiliatePubkey,
referral: referralKeypair.publicKey,
merchant: merchantPubkey,
tokenMint: tokenMint,
merchantTokenAccount: merchantTokenAccount,
affiliateTokenAccount: affiliateTokenAccount,
payerTokenAccount: payerTokenAccount,
payer: this.wallet.publicKey,
})
.signers([referralKeypair])
.rpc();
console.log("Token referral processed with tx:", tx);
console.log("Referral account:", referralKeypair.publicKey.toString());
return tx;
}
catch (error) {
console.error("Error processing token referral:", error);
throw error;
}
}
/**
* Update a merchant's commission rate
* @param merchantPubkey The merchant's account public key
* @param newCommissionBps The new commission rate in basis points
* @returns Transaction signature
*/
async updateMerchantCommission(merchantPubkey, newCommissionBps) {
// Validate commission rate
if (newCommissionBps > 10000) {
throw new Error("Commission rate cannot exceed 100% (10000 basis points)");
}
try {
// Execute the transaction
const tx = await this.program.methods
.updateMerchantCommission(newCommissionBps)
.accounts({
merchant: merchantPubkey,
authority: this.wallet.publicKey,
})
.rpc();
console.log("Merchant commission updated with tx:", tx);
return tx;
}
catch (error) {
console.error("Error updating merchant commission:", error);
throw error;
}
}
/**
* Toggle a merchant's active status
* @param merchantPubkey The merchant's account public key
* @returns Transaction signature
*/
async toggleMerchantStatus(merchantPubkey) {
try {
// Execute the transaction
const tx = await this.program.methods
.toggleMerchantStatus()
.accounts({
merchant: merchantPubkey,
authority: this.wallet.publicKey,
})
.rpc();
console.log("Merchant status toggled with tx:", tx);
return tx;
}
catch (error) {
console.error("Error toggling merchant status:", error);
throw error;
}
}
/**
* Get an affiliate's account data
* @param affiliatePubkey The affiliate's account public key
* @returns Affiliate account data
*/
async getAffiliateData(affiliatePubkey) {
try {
return await this.program.account.affiliate.fetch(affiliatePubkey);
}
catch (error) {
console.error("Error fetching affiliate data:", error);
throw error;
}
}
/**
* Get a merchant's account data
* @param merchantPubkey The merchant's account public key
* @returns Merchant account data
*/
async getMerchantData(merchantPubkey) {
try {
return await this.program.account.merchant.fetch(merchantPubkey);
}
catch (error) {
console.error("Error fetching merchant data:", error);
throw error;
}
}
/**
* Get a referral's account data
* @param referralPubkey The referral's account public key
* @returns Referral account data
*/
async getReferralData(referralPubkey) {
try {
return await this.program.account.referral.fetch(referralPubkey);
}
catch (error) {
console.error("Error fetching referral data:", error);
throw error;
}
}
/**
* Get all referrals for a specific affiliate
* @param affiliatePubkey The affiliate's account public key
* @returns Array of referral accounts
*/
async getAffiliateReferrals(affiliatePubkey) {
try {
const referrals = await this.program.account.referral.all([
{
memcmp: {
offset: 8, // Account discriminator is 8 bytes
bytes: affiliatePubkey.toBase58(),
},
},
]);
return referrals;
}
catch (error) {
console.error("Error getting affiliate referrals:", error);
throw error;
}
}
/**
* Get all referrals for a specific merchant
* @param merchantPubkey The merchant's account public key
* @returns Array of referral accounts
*/
async getMerchantReferrals(merchantPubkey) {
try {
const referrals = await this.program.account.referral.all([
{
memcmp: {
offset: 8 + 32, // Account discriminator + affiliate pubkey
bytes: merchantPubkey.toBase58(),
},
},
]);
return referrals;
}
catch (error) {
console.error("Error getting merchant referrals:", error);
throw error;
}
}
/**
* Utility function to convert SOL to lamports
* @param sol Amount in SOL
* @returns Amount in lamports
*/
solToLamports(sol) {
return new anchor_1.BN(sol * web3_js_1.LAMPORTS_PER_SOL);
}
/**
* Utility function to convert lamports to SOL
* @param lamports Amount in lamports
* @returns Amount in SOL
*/
lamportsToSol(lamports) {
const lamportsNumber = lamports instanceof anchor_1.BN ? lamports.toNumber() : lamports;
return lamportsNumber / web3_js_1.LAMPORTS_PER_SOL;
}
}
exports.ReflinkSDK = ReflinkSDK;
// Export types and SDK
exports.default = ReflinkSDK;