Skip to main content

API Reference

This page lists the current developer-facing Move API in the protocol and market packages. It documents public entry functions, public helpers, key public structs, and module boundaries as they exist in source today.

Module organization

The public API is split into these modules:

  • mercatr::index — shared quadtree index and parcel lookup
  • mercatr::mutations — low-level geometry mutations gated by LifecycleCap
  • mercatr::admin — governed index creation, cap rotation, and sealing
  • mercatr_market::pricing — pure pricing math and PriceState
  • mercatr_market::market — shared market object, levels, treasury, pause, and tax wrappers
  • mercatr_market::trading — register, buy, price bump, price drop, and governed remove
  • mercatr_market::parcel_ops — expand, acquire, rebalance, split, and merge
  • mercatr_market::proposals — POI proposal boards and proposal lifecycle
  • mercatr_market::marks — parcel and POI marks

mercatr_market::revenue is not public API. Its functions are public(package) and exist only for internal payment routing.

mercatr::index

The index stores parcels in a quadtree and exposes the core parcel registry.

Public structs

Config

public struct Config has copy, drop, store {
max_vertices: u64,
max_parts_per_polygon: u64,
scaling_factor: u64,
max_broadphase_span: u64,
max_cell_occupancy: u64,
max_probes_per_call: u64,
}

Index

public struct Index has key, store {
id: object::UID,
cells: Table<u64, vector<ID>>,
polygons: Table<ID, Polygon>,
cell_size: u64,
max_depth: u8,
count: u64,
occupied_depths: u32,
config: Config,
authorized_caps: VecSet<ID>,
authorization_sealed: bool,
}

TransferCap

public struct TransferCap has key, store {
id: object::UID,
index_id: ID,
}

LifecycleCap

public struct LifecycleCap has key, store {
id: object::UID,
index_id: ID,
}

Public functions

public fun register(
_cap: &LifecycleCap,
index: &mut Index,
parts_xs: vector<vector<u64>>,
parts_ys: vector<vector<u64>>,
ctx: &mut tx_context::TxContext,
): ID

Registers a parcel and returns its object ID.

public fun remove(
_cap: &LifecycleCap,
index: &mut Index,
polygon_id: ID,
ctx: &mut tx_context::TxContext,
)
public fun transfer_ownership(
_cap: &LifecycleCap,
index: &mut Index,
polygon_id: ID,
new_owner: address,
ctx: &tx_context::TxContext,
)
public fun force_transfer(
_cap: &TransferCap,
index: &mut Index,
polygon_id: ID,
new_owner: address,
)
public fun candidates(index: &Index, query_id: ID): vector<ID>
public fun overlaps(index: &Index, id_a: ID, id_b: ID): bool
public fun outer_contains_inner(
outer_index: &Index,
outer_id: ID,
inner_index: &Index,
inner_id: ID,
): bool
public fun overlapping(index: &Index, query_id: ID): vector<ID>
public fun query_viewport(
index: &Index,
min_x: u64,
min_y: u64,
max_x: u64,
max_y: u64,
): vector<ID>
public fun new_config(
max_vertices: u64,
max_parts_per_polygon: u64,
scaling_factor: u64,
max_broadphase_span: u64,
max_cell_occupancy: u64,
max_probes_per_call: u64,
): Config
public fun is_sealed(index: &Index): bool
public fun count(index: &Index): u64
public fun cell_size(index: &Index): u64
public fun max_depth(index: &Index): u8
public fun max_vertices_per_part(index: &Index): u64
public fun max_parts_per_polygon(index: &Index): u64
public fun scaling_factor(index: &Index): u64
public fun max_broadphase_span(index: &Index): u64
public fun max_cell_occupancy(index: &Index): u64
public fun max_probes_per_call(index: &Index): u64
public fun get(index: &Index, polygon_id: ID): &Polygon

Package-only internals

new, with_config, share, share_existing, share_with_config, remove_unchecked, set_config, authorize_cap, seal, unseal, destroy_empty, and the geometry helpers are public(package). Call mercatr::admin for governed index creation and cap management.

mercatr::mutations

These functions mutate parcel geometry. They are public, but the intended caller is the market layer.

public fun reshape_unclaimed(
cap: &LifecycleCap,
index: &mut Index,
polygon_id: ID,
new_parts_xs: vector<vector<u64>>,
new_parts_ys: vector<vector<u64>>,
ctx: &tx_context::TxContext,
)
public fun repartition_adjacent(
cap: &LifecycleCap,
index: &mut Index,
a_id: ID,
a_parts_xs: vector<vector<u64>>,
a_parts_ys: vector<vector<u64>>,
b_id: ID,
b_parts_xs: vector<vector<u64>>,
b_parts_ys: vector<vector<u64>>,
ctx: &tx_context::TxContext,
)
public fun split_replace(
cap: &LifecycleCap,
index: &mut Index,
parent_id: ID,
children_parts_xs: vector<vector<vector<u64>>>,
children_parts_ys: vector<vector<vector<u64>>>,
ctx: &mut tx_context::TxContext,
): vector<ID>
public fun merge_keep(
cap: &LifecycleCap,
index: &mut Index,
keep_id: ID,
absorb_id: ID,
merged_parts_xs: vector<vector<u64>>,
merged_parts_ys: vector<vector<u64>>,
ctx: &tx_context::TxContext,
)
public fun remove_polygon(
cap: &LifecycleCap,
index: &mut Index,
polygon_id: ID,
ctx: &mut tx_context::TxContext,
)

mercatr::admin

This module creates indexes, mints and revokes capabilities, and seals or unseals authorization.

Public struct

public struct AdminCap has key, store {
id: sui::object::UID,
}

Public functions

public fun update_config(
_: &AdminCap,
index: &mut Index,
new_config: Config,
)
public fun create_index(
_: &AdminCap,
cell_size: u64,
max_depth: u8,
max_broadphase_span: u64,
max_cell_occupancy: u64,
max_probes_per_call: u64,
ctx: &mut sui::tx_context::TxContext,
): Index
public fun share_index(index: Index)
public fun destroy_index(_: &AdminCap, index: Index)
public fun mint_transfer_cap(
_: &AdminCap,
index: &mut Index,
ctx: &mut sui::tx_context::TxContext,
): TransferCap
public fun mint_lifecycle_cap(
_: &AdminCap,
index: &mut Index,
ctx: &mut sui::tx_context::TxContext,
): LifecycleCap
public fun mint_lifecycle_cap_with_id(
_: &AdminCap,
index: &mut Index,
ctx: &mut sui::tx_context::TxContext,
): (LifecycleCap, sui::object::ID)
public fun mint_caps_with_ids(
_: &AdminCap,
index: &mut Index,
ctx: &mut sui::tx_context::TxContext,
): (TransferCap, LifecycleCap, sui::object::ID, sui::object::ID)
public fun authorize_cap(
_: &AdminCap,
index: &mut Index,
cap_id: sui::object::ID,
)
public fun revoke_transfer_cap(
_: &AdminCap,
index: &mut Index,
cap_id: sui::object::ID,
)
public fun revoke_lifecycle_cap(
_: &AdminCap,
index: &mut Index,
cap_id: sui::object::ID,
)
public fun seal_index(_: &AdminCap, index: &mut Index)
public fun unseal_index(_: &AdminCap, index: &mut Index)

Disabled function

admin::force_remove is disabled in current code. The source keeps only a commented-out implementation and the production path is mercatr_market::trading::remove, which also cleans up PriceState, tax state, and metadata.

mercatr_market::pricing

This module holds pure pricing math.

Public struct

public struct PriceState has copy, drop, store {
premium_ppm: u64,
sale_count: u64,
}

Public functions

public fun next_resale_premium_ppm(
current_premium_ppm: u64,
sale_idx: u64,
): u64
public fun prev_resale_premium_ppm(
current_premium_ppm: u64,
current_sale_count: u64,
): u64
public fun post_registration_premium_ppm(): u64
public fun quote_price_from_premium(
area_m2: u64,
price_per_km2_mist: u64,
premium_ppm: u64,
): u64
public fun seller_proceeds_for_price(price: u64): u64
public fun treasury_fee_for_price(price: u64): u64
public fun hierarchy_pool_for_price(price: u64): u64

Removed names from older docs do not exist anymore. Do not call calculate_price or next_premium.

mercatr_market::market

This module owns the shared market object, level registry, treasury, pause switch, and tax wrappers.

Public structs

Level

public struct Level has copy, drop, store {
index_id: sui::object::ID,
price_per_km2_mist: u64,
min_area_m2: u64,
max_area_m2: u64,
}

MarketInner

public struct MarketInner has store {
version: u64,
transfer_cap: index::TransferCap,
lifecycle_cap: index::LifecycleCap,
treasury: Balance<SUI>,
price_states: Table<sui::object::ID, PriceState>,
levels: vector<Level>,
}

Market

public struct Market has key {
id: sui::object::UID,
paused: bool,
inner: Versioned,
}

Market stores its mutable core state inside inner: Versioned. Callers see a shared Market, but the actual market fields live in MarketInner behind the versioned wrapper.

MarketAdminCap

public struct MarketAdminCap has key, store {
id: sui::object::UID,
}

Public functions

public fun new(
transfer_cap: index::TransferCap,
lifecycle_cap: index::LifecycleCap,
ctx: &mut sui::tx_context::TxContext,
): Market
public fun share(market: Market)
public fun swap_caps(
_admin: &MarketAdminCap,
market: &mut Market,
new_transfer_cap: index::TransferCap,
new_lifecycle_cap: index::LifecycleCap,
_ctx: &mut sui::tx_context::TxContext,
): (index::TransferCap, index::LifecycleCap)
public fun add_level(
_admin: &MarketAdminCap,
market: &mut Market,
index: &index::Index,
price_per_km2_mist: u64,
min_area_m2: u64,
max_area_m2: u64,
)
public fun update_level(
_admin: &MarketAdminCap,
market: &mut Market,
level_index: u64,
price_per_km2_mist: u64,
min_area_m2: u64,
max_area_m2: u64,
)
public fun withdraw(
_admin: &MarketAdminCap,
market: &mut Market,
amount: u64,
ctx: &mut sui::tx_context::TxContext,
): Coin<SUI>
public fun pause(_admin: &MarketAdminCap, market: &mut Market)
public fun unpause(_admin: &MarketAdminCap, market: &mut Market)
public fun is_paused(market: &Market): bool
public fun treasury_balance(market: &Market): u64
public fun premium_ppm(market: &Market, polygon_id: sui::object::ID): u64
public fun sale_count(market: &Market, polygon_id: sui::object::ID): u64
public fun init_tax(
_admin: &MarketAdminCap,
market: &mut Market,
upstream_tax_bps: u64,
ctx: &mut sui::tx_context::TxContext,
)

upstream_tax_bps is still present in the call shape and is passed into tax::init_tax.

public fun set_tax_level_cfg(
_admin: &MarketAdminCap,
market: &mut Market,
level_index: u64,
cfg: tax::TaxLevelCfg,
)
public fun collect_tax(
market: &mut Market,
parent_index: &index::Index,
parent_id: sui::object::ID,
child_index: &index::Index,
child_ids: vector<sui::object::ID>,
child_bucket_ids: vector<u64>,
ctx: &mut sui::tx_context::TxContext,
)

This signature does not include child_versions.

public fun sweep_expired(
market: &mut Market,
polygon_id: sui::object::ID,
version: u64,
bucket_id: u64,
ctx: &mut sui::tx_context::TxContext,
)
public fun tax_is_initialized(market: &Market): bool
public fun tax_fund_balance(market: &Market): u64
public fun tax_version_counter(
market: &Market,
polygon_id: sui::object::ID,
): u64
public fun tax_self_claimable(
market: &Market,
polygon_id: sui::object::ID,
): u64

mercatr_market::trading

This module exposes the main market entry points.

Public entry functions and helpers

entry fun register(
market: &mut Market,
index: &mut index::Index,
parts_xs: vector<vector<u64>>,
parts_ys: vector<vector<u64>>,
mut payment: Coin<SUI>,
ctx: &mut sui::tx_context::TxContext,
): (sui::object::ID, Coin<SUI>)

The registration payment splits into 92% treasury and 8% hierarchy pool. The returned tuple is the new parcel ID plus the leftover payment coin.

entry fun buy_full(
market: &mut Market,
index: &mut index::Index,
polygon_id: sui::object::ID,
mut payment: Coin<SUI>,
ctx: &mut sui::tx_context::TxContext,
): Coin<SUI>

buy_full returns the leftover payment coin. Its payment split is 85% seller, 7% treasury, 8% hierarchy pool.

entry fun bump_price(
market: &mut Market,
index: &index::Index,
polygon_id: sui::object::ID,
mut payment: Coin<SUI>,
ctx: &mut sui::tx_context::TxContext,
): Coin<SUI>
entry fun drop_price(
market: &mut Market,
index: &index::Index,
polygon_id: sui::object::ID,
mut payment: Coin<SUI>,
ctx: &mut sui::tx_context::TxContext,
): Coin<SUI>
public fun current_price(
market: &Market,
index: &index::Index,
polygon_id: sui::object::ID,
): u64
public fun quote_bump_cost(
market: &Market,
index: &index::Index,
polygon_id: sui::object::ID,
): u64
public fun quote_drop_cost(
market: &Market,
index: &index::Index,
polygon_id: sui::object::ID,
): u64
public fun remove(
_admin: &MarketAdminCap,
market: &mut Market,
index: &mut index::Index,
polygon_id: sui::object::ID,
ctx: &mut sui::tx_context::TxContext,
)

mercatr_market::parcel_ops

These functions change parcel geometry through the market layer.

public fun expand_unclaimed(
market: &mut Market,
index: &mut index::Index,
polygon_id: sui::object::ID,
new_parts_xs: vector<vector<u64>>,
new_parts_ys: vector<vector<u64>>,
mut payment: Coin<SUI>,
ctx: &mut sui::tx_context::TxContext,
): Coin<SUI>

expand_unclaimed charges only for the added area and uses the same 92/8 treasury and hierarchy split as registration.

public fun acquire_slice(
market: &mut Market,
index: &mut index::Index,
receiver_id: sui::object::ID,
donor_id: sui::object::ID,
receiver_new_xs: vector<vector<u64>>,
receiver_new_ys: vector<vector<u64>>,
donor_new_xs: vector<vector<u64>>,
donor_new_ys: vector<vector<u64>>,
mut payment: Coin<SUI>,
ctx: &mut sui::tx_context::TxContext,
): Coin<SUI>

The protocol prices the captured area at the donor's current premium. After the transfer, the donor keeps its old premium_ppm, and the receiver gets the area-weighted blend of its old premium plus the acquired slice, rounded up with a ceiling division.

public fun rebalance_slice(
market: &mut Market,
index: &mut index::Index,
a_id: sui::object::ID,
a_new_xs: vector<vector<u64>>,
a_new_ys: vector<vector<u64>>,
b_id: sui::object::ID,
b_new_xs: vector<vector<u64>>,
b_new_ys: vector<vector<u64>>,
ctx: &mut sui::tx_context::TxContext,
)

rebalance_slice sets both parcels to the same area-weighted average premium, rounded up, and the max sale_count of the pair.

public fun split_owned(
market: &mut Market,
index: &mut index::Index,
parent_id: sui::object::ID,
children_parts_xs: vector<vector<vector<u64>>>,
children_parts_ys: vector<vector<vector<u64>>>,
ctx: &mut sui::tx_context::TxContext,
): vector<sui::object::ID>
public fun merge_owned(
market: &mut Market,
index: &mut index::Index,
keep_id: sui::object::ID,
absorb_id: sui::object::ID,
merged_parts_xs: vector<vector<u64>>,
merged_parts_ys: vector<vector<u64>>,
ctx: &mut sui::tx_context::TxContext,
)

merge_owned gives the survivor the area-weighted average premium, rounded up, and the max sale_count.

mercatr_market::proposals

This module manages POI proposal boards and escrowed offers.

Public structs

ProposalBoard

public struct ProposalBoard has key {
id: object::UID,
block_index_id: object::ID,
min_proposal_fee: u64,
max_per_polygon: u64,
max_per_proposer: u64,
pending_ttl_epochs: u64,
proposal_counter: u64,
escrow: Balance<SUI>,
}

Proposal

public struct Proposal has drop, store {
polygon_id: object::ID,
proposer: address,
poi_name: vector<u8>,
poi_coord_x: u64,
poi_coord_y: u64,
poi_icon: std::option::Option<vector<u8>>,
details_cid: std::option::Option<std::string::String>,
offer_amount: u64,
status: u8,
created_epoch: u64,
}

Public entry functions

entry fun create_proposal_board(
_admin: &market::MarketAdminCap,
block_index_id: object::ID,
min_proposal_fee: u64,
max_per_polygon: u64,
max_per_proposer: u64,
pending_ttl_epochs: u64,
ctx: &mut tx_context::TxContext,
)
entry fun set_min_offer(
board: &mut ProposalBoard,
index: &Index,
polygon_id: object::ID,
min_offer: u64,
ctx: &tx_context::TxContext,
)
entry fun propose_poi(
board: &mut ProposalBoard,
market: &mut market::Market,
index: &Index,
polygon_id: object::ID,
poi_name: vector<u8>,
poi_coord_x: u64,
poi_coord_y: u64,
poi_icon: std::option::Option<vector<u8>>,
details_cid: std::option::Option<std::string::String>,
mut payment: Coin<SUI>,
ctx: &mut tx_context::TxContext,
)
entry fun accept_proposal(
board: &mut ProposalBoard,
market: &mut market::Market,
index: &Index,
proposal_id: u64,
ctx: &mut tx_context::TxContext,
)
entry fun reject_proposal(
board: &mut ProposalBoard,
index: &Index,
proposal_id: u64,
ctx: &mut tx_context::TxContext,
)
entry fun withdraw_proposal(
board: &mut ProposalBoard,
proposal_id: u64,
ctx: &mut tx_context::TxContext,
)
entry fun prune_pending(
board: &mut ProposalBoard,
proposal_id: u64,
ctx: &mut tx_context::TxContext,
)

Public getters

public fun board_escrow_value(board: &ProposalBoard): u64
public fun board_proposal_counter(board: &ProposalBoard): u64
public fun get_proposal(board: &ProposalBoard, proposal_id: u64): &Proposal
public fun proposal_polygon_id(p: &Proposal): object::ID
public fun proposal_proposer(p: &Proposal): address
public fun proposal_poi_name(p: &Proposal): vector<u8>
public fun proposal_poi_coord_x(p: &Proposal): u64
public fun proposal_poi_coord_y(p: &Proposal): u64
public fun proposal_poi_icon(p: &Proposal): std::option::Option<vector<u8>>
public fun proposal_details_cid(
p: &Proposal,
): std::option::Option<std::string::String>
public fun proposal_offer_amount(p: &Proposal): u64
public fun proposal_status(p: &Proposal): u8
public fun proposal_created_epoch(p: &Proposal): u64
public fun get_polygon_proposal_ids(
board: &ProposalBoard,
polygon_id: object::ID,
): vector<u64>

The proposal fee floor goes to treasury. Any excess stays in escrow until accept, reject, withdraw, or expiry.

mercatr_market::marks

This module records paid reactions on parcels and accepted POIs.

Public struct

public struct MarkBoard has key {
id: object::UID,
}

Public entry functions

entry fun create_board(
_admin: &market::MarketAdminCap,
ctx: &mut tx_context::TxContext,
)
entry fun mark(
board: &mut MarkBoard,
market: &mut market::Market,
index: &Index,
polygon_id: object::ID,
mark_type: u8,
payment: Coin<SUI>,
ctx: &mut tx_context::TxContext,
)
entry fun mark_poi(
board: &mut MarkBoard,
market: &mut market::Market,
proposal_board: &proposals::ProposalBoard,
index: &Index,
proposal_id: u64,
mark_type: u8,
payment: Coin<SUI>,
ctx: &mut tx_context::TxContext,
)

Public getters

public fun get_poi_marks(
board: &MarkBoard,
proposal_id: u64,
): vector<u64>
public fun get_marks(
board: &MarkBoard,
polygon_id: object::ID,
): vector<u64>

Internal revenue module

mercatr_market::revenue contains only public(package) functions:

public(package) fun route_hierarchy_pool(...): Balance<SUI>
public(package) fun deposit_revenue(...): (Balance<SUI>, Balance<SUI>)
public(package) fun collect_treasury_fee(...): Balance<SUI>
public(package) fun route_mark_payment(...): Balance<SUI>

Treat this module as internal plumbing, not as a public integration surface.