Skip to main content

Module sui::accumulator_metadata

use std::ascii;
use std::bcs;
use std::option;
use std::string;
use std::vector;
use sui::accumulator;
use sui::address;
use sui::bag;
use sui::dynamic_field;
use sui::hex;
use sui::object;
use sui::party;
use sui::transfer;
use sui::tx_context;
use sui::vec_map;

Struct `OwnerKey`

=== Accumulator metadata ===

Accumulator metadata is organized as follows:

  • Each address that holds at least one type of accumulator has an owner field attached to the accumulator root.
  • For each type of accumulator held by that address, there is an AccumulatorMetadata field attached to the owner field.
  • When the value of an accumulator drops to zero, the metadata field is removed.
  • If the owner field has no more accumulator metadata field attached to it, it is removed as well.
public struct OwnerKey has copy, drop, store
Fields
owner: address

Struct `Owner`

An owner field, to which all AccumulatorMetadata fields for the owner are attached.
public struct Owner has store
Fields
balances: sui::bag::Bag
The individual balances owned by the owner.
owner: address

Struct `MetadataKey`

public struct MetadataKey<phantom T> has copy, drop, store
Fields

Struct `Metadata`

A metadata field for a balance field with type T.
public struct Metadata<phantom T> has store
Fields
fields: sui::bag::Bag
Any per-balance fields we wish to add in the future.

Constants

const EInvariantViolation: u64 = 0;

Function `accumulator_root_owner_exists`

=== Owner functions === Check if there is an owner field attached to the accumulator root.
fun accumulator_root_owner_exists(accumulator_root: &sui::accumulator::AccumulatorRoot, owner: address): bool
Implementation
fun accumulator_root_owner_exists(accumulator_root: &AccumulatorRoot, owner: address): bool {
    dynamic_field::exists_with_type<OwnerKey, Owner>(accumulator_root.id(), OwnerKey { owner })
}

Function `accumulator_root_borrow_owner_mut`

Borrow an owner field mutably.
fun accumulator_root_borrow_owner_mut(accumulator_root: &mut sui::accumulator::AccumulatorRoot, owner: address): &mut sui::accumulator_metadata::Owner
Implementation
fun accumulator_root_borrow_owner_mut(
    accumulator_root: &mut AccumulatorRoot,
    owner: address,
): &mut Owner {
    dynamic_field::borrow_mut(accumulator_root.id_mut(), OwnerKey { owner })
}

Function `accumulator_root_attach_owner`

Attach an owner field to the accumulator root.
fun accumulator_root_attach_owner(accumulator_root: &mut sui::accumulator::AccumulatorRoot, owner: sui::accumulator_metadata::Owner)
Implementation
fun accumulator_root_attach_owner(accumulator_root: &mut AccumulatorRoot, owner: Owner) {
    dynamic_field::add(accumulator_root.id_mut(), OwnerKey { owner: owner.owner }, owner);
}

Function `accumulator_root_detach_owner`

Detach an owner field from the accumulator root.
fun accumulator_root_detach_owner(accumulator_root: &mut sui::accumulator::AccumulatorRoot, owner: address): sui::accumulator_metadata::Owner
Implementation
fun accumulator_root_detach_owner(accumulator_root: &mut AccumulatorRoot, owner: address): Owner {
    dynamic_field::remove(accumulator_root.id_mut(), OwnerKey { owner })
}

Function `create_accumulator_metadata`

=== Metadata functions === Create a metadata field for a new balance field with type T. The metadata will be attached to the owner field owner. If the owner field does not exist, it will be created.
public(package) fun create_accumulator_metadata<T>(accumulator_root: &mut sui::accumulator::AccumulatorRoot, owner: address, ctx: &mut sui::tx_context::TxContext)
Implementation
public(package) fun create_accumulator_metadata<T>(
    accumulator_root: &mut AccumulatorRoot,
    owner: address,
    ctx: &mut TxContext,
) {
    let metadata = Metadata<T> {
        fields: bag::new(ctx),
    };
    if (accumulator_root.owner_exists(owner)) {
        let accumulator_owner = accumulator_root.borrow_owner_mut(owner);
        assert!(accumulator_owner.owner == owner, EInvariantViolation);
        accumulator_owner.attach_metadata(metadata);
    } else {
        let mut accumulator_owner = Owner {
            balances: bag::new(ctx),
            owner,
        };
        accumulator_owner.attach_metadata(metadata);
        accumulator_root.attach_owner(accumulator_owner);
    }
}

Function `remove_accumulator_metadata`

Remove the metadata field for a balance field with type T. The metadata will be detached from the owner field owner. If there are no more balance fields attached to the owner field, the owner field will be destroyed.
public(package) fun remove_accumulator_metadata<T>(accumulator_root: &mut sui::accumulator::AccumulatorRoot, owner: address)
Implementation
public(package) fun remove_accumulator_metadata<T>(
    accumulator_root: &mut AccumulatorRoot,
    owner: address,
) {
    let is_empty = {
        let accumulator_owner = accumulator_root.borrow_owner_mut(owner);
        let Metadata { fields } = accumulator_owner.detach_metadata<T>();
        fields.destroy_empty();
        accumulator_owner.balances.is_empty()
    };
    if (is_empty) {
        accumulator_root.detach_owner(owner).destroy();
    }
}

Function `accumulator_owner_attach_metadata`

Attach a metadata field for type T to the owner field.
fun accumulator_owner_attach_metadata<T>(self: &mut sui::accumulator_metadata::Owner, metadata: sui::accumulator_metadata::Metadata<T>)
Implementation
fun accumulator_owner_attach_metadata<T>(self: &mut Owner, metadata: Metadata<T>) {
    self.balances.add(MetadataKey<T>(), metadata);
}

Function `accumulator_owner_detach_metadata`

Detach a metadata field for type T from the owner field.
fun accumulator_owner_detach_metadata<T>(self: &mut sui::accumulator_metadata::Owner): sui::accumulator_metadata::Metadata<T>
Implementation
fun accumulator_owner_detach_metadata<T>(self: &mut Owner): Metadata<T> {
    self.balances.remove(MetadataKey<T>())
}

Function `accumulator_owner_destroy`

Destroy an owner field.
fun accumulator_owner_destroy(this: sui::accumulator_metadata::Owner)
Implementation
fun accumulator_owner_destroy(this: Owner) {
    let Owner { balances, .. } = this;
    balances.destroy_empty();
}