Module iota::coin_manager
The purpose of a CoinManager is to allow access to all properties of a Coin on-chain from within a single shared object This includes access to the total supply and metadata In addition a optional maximum supply can be set and a custom additional Metadata field can be added.
use iota::address;
use iota::bag;
use iota::balance;
use iota::coin;
use iota::config;
use iota::deny_list;
use iota::dynamic_field;
use iota::dynamic_object_field;
use iota::event;
use iota::hex;
use iota::object;
use iota::transfer;
use iota::tx_context;
use iota::types;
use iota::url;
use std::address;
use std::ascii;
use std::bcs;
use std::option;
use std::string;
use std::type_name;
use std::vector;
Module Functions
pub create
Convenience wrapper to create a new Coin and instantly wrap the cap inside a CoinManager.
public fun create<T: drop>(witness: T, decimals: u8, symbol: vector<u8>, name: vector<u8>, description: vector<u8>, icon_url: std::option::Option<iota::url::Url>, ctx: &mut iota::tx_context::TxContext): (iota::coin_manager::CoinManagerTreasuryCap<T>, iota::coin_manager::CoinManagerMetadataCap<T>, iota::coin_manager::CoinManager<T>)
Implementation
public fun create<T: drop>(
witness: T,
decimals: u8,
symbol: vector<u8>,
name: vector<u8>,
description: vector<u8>,
icon_url: Option<Url>,
ctx: &mut TxContext,
): (CoinManagerTreasuryCap<T>, CoinManagerMetadataCap<T>, CoinManager<T>) {
let (cap, meta) = coin::create_currency(
witness,
decimals,
symbol,
name,
description,
icon_url,
ctx,
);
new(cap, meta, ctx)
}
pub new
Wraps all important objects related to a Coin inside a shared object.
public fun new<T>(treasury_cap: iota::coin::TreasuryCap<T>, metadata: iota::coin::CoinMetadata<T>, ctx: &mut iota::tx_context::TxContext): (iota::coin_manager::CoinManagerTreasuryCap<T>, iota::coin_manager::CoinManagerMetadataCap<T>, iota::coin_manager::CoinManager<T>)
Implementation
public fun new<T>(
treasury_cap: TreasuryCap<T>,
metadata: CoinMetadata<T>,
ctx: &mut TxContext,
): (CoinManagerTreasuryCap<T>, CoinManagerMetadataCap<T>, CoinManager<T>) {
let manager = CoinManager {
id: object::new(ctx),
treasury_cap,
metadata: option::some(metadata),
immutable_metadata: option::none(),
maximum_supply: option::none(),
supply_immutable: false,
metadata_immutable: false,
};
event::emit(CoinManaged {
coin_name: type_name::into_string(type_name::get<T>()),
});
(
CoinManagerTreasuryCap<T> {
id: object::new(ctx),
},
CoinManagerMetadataCap<T> {
id: object::new(ctx),
},
manager,
)
}
pub new_with_immutable_metadata
This function allows the same as new but under the assumption the Metadata can not be transferred.
This would typically be the case with Coin instances where the metadata is already frozen.
public fun new_with_immutable_metadata<T>(treasury_cap: iota::coin::TreasuryCap<T>, metadata: &iota::coin::CoinMetadata<T>, ctx: &mut iota::tx_context::TxContext): (iota::coin_manager::CoinManagerTreasuryCap<T>, iota::coin_manager::CoinManager<T>)
Implementation
public fun new_with_immutable_metadata<T>(
treasury_cap: TreasuryCap<T>,
metadata: &CoinMetadata,
ctx: &mut TxContext,
): (CoinManagerTreasuryCap<T>, CoinManager<T>) {
let metacopy = ImmutableCoinMetadata<T> {
decimals: metadata.get_decimals(),
name: metadata.get_name(),
symbol: metadata.get_symbol(),
description: metadata.get_description(),
icon_url: metadata.get_icon_url(),
};
let manager = CoinManager {
id: object::new(ctx),
treasury_cap,
metadata: option::none(),
immutable_metadata: option::some(metacopy),
maximum_supply: option::none(),
supply_immutable: false,
metadata_immutable: true,
};
event::emit(CoinManaged {
coin_name: type_name::into_string(type_name::get<T>()),
});
(
CoinManagerTreasuryCap<T> {
id: object::new(ctx),
},
manager,
)
}
Structs
struct CoinManager
Holds all the related objects to the coin of type T in a convenient shared function.
public struct CoinManager<phantom T> has key, store
Fields
id: iota::object::UIDtreasury_cap: iota::coin::TreasuryCap<T>The original
TreasuryCapobject as returned bycreate_currency.metadata: std::option::Option<iota::coin::CoinMetadata<T>>Metadata object, original one from the
coinmodule, if available.immutable_metadata: std::option::Option<iota::coin_manager::ImmutableCoinMetadata<T>>Immutable Metadata object, only to be used as a last resort if the original metadata is frozen.
maximum_supply: std::option::Option<u64>Optional maximum supply, if set you can't mint more as this number - can only be set once.
supply_immutable: boolFlag indicating if the supply is considered immutable (TreasuryCap is exchanged for this).
metadata_immutable: boolFlag indicating if the metadata is considered immutable (MetadataCap is exchanged for this).
pub additional_metadata
public fun additional_metadata<T, Value: store>(manager: &mut iota::coin_manager::CoinManager<T>): &Value
Implementation
public fun additional_metadata<T, Value: store>(manager: &mut CoinManager<T>): &Value {
assert!(df::exists_(&manager.id, ADDITIONAL_METADATA_NAME), EAdditionalMetadataDoesNotExist);
let meta: &Value = df::borrow(&manager.id, ADDITIONAL_METADATA_NAME);
meta
}
pub available_supply
Convenience function returning the remaining supply that can be minted still.
public fun available_supply<T>(manager: &iota::coin_manager::CoinManager<T>): u64
Implementation
public fun available_supply<T>(manager: &CoinManager<T>): u64 {
maximum_supply(manager) - total_supply(manager)
}
pub decimals
public fun decimals<T>(manager: &iota::coin_manager::CoinManager<T>): u8
Implementation
public fun decimals<T>(manager: &CoinManager<T>): u8 {
if (option::is_some(&manager.metadata)) {
coin::get_decimals(option::borrow(&manager.metadata))
} else {
option::borrow(&manager.immutable_metadata).decimals
}
}
pub description
public fun description<T>(manager: &iota::coin_manager::CoinManager<T>): std::string::String
Implementation
public fun description<T>(manager: &CoinManager<T>): string::String {
if (option::is_some(&manager.metadata)) {
coin::get_description(option::borrow(&manager.metadata))
} else {
option::borrow(&manager.immutable_metadata).description
}
}
pub get_additional_metadata
Immutably borrows the additional metadata.
public fun get_additional_metadata<T, Value: store>(manager: &iota::coin_manager::CoinManager<T>): &Value
Implementation
public fun get_additional_metadata<T, Value: store>(manager: &CoinManager<T>): &Value {
assert!(df::exists_(&manager.id, ADDITIONAL_METADATA_NAME), EAdditionalMetadataDoesNotExist);
let meta: &Value = df::borrow(&manager.id, ADDITIONAL_METADATA_NAME);
meta
}
pub has_maximum_supply
Returns if a maximum supply has been set for this Coin or not.
public fun has_maximum_supply<T>(manager: &iota::coin_manager::CoinManager<T>): bool
Implementation
public fun has_maximum_supply<T>(manager: &CoinManager<T>): bool {
option::is_some(&manager.maximum_supply)
}
pub icon_url
public fun icon_url<T>(manager: &iota::coin_manager::CoinManager<T>): std::option::Option<iota::url::Url>
Implementation
public fun icon_url<T>(manager: &CoinManager<T>): Option<Url> {
if (option::is_some(&manager.metadata)) {
coin::get_icon_url(option::borrow(&manager.metadata))
} else {
option::borrow(&manager.immutable_metadata).icon_url
}
}
pub immutable_metadata
Get a read-only version of the read-only metadata, available for everyone.
public fun immutable_metadata<T>(manager: &iota::coin_manager::CoinManager<T>): &iota::coin_manager::ImmutableCoinMetadata<T>
Implementation
public fun immutable_metadata<T>(manager: &CoinManager<T>): &ImmutableCoinMetadata<T> {
option::borrow(&manager.immutable_metadata)
}
pub maximum_supply
Get the maximum supply possible as a number. If no maximum set it's the maximum u64 possible.
public fun maximum_supply<T>(manager: &iota::coin_manager::CoinManager<T>): u64
Implementation
public fun maximum_supply<T>(manager: &CoinManager<T>): u64 {
option::get_with_default(&manager.maximum_supply, MAX_SUPPLY)
}
pub metadata
Get a read-only version of the metadata, available for everyone.
public fun metadata<T>(manager: &iota::coin_manager::CoinManager<T>): &iota::coin::CoinMetadata<T>
Implementation
public fun metadata<T>(manager: &CoinManager<T>): &CoinMetadata {
option::borrow(&manager.metadata)
}
pub metadata_is_immutable
Convenience function allowing users to query if the ownership of the metadata management and thus the ability to change any of the metadata has been renounced.
public fun metadata_is_immutable<T>(manager: &iota::coin_manager::CoinManager<T>): bool
Implementation
public fun metadata_is_immutable<T>(manager: &CoinManager<T>): bool {
manager.metadata_immutable || option::is_some(&manager.immutable_metadata)
}
pub name
public fun name<T>(manager: &iota::coin_manager::CoinManager<T>): std::string::String
Implementation
public fun name<T>(manager: &CoinManager<T>): string::String {
if (option::is_some(&manager.metadata)) {
coin::get_name(option::borrow(&manager.metadata))
} else {
option::borrow(&manager.immutable_metadata).name
}
}
pub supply_immut
Get immutable reference to the treasury's Supply.
public fun supply_immut<T>(manager: &iota::coin_manager::CoinManager<T>): &iota::balance::Supply<T>
Implementation
public fun supply_immut<T>(manager: &CoinManager<T>): &Supply {
coin::supply_immut(&manager.treasury_cap)
}
pub supply_is_immutable
Convenience function allowing users to query if the ownership of the supply of this Coin
and thus the ability to mint new Coin has been renounced.
public fun supply_is_immutable<T>(manager: &iota::coin_manager::CoinManager<T>): bool
Implementation
public fun supply_is_immutable<T>(manager: &CoinManager<T>): bool {
manager.supply_immutable
}
pub symbol
public fun symbol<T>(manager: &iota::coin_manager::CoinManager<T>): std::ascii::String
Implementation
public fun symbol<T>(manager: &CoinManager<T>): ascii::String {
if (option::is_some(&manager.metadata)) {
coin::get_symbol(option::borrow(&manager.metadata))
} else {
option::borrow(&manager.immutable_metadata).symbol
}
}
pub total_supply
Get the total supply as a number.
public fun total_supply<T>(manager: &iota::coin_manager::CoinManager<T>): u64
Implementation
public fun total_supply<T>(manager: &CoinManager<T>): u64 {
coin::total_supply(&manager.treasury_cap)
}
struct CoinManagerTreasuryCap
Like TreasuryCap, but for dealing with TreasuryCap inside CoinManager objects.
public struct CoinManagerTreasuryCap<phantom T> has key, store
Fields
pub enforce_maximum_supply
A one-time callable function to set a maximum mintable supply on a coin. This can only be set once and is irrevertable.
public fun enforce_maximum_supply<T>(_: &iota::coin_manager::CoinManagerTreasuryCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, maximum_supply: u64)
Implementation
public fun enforce_maximum_supply<T>(
_: &CoinManagerTreasuryCap<T>,
manager: &mut CoinManager<T>,
maximum_supply: u64,
) {
assert!(option::is_none(&manager.maximum_supply), EMaximumSupplyAlreadySet);
assert!(maximum_supply <= MAX_SUPPLY, EMaximumSupplyHigherThanPossible);
assert!(total_supply(manager) <= maximum_supply, EMaximumSupplyLowerThanTotalSupply);
option::fill(&mut manager.maximum_supply, maximum_supply);
}
pub mint
Create a coin worth value and increase the total supply
in cap accordingly.
public fun mint<T>(_: &iota::coin_manager::CoinManagerTreasuryCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, value: u64, ctx: &mut iota::tx_context::TxContext): iota::coin::Coin<T>
Implementation
public fun mint<T>(
_: &CoinManagerTreasuryCap<T>,
manager: &mut CoinManager<T>,
value: u64,
ctx: &mut TxContext,
): Coin<T> {
assert!(total_supply(manager) + value <= maximum_supply(manager), EMaximumSupplyReached);
coin::mint(&mut manager.treasury_cap, value, ctx)
}
pub mint_and_transfer
Mint amount of Coin and send it to recipient. Invokes mint().
public fun mint_and_transfer<T>(_: &iota::coin_manager::CoinManagerTreasuryCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, amount: u64, recipient: address, ctx: &mut iota::tx_context::TxContext)
Implementation
public fun mint_and_transfer<T>(
_: &CoinManagerTreasuryCap<T>,
manager: &mut CoinManager<T>,
amount: u64,
recipient: address,
ctx: &mut TxContext,
) {
assert!(total_supply(manager) + amount <= maximum_supply(manager), EMaximumSupplyReached);
coin::mint_and_transfer(&mut manager.treasury_cap, amount, recipient, ctx)
}
pub mint_balance
Mint some amount of T as a Balance and increase the total
supply in cap accordingly.
Aborts if value + cap.total_supply >= U64_MAX
public fun mint_balance<T>(_: &iota::coin_manager::CoinManagerTreasuryCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, value: u64): iota::balance::Balance<T>
Implementation
public fun mint_balance<T>(
_: &CoinManagerTreasuryCap<T>,
manager: &mut CoinManager<T>,
value: u64,
): Balance<T> {
assert!(total_supply(manager) + value <= maximum_supply(manager), EMaximumSupplyReached);
coin::mint_balance(&mut manager.treasury_cap, value)
}
pub renounce_treasury_ownership
An irreversible action renouncing supply ownership which can be called if you hold the CoinManagerTreasuryCap.
This action provides Coin holders with some assurances if called, namely that there will
not be any new minting or changes to the supply from this point onward. The maximum supply
will be set to the current supply and will not be changed any more afterwards.
public fun renounce_treasury_ownership<T>(cap: iota::coin_manager::CoinManagerTreasuryCap<T>, manager: &mut iota::coin_manager::CoinManager<T>)
Implementation
public fun renounce_treasury_ownership<T>(
cap: CoinManagerTreasuryCap<T>,
manager: &mut CoinManager<T>,
) {
// Deleting the Cap
let CoinManagerTreasuryCap { id } = cap;
object::delete(id);
// Updating the maximum supply to the total supply
let total_supply = total_supply(manager);
if (manager.has_maximum_supply()) {
option::swap(&mut manager.maximum_supply, total_supply);
} else {
option::fill(&mut manager.maximum_supply, total_supply);
};
// Setting ownership renounced to true
manager.supply_immutable = true;
event::emit(TreasuryOwnershipRenounced {
coin_name: type_name::into_string(type_name::get<T>()),
});
}
pub entry burn
Destroy the coin c and decrease the total supply in cap
accordingly.
public entry fun burn<T>(_: &iota::coin_manager::CoinManagerTreasuryCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, c: iota::coin::Coin<T>): u64
Implementation
public entry fun burn<T>(
_: &CoinManagerTreasuryCap<T>,
manager: &mut CoinManager<T>,
c: Coin<T>,
): u64 {
coin::burn(&mut manager.treasury_cap, c)
}
struct CoinManagerMetadataCap
Metadata has it's own Cap, independent of the TreasuryCap.
public struct CoinManagerMetadataCap<phantom T> has key, store
Fields
pub add_additional_metadata
Option to add an additional metadata object to the manager. Can contain whatever you need in terms of additional metadata as a object.
public fun add_additional_metadata<T, Value: store>(_: &iota::coin_manager::CoinManagerMetadataCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, value: Value)
Implementation
public fun add_additional_metadata<T, Value: store>(
_: &CoinManagerMetadataCap<T>,
manager: &mut CoinManager<T>,
value: Value,
) {
df::add(&mut manager.id, ADDITIONAL_METADATA_NAME, value);
}
pub renounce_metadata_ownership
An irreversible action renouncing manager ownership which can be called if you hold the CoinManagerMetadataCap.
This action provides Coin holders with some assurances if called, namely that there will
not be any changes to the metadata from this point onward.
public fun renounce_metadata_ownership<T>(cap: iota::coin_manager::CoinManagerMetadataCap<T>, manager: &mut iota::coin_manager::CoinManager<T>)
Implementation
public fun renounce_metadata_ownership<T>(
cap: CoinManagerMetadataCap<T>,
manager: &mut CoinManager<T>,
) {
// Deleting the Cap
let CoinManagerMetadataCap { id } = cap;
object::delete(id);
// Setting ownership renounced to true
manager.metadata_immutable = true;
event::emit(MetadataOwnershipRenounced {
coin_name: type_name::into_string(type_name::get<T>()),
});
}
pub replace_additional_metadata
Option to replace an additional metadata object to the manager. Can contain whatever you need in terms of additional metadata as a object.
public fun replace_additional_metadata<T, Value: store, OldValue: store>(_: &iota::coin_manager::CoinManagerMetadataCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, value: Value): OldValue
Implementation
public fun replace_additional_metadata<T, Value: store, OldValue: store>(
: &CoinManagerMetadataCap<T>,
manager: &mut CoinManager<T>,
value: Value,
): OldValue {
assert!(df::exists(&manager.id, ADDITIONAL_METADATA_NAME), EAdditionalMetadataDoesNotExist);
let old_value = df::remove<vector<u8>, OldValue>(&mut manager.id, ADDITIONAL_METADATA_NAME);
df::add(&mut manager.id, ADDITIONAL_METADATA_NAME, value);
old_value
}
pub update_description
Update the description of the coin in the CoinMetadata.
public fun update_description<T>(_: &iota::coin_manager::CoinManagerMetadataCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, description: std::string::String)
Implementation
public fun update_description<T>(
_: &CoinManagerMetadataCap<T>,
manager: &mut CoinManager<T>,
description: string::String,
) {
coin::update_description(
&manager.treasury_cap,
option::borrow_mut(&mut manager.metadata),
description,
)
}
pub update_icon_url
Update the url of the coin in the CoinMetadata.
public fun update_icon_url<T>(_: &iota::coin_manager::CoinManagerMetadataCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, url: std::ascii::String)
Implementation
public fun update_icon_url<T>(
_: &CoinManagerMetadataCap<T>,
manager: &mut CoinManager<T>,
url: ascii::String,
) {
coin::update_icon_url(&manager.treasury_cap, option::borrow_mut(&mut manager.metadata), url)
}
pub update_name
Update the name of the coin in the CoinMetadata.
public fun update_name<T>(_: &iota::coin_manager::CoinManagerMetadataCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, name: std::string::String)
Implementation
public fun update_name<T>(
_: &CoinManagerMetadataCap<T>,
manager: &mut CoinManager<T>,
name: string::String,
) {
coin::update_name(&manager.treasury_cap, option::borrow_mut(&mut manager.metadata), name)
}
pub update_symbol
Update the symbol of the coin in the CoinMetadata.
public fun update_symbol<T>(_: &iota::coin_manager::CoinManagerMetadataCap<T>, manager: &mut iota::coin_manager::CoinManager<T>, symbol: std::ascii::String)
Implementation
public fun update_symbol<T>(
_: &CoinManagerMetadataCap<T>,
manager: &mut CoinManager<T>,
symbol: ascii::String,
) {
coin::update_symbol(&manager.treasury_cap, option::borrow_mut(&mut manager.metadata), symbol)
}
struct ImmutableCoinMetadata
The immutable version of CoinMetadata, used in case of migrating from frozen objects
to a CoinManager holding the metadata.
public struct ImmutableCoinMetadata<phantom T> has store
Fields
decimals: u8Number of decimal places the coin uses. A coin with
valueN anddecimalsD should be shown as N / 10^D E.g., a coin withvalue7002 and decimals 3 should be displayed as 7.002 This is metadata for display usage only.name: std::string::StringName for the token.
symbol: std::ascii::StringSymbol for the token.
description: std::string::StringDescription of the token.
icon_url: std::option::Option<iota::url::Url>URL for the token logo.
struct CoinManaged
Event triggered once Coin ownership is transferred to a new CoinManager.
public struct CoinManaged has copy, drop
Fields
coin_name: std::ascii::String
struct TreasuryOwnershipRenounced
Event triggered if the ownership of the treasury part of a CoinManager is renounced.
public struct TreasuryOwnershipRenounced has copy, drop
Fields
coin_name: std::ascii::String
struct MetadataOwnershipRenounced
Event triggered if the ownership of the metadata part of a CoinManager is renounced.
public struct MetadataOwnershipRenounced has copy, drop
Fields
coin_name: std::ascii::String
Constants
err EMaximumSupplyReached
The error returned when the maximum supply reached.
const EMaximumSupplyReached: u64 = 0;
err EMaximumSupplyAlreadySet
The error returned if an attempt is made to change the maximum supply after setting it.
const EMaximumSupplyAlreadySet: u64 = 1;
err EMaximumSupplyLowerThanTotalSupply
The error returned if an attempt is made to change the maximum supply that is lower than the total supply.
const EMaximumSupplyLowerThanTotalSupply: u64 = 2;
err EMaximumSupplyHigherThanPossible
The error returned if an attempt is made to change the maximum supply that is higher than the maximum possible supply.
const EMaximumSupplyHigherThanPossible: u64 = 3;
err EAdditionalMetadataDoesNotExist
The error returned if you try to edit nonexisting additional metadata.
const EAdditionalMetadataDoesNotExist: u64 = 4;
const MAX_SUPPLY
The maximum supply supported by CoinManager.
const MAX_SUPPLY: u64 = 18446744073709551614;
const ADDITIONAL_METADATA_NAME
The name of the related additional metadata dynamic field.
const ADDITIONAL_METADATA_NAME: vector<u8> = vector[97, 100, 100, 105, 116, 105, 111, 110, 97, 108, 95, 109, 101, 116, 97, 100, 97, 116, 97];