Defines the Coin
type - platform wide representation of fungible
tokens and coins. Coin
can be described as a secure wrapper around
Balance
type.
- Resource
Coin
- Resource
TreasuryCap
- Struct
CurrencyCreated
- Constants
- Function
total_supply
- Function
treasury_into_supply
- Function
supply
- Function
supply_mut
- Function
value
- Function
balance
- Function
balance_mut
- Function
from_balance
- Function
into_balance
- Function
take
- Function
put
- Function
keep
- Function
join
- Function
join_vec
- Function
destroy_zero
- Function
zero
- Function
create_currency
- Function
mint
- Function
mint_balance
- Function
burn
- Function
mint_and_transfer
- Function
burn_
- Function
split_and_transfer
- Function
split
- Function
split_n_to_vec
- Function
split_n
- Function
split_vec
use 0x1::vector;
use 0x2::balance;
use 0x2::event;
use 0x2::object;
use 0x2::transfer;
use 0x2::tx_context;
use 0x2::types;
A coin of type T
worth value
. Transferable and storable
struct Coin<T> has store, key
Fields
-
id: object::UID
-
balance: balance::Balance<T>
Capability allowing the bearer to mint and burn
coins of type T
. Transferable
struct TreasuryCap<T> has store, key
Fields
-
id: object::UID
-
total_supply: balance::Supply<T>
Emitted when new currency is created through the create_currency
call.
Contains currency metadata for off-chain discovery. Type parameter T
matches the one in Coin<T>
struct CurrencyCreated<T> has copy, drop
Fields
-
decimals: u8
-
Number of decimal places the coin uses.
A coin with
value
N anddecimals
D should be shown as N / 10^D E.g., a coin withvalue
7002 and decimals 3 should be displayed as 7.002 This is metadata for display usage only.
For when trying to split a coin more times than its balance allows.
const ENotEnough: u64 = 2;
For when a type passed to create_supply is not a one-time witness.
const EBadWitness: u64 = 0;
For when invalid arguments are passed to a function.
const EInvalidArg: u64 = 1;
Return the total number of T
's in circulation.
public fun total_supply<T>(cap: &coin::TreasuryCap<T>): u64
Implementation
public fun total_supply<T>(cap: &TreasuryCap<T>): u64 {
balance::supply_value(&cap.total_supply)
}
Unwrap TreasuryCap
getting the Supply
.
Operation is irreversible. Supply cannot be converted into a TreasuryCap
due
to different security guarantees (TreasuryCap can be created only once for a type)
public fun treasury_into_supply<T>(treasury: coin::TreasuryCap<T>): balance::Supply<T>
Implementation
public fun treasury_into_supply<T>(treasury: TreasuryCap<T>): Supply<T> {
let TreasuryCap { id, total_supply } = treasury;
object::delete(id);
total_supply
}
Get immutable reference to the treasury's Supply
.
public fun supply<T>(treasury: &mut coin::TreasuryCap<T>): &balance::Supply<T>
Implementation
public fun supply<T>(treasury: &mut TreasuryCap<T>): &Supply<T> {
&treasury.total_supply
}
Get mutable reference to the treasury's Supply
.
public fun supply_mut<T>(treasury: &mut coin::TreasuryCap<T>): &mut balance::Supply<T>
Implementation
public fun supply_mut<T>(treasury: &mut TreasuryCap<T>): &mut Supply<T> {
&mut treasury.total_supply
}
Public getter for the coin's value
public fun value<T>(self: &coin::Coin<T>): u64
Implementation
public fun value<T>(self: &Coin<T>): u64 {
balance::value(&self.balance)
}
Get immutable reference to the balance of a coin.
public fun balance<T>(coin: &coin::Coin<T>): &balance::Balance<T>
Get a mutable reference to the balance of a coin.
public fun balance_mut<T>(coin: &mut coin::Coin<T>): &mut balance::Balance<T>
Implementation
public fun balance_mut<T>(coin: &mut Coin<T>): &mut Balance<T> {
&mut coin.balance
}
Wrap a balance into a Coin to make it transferable.
public fun from_balance<T>(balance: balance::Balance<T>, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun from_balance<T>(balance: Balance<T>, ctx: &mut TxContext): Coin<T> {
Coin { id: object::new(ctx), balance }
}
Destruct a Coin wrapper and keep the balance.
public fun into_balance<T>(coin: coin::Coin<T>): balance::Balance<T>
Implementation
public fun into_balance<T>(coin: Coin<T>): Balance<T> {
let Coin { id, balance } = coin;
object::delete(id);
balance
}
Take a Coin
worth of value
from Balance
.
Aborts if value > balance.value
public fun take<T>(balance: &mut balance::Balance<T>, value: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun take<T>(
balance: &mut Balance<T>, value: u64, ctx: &mut TxContext,
): Coin<T> {
Coin {
id: object::new(ctx),
balance: balance::split(balance, value)
}
}
Put a Coin<T>
to the Balance<T>
.
public fun put<T>(balance: &mut balance::Balance<T>, coin: coin::Coin<T>)
Implementation
public fun put<T>(balance: &mut Balance<T>, coin: Coin<T>) {
balance::join(balance, into_balance(coin));
}
Transfer c
to the sender of the current transaction
public fun keep<T>(c: coin::Coin<T>, ctx: &tx_context::TxContext)
Implementation
public fun keep<T>(c: Coin<T>, ctx: &TxContext) {
transfer::transfer(c, tx_context::sender(ctx))
}
Consume the coin c
and add its value to self
.
Aborts if c.value + self.value > U64_MAX
public fun join<T>(self: &mut coin::Coin<T>, c: coin::Coin<T>)
Implementation
public entry fun join<T>(self: &mut Coin<T>, c: Coin<T>) {
let Coin { id, balance } = c;
object::delete(id);
balance::join(&mut self.balance, balance);
}
Join everything in coins
with self
public fun join_vec<T>(self: &mut coin::Coin<T>, coins: vector<coin::Coin<T>>)
Implementation
public entry fun join_vec<T>(self: &mut Coin<T>, coins: vector<Coin<T>>) {
let i = 0;
let len = vector::length(&coins);
while (i < len) {
let coin = vector::remove(&mut coins, i);
join(self, coin);
i = i + 1
};
// safe because we've drained the vector
vector::destroy_empty(coins)
}
Destroy a coin with value zero
public fun destroy_zero<T>(c: coin::Coin<T>)
Implementation
public fun destroy_zero<T>(c: Coin<T>) {
let Coin { id, balance } = c;
object::delete(id);
balance::destroy_zero(balance)
}
Make any Coin with a zero value. Useful for placeholding bids/payments or preemptively making empty balances.
public fun zero<T>(ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun zero<T>(ctx: &mut TxContext): Coin<T> {
Coin { id: object::new(ctx), balance: balance::zero() }
}
Create a new currency type T
as and return the TreasuryCap
for
T
to the caller. Can only be called with a one-time-witness
type, ensuring that there's only one TreasuryCap
per T
.
public fun create_currency<T: drop>(witness: T, decimals: u8, ctx: &mut tx_context::TxContext): coin::TreasuryCap<T>
Implementation
public fun create_currency<T: drop>(
witness: T,
decimals: u8,
ctx: &mut TxContext
): TreasuryCap<T> {
// Make sure there's only one instance of the type T
assert!(sui::types::is_one_time_witness(&witness), EBadWitness);
// Emit Currency metadata as an event.
event::emit(CurrencyCreated<T> {
decimals
});
TreasuryCap {
id: object::new(ctx),
total_supply: balance::create_supply(witness)
}
}
Create a coin worth value
. and increase the total supply
in cap
accordingly.
public fun mint<T>(cap: &mut coin::TreasuryCap<T>, value: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun mint<T>(
cap: &mut TreasuryCap<T>, value: u64, ctx: &mut TxContext,
): Coin<T> {
Coin {
id: object::new(ctx),
balance: balance::increase_supply(&mut cap.total_supply, value)
}
}
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>(cap: &mut coin::TreasuryCap<T>, value: u64): balance::Balance<T>
Implementation
public fun mint_balance<T>(
cap: &mut TreasuryCap<T>, value: u64
): Balance<T> {
balance::increase_supply(&mut cap.total_supply, value)
}
Destroy the coin c
and decrease the total supply in cap
accordingly.
public fun burn<T>(cap: &mut coin::TreasuryCap<T>, c: coin::Coin<T>): u64
Implementation
public fun burn<T>(cap: &mut TreasuryCap<T>, c: Coin<T>): u64 {
let Coin { id, balance } = c;
object::delete(id);
balance::decrease_supply(&mut cap.total_supply, balance)
}
Mint amount
of Coin
and send it to recipient
. Invokes mint()
.
public fun mint_and_transfer<T>(c: &mut coin::TreasuryCap<T>, amount: u64, recipient: address, ctx: &mut tx_context::TxContext)
Implementation
public entry fun mint_and_transfer<T>(
c: &mut TreasuryCap<T>, amount: u64, recipient: address, ctx: &mut TxContext
) {
transfer::transfer(mint(c, amount, ctx), recipient)
}
Burn a Coin and reduce the total_supply. Invokes burn()
.
public fun burn_<T>(c: &mut coin::TreasuryCap<T>, coin: coin::Coin<T>)
Send amount
units of c
to recipient
Aborts with EVALUE
if amount
is greater than or equal to amount
public fun split_and_transfer<T>(c: &mut coin::Coin<T>, amount: u64, recipient: address, ctx: &mut tx_context::TxContext)
Implementation
public entry fun split_and_transfer<T>(
c: &mut Coin<T>, amount: u64, recipient: address, ctx: &mut TxContext
) {
transfer::transfer(take(&mut c.balance, amount, ctx), recipient)
}
Split coin self
to two coins, one with balance split_amount
,
and the remaining balance is left is self
.
public fun split<T>(self: &mut coin::Coin<T>, split_amount: u64, ctx: &mut tx_context::TxContext)
Implementation
public entry fun split<T>(self: &mut Coin<T>, split_amount: u64, ctx: &mut TxContext) {
transfer::transfer(
take(&mut self.balance, split_amount, ctx),
tx_context::sender(ctx)
)
}
Split coin self
into n
coins with equal balances. If the balance is
not evenly divisible by n
, the remainder is left in self
. Return
newly created coins.
public fun split_n_to_vec<T>(self: &mut coin::Coin<T>, n: u64, ctx: &mut tx_context::TxContext): vector<coin::Coin<T>>
Implementation
public fun split_n_to_vec<T>(self: &mut Coin<T>, n: u64, ctx: &mut TxContext): vector<Coin<T>> {
assert!(n > 0, EInvalidArg);
assert!(n <= balance::value(&self.balance), ENotEnough);
let vec = vector::empty<Coin<T>>();
let i = 0;
let split_amount = balance::value(&self.balance) / n;
while (i < n - 1) {
vector::push_back(&mut vec, take(&mut self.balance, split_amount, ctx));
i = i + 1;
};
vec
}
Split coin self
into n
coins with equal balances. If the balance is
not evenly divisible by n
, the remainder is left in self
.
public fun split_n<T>(self: &mut coin::Coin<T>, n: u64, ctx: &mut tx_context::TxContext)
Implementation
public entry fun split_n<T>(self: &mut Coin<T>, n: u64, ctx: &mut TxContext) {
let vec: vector<Coin<T>> = split_n_to_vec(self, n, ctx);
let i = 0;
let len = vector::length(&vec);
while (i < len) {
transfer::transfer(vector::pop_back(&mut vec), tx_context::sender(ctx));
i = i + 1;
};
vector::destroy_empty(vec);
}
Split coin self
into multiple coins, each with balance specified
in split_amounts
. Remaining balance is left in self
.
public fun split_vec<T>(self: &mut coin::Coin<T>, split_amounts: vector<u64>, ctx: &mut tx_context::TxContext)
Implementation
public entry fun split_vec<T>(self: &mut Coin<T>, split_amounts: vector<u64>, ctx: &mut TxContext) {
let i = 0;
let len = vector::length(&split_amounts);
while (i < len) {
split(self, *vector::borrow(&split_amounts, i), ctx);
i = i + 1;
};
}