Containers and Assets

Containers are the fundamental storage abstraction in Asset Core. They hold assets with different spatial characteristics depending on their kind.

Problem this concept solves

Real-world asset management involves diverse storage patterns:

  • Aggregated quantities (account balances, inventory counts)
  • Ordered sequences (equipment slots, ranked lists)
  • Spatial arrangements (warehouse grids, lab plates)

A single storage model cannot efficiently represent all these patterns. Asset Core solves this by providing multiple container kinds, each optimized for its spatial dimension while sharing a common operation interface.

Core ideas

Dimensional Classification

Containers are classified by the dimensionality of their address space:

KindDimensionAddress SpaceUse Case
Standard0DNone (aggregation only)Balances, totals
Slots1DSequential indicesEquipment, ordered lists
Grid2DLattice coordinatesPlates, warehouses
Continuous Line1DFixed-point coordinate (x)Rails, actuators
Continuous Plane2DFixed-point coordinates (x, y)Robot workcells, pick-and-place

Each dimension adds spatial semantics while preserving the same operation grammar.

Balances (0D)

Standard containers hold fungible balances:

  • Identified by (class_id, key) pairs
  • Quantities aggregate without spatial position
  • Support add, remove, and transfer operations

Example: A reagent inventory where you only care about total quantities.

{
  "op": "AddFungible",
  "args": {
    "container_id": 1001,
    "class_id": 100,
    "key": 1,
    "quantity": 500
  }
}

Slots (1D)

Slot containers hold unique instances in sequential positions:

  • Indices from 0 to N-1 (configurable capacity)
  • Each slot holds at most one instance
  • Support place, remove, and swap operations

Example: Equipment slots on a character or positions in a processing queue.

{
  "op": "PlaceInSlot",
  "args": {
    "container_id": 1001,
    "instance_id": 9001,
    "slot_index": 0
  }
}

Grid (2D)

Grid containers add spatial geometry:

  • Width x Height lattice of cells
  • Items occupy multiple cells based on shape
  • Support collision detection and adjacency

Example: A 96-well plate or warehouse storage grid.

Grid containers can hold both fungible stacks (with spatial placement) and unique instances.

Continuous Line (1D)

Continuous line containers store instances along a single fixed-point axis:

  • Coordinates are deterministic fixed-point integers (no floats)
  • Placements must remain within min/max bounds
  • Collision checks enforce non-overlapping spans

Use cases: linear rails, conveyors with sub-cell precision, and single-axis robotics.

Continuous Plane (2D)

Continuous plane containers store instances in a bounded, continuous workspace:

  • Fixed-point x/y coordinates with deterministic rounding
  • Oriented-rectangle collision checks (rotation in millidegrees)
  • Bounds-checked placements, moves, and rotations
  • Instance-only placements (no fungible stacks)

Use cases: robot workcells, pick-and-place tasks, and metric collision planning.

Instances vs. Fungibles

Fungible assets are interchangeable quantities:

  • Identified by class and key
  • Operations specify quantities
  • Can be split and merged freely

Unique instances are individually tracked:

  • Have globally unique IDs
  • Cannot be split or merged
  • Can form parent-child hierarchies via attach/detach

Classes and Shapes

Classes define asset types:

  • Specify whether assets are fungible or unique
  • Provide metadata like names
  • Must be registered before use

Shapes define spatial footprints:

  • Width and height in grid cells
  • Associated with a class
  • Required for grid container placement
{
  "op": "RegisterClass",
  "args": {
    "request": {
      "class_id": 200,
      "name": "Sample Tube",
      "fungible": false
    }
  }
}

How it fits into the system

Operation Dispatch

The runtime dispatches operations based on container kind:

  • AddFungible on Standard: direct balance addition
  • AddFungible on Grid: spatial placement with shape lookup
  • AddFungible on Slots: rejected (wrong container kind)

This dispatch is handled internally; clients specify operations without knowing container internals.

Event Generation

Each container kind generates appropriate events:

  • Standard: BalanceAdded, BalanceRemoved
  • Slots: SlotOccupied, SlotCleared
  • Grid: GridPlacement, StackQtyChanged

Events carry post-state for deterministic replay.

Index Maintenance

The runtime maintains indexes for efficient queries:

  • Balance lookups by class and key
  • Instance locations by ID
  • Slot occupancy by index

These indexes are updated atomically with operations.

Key invariants and guarantees

Container Lifecycle

  • Containers must be created before use
  • Containers must be empty before removal
  • Container IDs cannot be reused

Capacity Constraints

  • Slot indices must be within bounds
  • Grid placements must fit within dimensions
  • Quantities cannot overflow u64

Type Safety

  • Fungible operations reject Slots containers
  • Slot operations reject Standard containers
  • Operations validate container kind before execution

See also