Managing Payment in APT

Users Pays Contract

Both Solana and Aptos use signer to authorize transactions. By having access to the signer, we can send SOL from signer's account to any designated account. Here's how we transfer SOL from buyer's account to vault account. Vault account holds all SOL from users who bought keys.


use crate::state::{Config, Holding, Issuer};
use anchor_lang::{prelude::*, solana_program::native_token::LAMPORTS_PER_SOL};
#[derive(Accounts, Clone)]
pub struct TransactHoldings<'info> {
/// CHECK vault
#[account(mut, seeds = [b"vault"], bump)]
pub vault: AccountInfo<'info>,
#[account(mut)]
pub signer: Signer<'info>,
// ... other accounts
}
pub fn handle_buy_key(ctx: Context<TransactHoldings>, amount: u64) -> Result<()> {
// ... other stuff
let ix = anchor_lang::solana_program::system_instruction::transfer(
&ctx.accounts.signer.key(),
&ctx.accounts.vault.key(),
price,
);
anchor_lang::solana_program::program::invoke(
&ix,
&[
ctx.accounts.signer.to_account_info(),
ctx.accounts.vault.to_account_info(),
],
)?;
// ... other stuff
}

On Aptos, it's very similar.


module friend_tech_addr::friend_tech {
use aptos_framework::aptos_account;
public entry fun buy_key(
sender: &signer,
issuer_addr: address,
amount: u64,
) acquires Issuer, Holding, User {
// ... other stuff
aptos_account::transfer(sender, get_vault_addr(), price);
// ... other stuff
}
}

Contract Pays Users

When a user sells the key, we need to send the funds from the vault to the seller. On Solana, we use the PDA signer to send funds from PDA.


use crate::state::{Config, Holding, Issuer};
use anchor_lang::{prelude::*, solana_program::native_token::LAMPORTS_PER_SOL};
pub fn handle_sell_key(ctx: Context<TransactHoldings>, k: u64) -> Result<()> {
// ... other stuff
let cpi_accounts = anchor_lang::system_program::Transfer {
from: ctx.accounts.vault.to_account_info(),
to: ctx.accounts.signer.to_account_info(),
};
let signature_seeds = [b"vault".as_ref(), &[vault_bump]];
let signers = &[&signature_seeds[..]];
let cpi_context = CpiContext::new_with_signer(cpi_program, cpi_accounts, signers);
anchor_lang::system_program::transfer(cpi_context, price)?;
// ... other stuff
}

On Aptos we use the Object signer to send funds from the Object.


module friend_tech_addr::friend_tech {
use aptos_framework::aptos_account;
struct Vault has key {
extend_ref: object::ExtendRef,
}
public entry fun buy_key(
sender: &signer,
issuer_addr: address,
amount: u64,
) acquires Issuer, Holding, User {
// ... other stuff
aptos_account::transfer(&get_vault_signer(), sender_addr, key_cost);
// ... other stuff
}
fun get_vault_signer(): signer acquires Vault {
let vault = borrow_global<Vault>(get_vault_addr());
object::generate_signer_for_extending(&vault.extend_ref)
}
}