Skip to main content

Core Modules 🏗️

DolphinPay's core functionality is implemented in two main modules: Payment and Merchant. These modules work together to provide a complete payment infrastructure.

Payment Module

The Payment module (payment.move) handles all payment-related operations from creation to completion.

Key Data Structures

Payment Object

struct Payment has key, store {
id: UID,
merchant: address, // Merchant receiving payment
payer: Option<address>, // Address that paid (if completed)
amount: u64, // Payment amount in smallest unit
currency: TypeName, // Currency type (e.g., SUI)
description: String, // Payment description
metadata: VecMap<String, String>, // Custom key-value data
status: u8, // Payment status (0-4)
expiry_timestamp: u64, // When payment expires
platform_fee: u64, // Platform fee amount
merchant_fee: u64, // Merchant fee amount
created_at: u64, // Creation timestamp
completed_at: Option<u64>, // Completion timestamp
}

Payment Status Values

  • 0 - PENDING: Payment created but not yet executed
  • 1 - COMPLETED: Payment successfully executed
  • 2 - CANCELLED: Payment cancelled by merchant
  • 3 - EXPIRED: Payment expired without execution
  • 4 - FAILED: Payment execution failed

Core Functions

Create Payment

public fun create_payment(
merchant: address,
amount: u64,
currency: TypeName,
description: String,
metadata: VecMap<String, String>,
expiry_seconds: u64,
ctx: &mut TxContext
): Payment

Creates a new payment request with the specified parameters.

Parameters:

  • merchant: Address that will receive the payment
  • amount: Payment amount (in smallest currency unit)
  • currency: Currency type name
  • description: Human-readable payment description
  • metadata: Additional key-value data
  • expiry_seconds: How long payment is valid for
  • ctx: Transaction context

Execute Payment

public fun execute_payment<T>(
payment: &mut Payment,
coin: Coin<T>,
ctx: &mut TxContext
)

Executes a pending payment by transferring the specified coin.

Requirements:

  • Payment must be in PENDING state
  • Payment must not be expired
  • Coin amount must be exactly equal to payment amount
  • Currency must match payment currency

Cancel Payment

public fun cancel_payment(
payment: &mut Payment,
merchant_cap: &MerchantCap,
ctx: &mut TxContext
)

Cancels a pending payment. Only the merchant can cancel their own payments.

Query Functions

public fun get_payment_status(payment: &Payment): u8
public fun get_payment_amount(payment: &Payment): u64
public fun get_payment_merchant(payment: &Payment): address
public fun is_payment_expired(payment: &Payment): bool

Fee Calculation

Fees are calculated automatically based on merchant configuration:

// Platform fee: 0.3% (30 basis points)
const PLATFORM_FEE_BPS: u64 = 30;

// Merchant fee: configurable (0-1000 basis points)
let merchant_fee_bps = get_merchant_fee_config(merchant);
let total_fee_bps = PLATFORM_FEE_BPS + merchant_fee_bps;

// Calculate fees
let platform_fee = (amount * PLATFORM_FEE_BPS) / BPS_DIVISOR;
let merchant_fee = (amount * merchant_fee_bps) / BPS_DIVISOR;
let net_amount = amount - platform_fee - merchant_fee;

Merchant Module

The Merchant module (merchant.move) manages merchant accounts and their configurations.

Key Data Structures

Merchant Object

struct Merchant has key, store {
id: UID,
owner: address, // Merchant owner address
name: String, // Business name
description: String, // Business description
receiving_addresses: VecMap<TypeName, address>, // Currency -> address mapping
fee_config: FeeConfig, // Fee configuration
supported_currencies: VecSet<TypeName>, // Supported currency types
settings: MerchantSettings, // Additional settings
status: u8, // Active/Inactive status
created_at: u64, // Registration timestamp
}

Fee Configuration

struct FeeConfig has store {
platform_fee_bps: u64, // Platform fee (fixed at 30)
custom_fee_bps: u64, // Merchant's custom fee (0-1000)
min_fee: u64, // Minimum fee amount
max_fee: u64, // Maximum fee amount
}

Core Functions

Register Merchant

public fun register_merchant(
name: String,
description: String,
ctx: &mut TxContext
): (Merchant, MerchantCap)

Registers a new merchant and returns the merchant object and capability.

Returns:

  • Merchant: Merchant object (stored at merchant address)
  • MerchantCap: Capability object allowing merchant operations

Configure Fees

public fun configure_merchant_fees(
merchant: &mut Merchant,
merchant_cap: &MerchantCap,
custom_fee_bps: u64,
min_fee: u64,
max_fee: u64,
ctx: &mut TxContext
)

Configures the merchant's custom fee structure.

Parameters:

  • custom_fee_bps: Custom fee in basis points (0-1000 = 0-10%)
  • min_fee: Minimum fee amount in smallest currency unit
  • max_fee: Maximum fee amount in smallest currency unit

Add Currency Support

public fun add_supported_currency<T>(
merchant: &mut Merchant,
merchant_cap: &MerchantCap,
receiving_address: address,
ctx: &mut TxContext
)

Adds support for a new currency with the specified receiving address.

Set Receiving Address

public fun set_receiving_address<T>(
merchant: &mut Merchant,
merchant_cap: &MerchantCap,
currency: TypeName,
address: address,
ctx: &mut TxContext
)

Updates the receiving address for a specific currency.

Merchant Capabilities

The MerchantCap object is crucial for security:

struct MerchantCap has key {
id: UID,
merchant_id: ID, // Links to specific merchant
permissions: u64, // Permission bitmask
}

Permission Types:

  • REGISTER_MERCHANT: Register new merchants
  • CONFIGURE_FEES: Modify fee settings
  • ADD_CURRENCY: Add new currency support
  • SET_ADDRESSES: Update receiving addresses
  • CANCEL_PAYMENTS: Cancel merchant's payments

Events

Both modules emit comprehensive events for all operations:

Payment Events

struct PaymentCreated has copy, drop {
payment_id: ID,
merchant: address,
amount: u64,
currency: TypeName,
description: String,
expiry_timestamp: u64,
}

struct PaymentCompleted has copy, drop {
payment_id: ID,
payer: address,
amount: u64,
net_amount: u64,
platform_fee: u64,
merchant_fee: u64,
tx_hash: vector<u8>,
}

Merchant Events

struct MerchantRegistered has copy, drop {
merchant_id: ID,
owner: address,
name: String,
}

struct MerchantFeesUpdated has copy, drop {
merchant_id: ID,
custom_fee_bps: u64,
min_fee: u64,
max_fee: u64,
}

Integration Example

Here's how the modules work together:

// 1. Register merchant
let (merchant, merchant_cap) = merchant::register_merchant(
"My Store",
"E-commerce platform",
ctx
);

// 2. Configure merchant
merchant::configure_merchant_fees(
&mut merchant,
&merchant_cap,
50, // 0.5% custom fee
1000000, // 0.001 SUI min fee
1000000000, // 1 SUI max fee
ctx
);

// 3. Add currency support
merchant::add_supported_currency<SUI>(
&mut merchant,
&merchant_cap,
merchant_address, // Receiving address
ctx
);

// 4. Create payment
let payment = payment::create_payment(
merchant_address,
10000000000, // 10 SUI
sui::SUI,
"Order #12345",
metadata,
3600, // 1 hour expiry
ctx
);

// 5. Execute payment (by customer)
payment::execute_payment(
&mut payment,
coin, // Customer's coin
ctx
);

Security Features

Input Validation

  • Amount Validation: Enforces minimum (0.0001 SUI) and maximum (1000 SUI) amounts
  • Address Validation: Checks for zero addresses and malformed addresses
  • String Validation: Enforces length limits on descriptions and metadata
  • Time Validation: Ensures expiry times are reasonable (1 hour to 1 week)

Access Control

  • Capability System: Uses Sui's object capability model for secure access
  • Owner Verification: Merchants can only modify their own configurations
  • Admin Controls: Separate admin capabilities for platform management

Overflow Protection

  • Safe Arithmetic: All calculations use checked operations
  • u128 Usage: Fee calculations use u128 to prevent overflow
  • Percentage Bounds: Fee percentages are strictly bounded (0-10%)

Testing

Unit Tests

# Run payment module tests
sui move test payment_tests

# Run merchant module tests
sui move test merchant_tests

# Run all tests
sui move test

Test Coverage

  • ✅ Payment creation and validation
  • ✅ Payment execution with various amounts
  • ✅ Payment cancellation by merchants
  • ✅ Merchant registration and configuration
  • ✅ Fee calculation accuracy
  • ✅ Event emission verification
  • ✅ Error condition handling
  • ✅ Access control enforcement

Gas Optimization

Efficient Patterns

  • Object Reuse: Minimize creation of new objects
  • Batch Operations: Combine operations where possible
  • Event Optimization: Structured events for minimal gas usage
  • Validation Ordering: Fail fast on invalid inputs

Typical Gas Costs (Testnet)

OperationGas CostDescription
Create Payment~0.01 SUIStandard payment creation
Execute Payment~0.015 SUIPayment completion
Register Merchant~0.015 SUINew merchant setup
Configure Fees~0.01 SUIUpdate fee settings
Cancel Payment~0.008 SUIPayment cancellation

Next Steps


Ready to build? Check out the SDK documentation to start integrating with these modules!