Merchant Module API Reference
Complete API documentation for the dolphinpay::merchant module.
Overview
The Merchant module (merchant.move) handles merchant account management:
- Merchant registration and onboarding
- Multi-currency support configuration
- Receiving address management
- Fee configuration (admin-controlled)
- Status management (active/inactive)
Package Location: dolphinpay::merchant
Data Structures
Merchant
Main merchant account object.
public struct Merchant has key, store {
id: UID,
owner: address,
name: String,
description: String,
receiving_addresses: VecMap<TypeName, address>,
fee_config: FeeConfig,
settings: MerchantSettings,
created_at: u64,
is_active: bool,
supported_currencies: VecSet<TypeName>,
}
Fields:
id- Unique object identifierowner- Owner's address (receives MerchantCap)name- Merchant name (1-100 characters)description- Merchant description (max 500 characters)receiving_addresses- Map of currency type to receiving addressfee_config- Fee configuration (admin-controlled)settings- Merchant settings (webhooks, auto-settlement, etc.)created_at- Registration timestamp (milliseconds)is_active- Whether merchant is activesupported_currencies- Set of supported currency types
MerchantCap
Capability object proving merchant ownership.
public struct MerchantCap has key {
id: UID,
merchant_id: ID,
}
Fields:
id- Unique object identifiermerchant_id- ID of the owned merchant
FeeConfig
Fee configuration (admin-controlled).
public struct FeeConfig has store, copy, drop {
platform_fee_bps: u64, // Platform fee in basis points
}
MerchantSettings
Merchant configuration settings.
public struct MerchantSettings has store {
auto_settlement: bool,
settlement_threshold: u64,
webhook_url: String,
api_keys: vector<String>,
require_confirmation: bool,
default_refund_policy: RefundPolicy,
}
RefundPolicy
Refund policy configuration.
public struct RefundPolicy has store, copy, drop {
enabled: bool,
window_days: u64,
require_approval: bool,
auto_approve_threshold: u64,
}
Constants
Limits
const DEFAULT_PLATFORM_FEE_BPS: u64 = 30; // 0.3% default platform fee
const MAX_NAME_LENGTH: u64 = 100; // Max merchant name length
const MAX_DESCRIPTION_LENGTH: u64 = 500; // Max description length
Error Codes
const E_NOT_AUTHORIZED: u64 = 1;
const E_INVALID_FEE: u64 = 200;
const E_MERCHANT_NOT_FOUND: u64 = 201;
const E_MERCHANT_INACTIVE: u64 = 202;
const E_INVALID_NAME: u64 = 203;
const E_FEE_TOO_HIGH: u64 = 204;
const E_CURRENCY_ALREADY_SUPPORTED: u64 = 205;
const E_CURRENCY_NOT_SUPPORTED: u64 = 206;
const E_INVALID_ADDRESS: u64 = 207;
Public Functions
register_merchant
Registers a new merchant account.
public entry fun register_merchant(
name: String,
description: String,
ctx: &mut TxContext
)
Parameters:
name- Merchant name (1-100 characters)description- Merchant description (max 500 characters)ctx- Transaction context
Effects:
- Creates and shares a Merchant object
- Creates and transfers MerchantCap to sender
- Merchant starts in active state
- Default fee configuration applied
Emits:
MerchantRegisteredevent
Errors:
E_INVALID_NAME- Name is empty, too long, or description too long
Example Usage:
// Using SDK
const txb = client.merchant.buildRegisterMerchant({
name: 'Acme Store',
description: 'Premium digital goods marketplace',
});
await wallet.signAndExecuteTransactionBlock({ transactionBlock: txb });
update_merchant_info
Updates merchant name and description.
public entry fun update_merchant_info(
merchant: &mut Merchant,
cap: &MerchantCap,
name: String,
description: String,
ctx: &mut TxContext
)
Parameters:
merchant- Mutable reference to merchant objectcap- Merchant capability (proves ownership)name- New merchant namedescription- New descriptionctx- Transaction context
Effects:
- Updates merchant name and description
Emits:
MerchantSettingsUpdatedevent
Errors:
E_NOT_AUTHORIZED- Cap doesn't match merchantE_INVALID_NAME- Name validation failed
add_supported_currency
Adds a supported currency with receiving address.
public entry fun add_supported_currency(
merchant: &mut Merchant,
cap: &MerchantCap,
currency: TypeName,
receiving_address: address,
ctx: &mut TxContext
)
Parameters:
merchant- Mutable reference to merchantcap- Merchant capabilitycurrency- Currency type to add (e.g.,0x2::sui::SUI)receiving_address- Address to receive payments in this currencyctx- Transaction context
Effects:
- Adds currency to supported currencies set
- Maps currency to receiving address
Emits:
MerchantSettingsUpdatedevent
Errors:
E_NOT_AUTHORIZED- Cap doesn't match merchantE_CURRENCY_ALREADY_SUPPORTED- Currency already addedE_INVALID_ADDRESS- Receiving address is 0x0
Example:
const txb = client.merchant.buildAddSupportedCurrency({
merchantObjectId: '0xMERCHANT_ID',
merchantCapId: '0xCAP_ID',
currencyType: '0x2::sui::SUI',
receivingAddress: '0xWALLET_ADDRESS',
});
remove_supported_currency
Removes a supported currency.
public entry fun remove_supported_currency(
merchant: &mut Merchant,
cap: &MerchantCap,
currency: TypeName,
ctx: &mut TxContext
)
Parameters:
merchant- Mutable reference to merchantcap- Merchant capabilitycurrency- Currency type to removectx- Transaction context
Effects:
- Removes currency from supported currencies
- Removes receiving address mapping
Emits:
MerchantSettingsUpdatedevent
Errors:
E_NOT_AUTHORIZED- Cap doesn't match merchantE_CURRENCY_NOT_SUPPORTED- Currency not in supported list
set_receiving_address
Updates receiving address for a currency.
public entry fun set_receiving_address(
merchant: &mut Merchant,
cap: &MerchantCap,
currency: TypeName,
new_address: address,
ctx: &mut TxContext
)
Parameters:
merchant- Mutable reference to merchantcap- Merchant capabilitycurrency- Currency type to updatenew_address- New receiving addressctx- Transaction context
Effects:
- Updates receiving address for specified currency
Emits:
MerchantSettingsUpdatedevent
Errors:
E_NOT_AUTHORIZED- Cap doesn't match merchantE_CURRENCY_NOT_SUPPORTED- Currency not supportedE_INVALID_ADDRESS- New address is 0x0
Example:
const txb = client.merchant.buildSetReceivingAddress({
merchantObjectId: '0xMERCHANT_ID',
merchantCapId: '0xCAP_ID',
currencyType: '0x2::sui::SUI',
newAddress: '0xNEW_WALLET_ADDRESS',
});
toggle_merchant_status
Toggles merchant active status.
public entry fun toggle_merchant_status(
merchant: &mut Merchant,
cap: &MerchantCap,
ctx: &mut TxContext
)
Parameters:
merchant- Mutable reference to merchantcap- Merchant capabilityctx- Transaction context
Effects:
- Toggles
is_activefield (true ↔ false) - Inactive merchants cannot receive new payments
Emits:
MerchantStatusChangedevent
Errors:
E_NOT_AUTHORIZED- Cap doesn't match merchant
Query Functions
is_active
Checks if merchant is active.
public fun is_active(merchant: &Merchant): bool
Returns:
bool- true if merchant is active
get_owner
Returns merchant owner address.
public fun get_owner(merchant: &Merchant): address
Returns:
address- Owner's address
get_name
Returns merchant name.
public fun get_name(merchant: &Merchant): String
Returns:
String- Merchant name
get_description
Returns merchant description.
public fun get_description(merchant: &Merchant): String
Returns:
String- Merchant description
get_receiving_address
Gets receiving address for a currency.
public fun get_receiving_address(
merchant: &Merchant,
currency: TypeName
): Option<address>
Parameters:
merchant- Reference to merchantcurrency- Currency type to query
Returns:
Option<address>- Receiving address (Some if currency supported)
supports_currency
Checks if merchant supports a currency.
public fun supports_currency(
merchant: &Merchant,
currency: TypeName
): bool
Parameters:
merchant- Reference to merchantcurrency- Currency type to check
Returns:
bool- true if currency is supported
get_fee_config
Returns merchant's fee configuration.
public fun get_fee_config(merchant: &Merchant): &FeeConfig
Returns:
&FeeConfig- Reference to fee configuration
get_platform_fee_bps
Gets platform fee in basis points.
public fun get_platform_fee_bps(merchant: &Merchant): u64
Returns:
u64- Platform fee in basis points (default: 30 = 0.3%)
Admin Functions
These functions are only callable by admin (with AdminCap).
set_merchant_fee
Sets merchant-specific fee (admin only).
public entry fun set_merchant_fee(
merchant: &mut Merchant,
admin_cap: &AdminCap,
platform_fee_bps: u64,
ctx: &mut TxContext
)
Parameters:
merchant- Mutable reference to merchantadmin_cap- Admin capabilityplatform_fee_bps- New platform fee in basis pointsctx- Transaction context
Effects:
- Updates merchant's platform fee
- Allows custom fees per merchant
Note: Only admin can modify fees. Merchants cannot set their own fees.
Events
MerchantRegistered
Emitted when a merchant is registered.
public struct MerchantRegistered has copy, drop {
merchant_id: ID,
owner: address,
name: String,
timestamp: u64,
}
MerchantSettingsUpdated
Emitted when merchant settings are updated.
public struct MerchantSettingsUpdated has copy, drop {
merchant_id: ID,
updated_by: address,
timestamp: u64,
}
MerchantStatusChanged
Emitted when merchant status changes.
public struct MerchantStatusChanged has copy, drop {
merchant_id: ID,
is_active: bool,
changed_by: address,
timestamp: u64,
}
Usage Examples
Complete Merchant Setup
// 1. Register merchant
merchant::register_merchant(
string::utf8(b"Acme Store"),
string::utf8(b"Premium digital goods"),
ctx
);
// 2. Add supported currencies
merchant::add_supported_currency(
&mut merchant,
&merchant_cap,
type_name::get<SUI>(),
wallet_address,
ctx
);
merchant::add_supported_currency(
&mut merchant,
&merchant_cap,
type_name::get<USDC>(),
usdc_wallet_address,
ctx
);
// 3. Verify setup
assert!(merchant::is_active(&merchant), 0);
assert!(merchant::supports_currency(&merchant, type_name::get<SUI>()), 1);
Currency Management
// Add new currency
merchant::add_supported_currency(
&mut merchant,
&cap,
currency_type,
receiving_addr,
ctx
);
// Update receiving address
merchant::set_receiving_address(
&mut merchant,
&cap,
currency_type,
new_addr,
ctx
);
// Remove currency
merchant::remove_supported_currency(
&mut merchant,
&cap,
currency_type,
ctx
);
Status Management
// Deactivate merchant (e.g., for maintenance)
merchant::toggle_merchant_status(&mut merchant, &cap, ctx);
assert!(!merchant::is_active(&merchant), 0);
// Reactivate merchant
merchant::toggle_merchant_status(&mut merchant, &cap, ctx);
assert!(merchant::is_active(&merchant), 0);
Security Considerations
Capability-Based Authorization
All merchant operations require MerchantCap:
// MerchantCap proves ownership
public struct MerchantCap has key {
merchant_id: ID, // Links to specific merchant
}
// Operations verify cap matches merchant
assert!(object::id(merchant) == cap.merchant_id, E_NOT_AUTHORIZED);
Fee Control
- ✅ Fees are admin-controlled only
- ✅ Merchants cannot set their own fees
- ✅ Prevents fee manipulation
- ✅ Platform maintains fee consistency
Address Validation
All receiving addresses are validated:
- ✅ Cannot be 0x0
- ✅ Checked before adding currency
- ✅ Verified on address updates
Best Practices
1. Store MerchantCap Securely
// After registration
const merchantCap = extractObjectId(result, 'MerchantCap');
// Store securely (database, environment variable, etc.)
process.env.MERCHANT_CAP_ID = merchantCap;
// Never share or expose publicly
2. Validate Before Operations
// Check merchant status before accepting payments
const isActive = await client.merchant.isMerchantActive(merchantId);
if (!isActive) {
throw new Error('Merchant is inactive');
}
// Verify currency support
const merchant = await client.merchant.getMerchant(merchantId);
if (!merchant.supported_currencies.includes(currencyType)) {
throw new Error('Currency not supported');
}
3. Handle Multiple Currencies
// Add all currencies at setup
const currencies = [
{ type: '0x2::sui::SUI', address: suiWallet },
{ type: '0x...::usdc::USDC', address: usdcWallet },
{ type: '0x...::usdt::USDT', address: usdtWallet },
];
for (const currency of currencies) {
const txb = client.merchant.buildAddSupportedCurrency({
merchantObjectId: merchantId,
merchantCapId: capId,
currencyType: currency.type,
receivingAddress: currency.address,
});
await wallet.signAndExecuteTransactionBlock({ transactionBlock: txb });
}
4. Use Separate Wallets
// Recommended: Use different wallets for different currencies
const wallets = {
SUI: '0xSUI_WALLET_ADDRESS',
USDC: '0xUSDC_WALLET_ADDRESS',
USDT: '0xUSDT_WALLET_ADDRESS',
};
// Better security and accounting
Architecture Notes
Admin-Controlled Fees
┌─────────────────────────────────────┐
│ Fee Management Architecture │
├─────────────────────────────────────┤
│ │
│ Admin (AdminCap) │
│ │ │
│ ├─► Set Platform Fee │
│ │ (Global Default) │
│ │ │
│ └─► Set Merchant Fee │
│ (Per-Merchant Override) │
│ │
│ Merchant (MerchantCap) │
│ │ │
│ ├─► Read Fee Config ✓ │
│ └─► Modify Fee ✗ (Not Allowed) │
│ │
└─────────────────────────────────────┘
For details, see the Core Modules documentation.
Next Steps
- Payment Module API - Payment operations
- Admin Module API - Admin operations
- Merchant Operations Guide - SDK merchant guide
- Merchant Getting Started - Complete merchant setup