Skip to main content

Merchant Module API Reference

API reference for dolphinpay::merchant (contract/sources/core/merchant.move).

The module handles merchant registration, receiving addresses, and active/inactive status. Merchants have no fee configuration — the platform fee is global and admin-governed (see the Admin API); it is currently 0 bps by policy.

Data structures

Merchant

Shared object created at registration.

public struct Merchant has key, store {
id: UID,
owner: address,
name: String, // 1–100 chars
description: String, // ≤ 500 chars
receiving_addresses: VecMap<TypeName, address>,
settings: MerchantSettings,
created_at: u64, // ms
is_active: bool,
supported_currencies: VecSet<TypeName>,
}

MerchantCap

Capability transferred to the registering sender; required for all merchant mutations.

public struct MerchantCap has key {
id: UID,
merchant_id: ID,
}

MerchantSettings

public struct MerchantSettings has store {
auto_settlement: bool,
settlement_threshold: u64,
webhook_url: String,
api_keys: vector<String>,
require_confirmation: bool,
}

Defaults are all-off/empty at registration. There is no fee config and no refund policy in the merchant object.

Constants

const MAX_NAME_LENGTH: u64 = 100;
const MAX_DESCRIPTION_LENGTH: u64 = 500;

Error codes

const E_NOT_AUTHORIZED: u64 = 1;
const E_INVALID_FEE: u64 = 200; // declared; unused
const E_MERCHANT_NOT_FOUND: u64 = 201; // declared; unused
const E_MERCHANT_INACTIVE: u64 = 202;
const E_INVALID_NAME: u64 = 203;
const E_FEE_TOO_HIGH: u64 = 204; // declared; unused
const E_CURRENCY_ALREADY_SUPPORTED: u64 = 205;
const E_CURRENCY_NOT_SUPPORTED: u64 = 206;
const E_INVALID_ADDRESS: u64 = 207;

Entry functions

register_merchant

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

Creates and shares a Merchant object (active by default) and transfers a MerchantCap to the sender.

Emits: MerchantRegistered

Aborts: E_INVALID_NAME — name empty or > 100 chars, or description

500 chars


update_merchant_info

public entry fun update_merchant_info(
merchant: &mut Merchant,
cap: &MerchantCap,
name: String,
description: String,
ctx: &TxContext,
)

Updates name and/or description. An empty string keeps the current value.

Emits: MerchantSettingsUpdated

Aborts: E_NOT_AUTHORIZED (cap doesn't match merchant), E_INVALID_NAME (length limits)


add_supported_currency

public entry fun add_supported_currency<T>(
merchant: &mut Merchant,
cap: &MerchantCap,
receiving_address: address,
)

Registers coin type T with a receiving address for this merchant. Note: the platform accepts only native Circle USDC, so registering any other type has no effect on payments — only the USDC entry is ever used by payment::execute_payment_with_merchant.

Aborts: E_NOT_AUTHORIZED, E_INVALID_ADDRESS (address is @0x0), E_CURRENCY_ALREADY_SUPPORTED


remove_supported_currency

public entry fun remove_supported_currency<T>(
merchant: &mut Merchant,
cap: &MerchantCap,
)

Removes T from the supported set and drops its receiving address.

Aborts: E_NOT_AUTHORIZED, E_CURRENCY_NOT_SUPPORTED


set_receiving_address

public entry fun set_receiving_address<T>(
merchant: &mut Merchant,
cap: &MerchantCap,
receiving_address: address,
)

Updates the receiving address for an already-supported currency T.

Aborts: E_NOT_AUTHORIZED, E_INVALID_ADDRESS, E_CURRENCY_NOT_SUPPORTED


toggle_merchant_status

public entry fun toggle_merchant_status(
merchant: &mut Merchant,
cap: &MerchantCap,
active: bool,
ctx: &TxContext,
)

Sets is_active to the given value. Inactive merchants cannot be used with create_payment_with_merchant / execute_payment_with_merchant.

Emits: MerchantStatusChanged

Aborts: E_NOT_AUTHORIZED

Query functions

public fun is_merchant_active(merchant: &Merchant): bool
public fun is_currency_supported<T>(merchant: &Merchant): bool
public fun get_receiving_address<T>(merchant: &Merchant): address
// aborts with E_CURRENCY_NOT_SUPPORTED if T isn't supported
public fun get_owner(merchant: &Merchant): address
public fun get_name(merchant: &Merchant): String
public fun get_description(merchant: &Merchant): String
public fun get_created_at(merchant: &Merchant): u64

Admin override (package-private)

public(package) fun admin_set_active_status(merchant: &mut Merchant, active: bool)

Callable only from within the package — used by admin::force_activate_merchant / admin::force_deactivate_merchant (AdminCap-gated). See the Admin API.

Usage example

# Register a merchant
sui client call \
--package <PACKAGE_ID> --module merchant --function register_merchant \
--args "Acme Store" "Digital goods"

# Set a dedicated USDC receiving address
sui client call \
--package <PACKAGE_ID> --module merchant --function add_supported_currency \
--type-args <USDC_TYPE> \
--args <MERCHANT_ID> <MERCHANT_CAP_ID> <RECEIVING_ADDRESS>

<USDC_TYPE> on testnet: 0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC. Package and object IDs come from DEPLOYMENT.md — never hard-code stale IDs.

Security notes

  • All mutations verify cap.merchant_id == object::id(merchant).
  • Receiving addresses cannot be @0x0.
  • Fees are outside merchant control entirely; there is no merchant fee field to configure or manipulate.
  • Keep the MerchantCap object secure — whoever holds it controls the merchant record.

Next steps