0x0::balance_manager
The BalanceManager is a shared object that holds all of the balances for different assets. A combination of BalanceManager
and
TradeProof
are passed into a pool to perform trades. A TradeProof
can be generated in two ways: by the
owner directly, or by any TradeCap
owner. The owner can generate a TradeProof
without the risk of
equivocation. The TradeCap
owner, due to it being an owned object, risks equivocation when generating
a TradeProof
. Generally, a high frequency trading engine will trade as the default owner.
BalanceManager
BalanceEvent
BalanceKey
TradeCap
TradeProof
new
balance
mint_trade_cap
revoke_trade_cap
generate_proof_as_owner
generate_proof_as_trader
deposit
withdraw
withdraw_all
validate_proof
owner
id
deposit_with_proof
withdraw_with_proof
delete
trader
validate_owner
validate_trader
use 0x1::type_name;
use 0x2::bag;
use 0x2::balance;
use 0x2::coin;
use 0x2::event;
use 0x2::object;
use 0x2::tx_context;
use 0x2::vec_set;
BalanceManager
A shared object that is passed into pools for placing orders.
struct BalanceManager has store, key
id: object::UID
owner: address
balances: bag::Bag
allow_listed: vec_set::VecSet<object::ID>
BalanceEvent
Event emitted when a deposit or withdrawal occurs.
struct BalanceEvent has copy, drop
balance_manager_id: object::ID
asset: type_name::TypeName
amount: u64
deposit: bool
BalanceKey
Balance identifier.
struct BalanceKey<T> has copy, drop, store
dummy_field: bool
TradeCap
Owners of a TradeCap
need to get a TradeProof
to trade across pools in a single PTB (drops after).
struct TradeCap has store, key
id: object::UID
balance_manager_id: object::ID
TradeProof
BalanceManager owner and TradeCap
owners can generate a TradeProof
.
TradeProof
is used to validate the balance_manager when trading on DeepBook.
struct TradeProof has drop
balance_manager_id: object::ID
trader: address
const EBalanceManagerBalanceTooLow: u64 = 3;
const EInvalidOwner: u64 = 0;
const EInvalidProof: u64 = 2;
const EInvalidTrader: u64 = 1;
const EMaxTradeCapsReached: u64 = 4;
const ETradeCapNotInList: u64 = 5;
const MAX_TRADE_CAPS: u64 = 1000;
new
public fun new(ctx: &mut tx_context::TxContext): balance_manager::BalanceManager
public fun new(ctx: &mut TxContext): BalanceManager {
BalanceManager {
id: object::new(ctx),
owner: ctx.sender(),
balances: bag::new(ctx),
allow_listed: vec_set::empty(),
}
}
balance
Returns the balance of a Coin in a balance_manager.
public fun balance<T>(balance_manager: &balance_manager::BalanceManager): u64
public fun balance<T>(balance_manager: &BalanceManager): u64 {
let key = BalanceKey<T> {};
if (!balance_manager.balances.contains(key)) {
0
} else {
let acc_balance: &Balance<T> = &balance_manager.balances[key];
acc_balance.value()
}
}
mint_trade_cap
Mint a TradeCap
, only owner can mint a TradeCap
.
public fun mint_trade_cap(balance_manager: &mut balance_manager::BalanceManager, ctx: &mut tx_context::TxContext): balance_manager::TradeCap
public fun mint_trade_cap(
balance_manager: &mut BalanceManager,
ctx: &mut TxContext,
): TradeCap {
balance_manager.validate_owner(ctx);
assert!(
balance_manager.allow_listed.size() < MAX_TRADE_CAPS,
EMaxTradeCapsReached,
);
let id = object::new(ctx);
balance_manager.allow_listed.insert(id.to_inner());
TradeCap {
id,
balance_manager_id: object::id(balance_manager),
}
}
revoke_trade_cap
Revoke a TradeCap
. Only the owner can revoke a TradeCap
.
public fun revoke_trade_cap(balance_manager: &mut balance_manager::BalanceManager, trade_cap_id: &object::ID, ctx: &tx_context::TxContext)
public fun revoke_trade_cap(
balance_manager: &mut BalanceManager,
trade_cap_id: &ID,
ctx: &TxContext,
) {
balance_manager.validate_owner(ctx);
assert!(
balance_manager.allow_listed.contains(trade_cap_id),
ETradeCapNotInList,
);
balance_manager.allow_listed.remove(trade_cap_id);
}
generate_proof_as_owner
Generate a TradeProof
by the owner. The owner does not require a capability
and can generate TradeProofs without the risk of equivocation.
public fun generate_proof_as_owner(balance_manager: &mut balance_manager::BalanceManager, ctx: &tx_context::TxContext): balance_manager::TradeProof
public fun generate_proof_as_owner(
balance_manager: &mut BalanceManager,
ctx: &TxContext,
): TradeProof {
balance_manager.validate_owner(ctx);
TradeProof {
balance_manager_id: object::id(balance_manager),
trader: ctx.sender(),
}
}
generate_proof_as_trader
Generate a TradeProof
with a TradeCap
.
Risk of equivocation since TradeCap
is an owned object.
public fun generate_proof_as_trader(balance_manager: &mut balance_manager::BalanceManager, trade_cap: &balance_manager::TradeCap, ctx: &tx_context::TxContext): balance_manager::TradeProof
public fun generate_proof_as_trader(
balance_manager: &mut BalanceManager,
trade_cap: &TradeCap,
ctx: &TxContext,
): TradeProof {
balance_manager.validate_trader(trade_cap);
TradeProof {
balance_manager_id: object::id(balance_manager),
trader: ctx.sender(),
}
}
deposit
Deposit funds to a balance_manager. Only owner can call this directly.
public fun deposit<T>(balance_manager: &mut balance_manager::BalanceManager, coin: coin::Coin<T>, ctx: &mut tx_context::TxContext)
public fun deposit<T>(
balance_manager: &mut BalanceManager,
coin: Coin<T>,
ctx: &mut TxContext,
) {
event::emit(BalanceEvent {
balance_manager_id: object::id(balance_manager),
asset: type_name::get<T>(),
amount: coin.value(),
deposit: true,
});
let proof = generate_proof_as_owner(balance_manager, ctx);
balance_manager.deposit_with_proof(&proof, coin.into_balance());
}
withdraw
Withdraw funds from a balance_manager. Only owner can call this directly. If withdraw_all is true, amount is ignored and full balance withdrawn. If withdraw_all is false, withdraw_amount will be withdrawn.
public fun withdraw<T>(balance_manager: &mut balance_manager::BalanceManager, withdraw_amount: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
public fun withdraw<T>(
balance_manager: &mut BalanceManager,
withdraw_amount: u64,
ctx: &mut TxContext,
): Coin<T> {
let proof = generate_proof_as_owner(balance_manager, ctx);
let coin = balance_manager
.withdraw_with_proof(&proof, withdraw_amount, false)
.into_coin(ctx);
event::emit(BalanceEvent {
balance_manager_id: object::id(balance_manager),
asset: type_name::get<T>(),
amount: coin.value(),
deposit: false,
});
coin
}
withdraw_all
public fun withdraw_all<T>(balance_manager: &mut balance_manager::BalanceManager, ctx: &mut tx_context::TxContext): coin::Coin<T>
public fun withdraw_all<T>(
balance_manager: &mut BalanceManager,
ctx: &mut TxContext,
): Coin<T> {
let proof = generate_proof_as_owner(balance_manager, ctx);
let coin = balance_manager
.withdraw_with_proof(&proof, 0, true)
.into_coin(ctx);
event::emit(BalanceEvent {
balance_manager_id: object::id(balance_manager),
asset: type_name::get<T>(),
amount: coin.value(),
deposit: false,
});
coin
}
validate_proof
public fun validate_proof(balance_manager: &balance_manager::BalanceManager, proof: &balance_manager::TradeProof)
public fun validate_proof(
balance_manager: &BalanceManager,
proof: &TradeProof,
) {
assert!(
object::id(balance_manager) == proof.balance_manager_id,
EInvalidProof,
);
}
owner
Returns the owner of the balance_manager.
public fun owner(balance_manager: &balance_manager::BalanceManager): address
public fun owner(balance_manager: &BalanceManager): address {
balance_manager.owner
}
id
Returns the owner of the balance_manager.
public fun id(balance_manager: &balance_manager::BalanceManager): object::ID
public fun id(balance_manager: &BalanceManager): ID {
balance_manager.id.to_inner()
}
deposit_with_proof
Deposit funds to a balance_manager. Pool will call this to deposit funds.
public(friend) fun deposit_with_proof<T>(balance_manager: &mut balance_manager::BalanceManager, proof: &balance_manager::TradeProof, to_deposit: balance::Balance<T>)
public(package) fun deposit_with_proof<T>(
balance_manager: &mut BalanceManager,
proof: &TradeProof,
to_deposit: Balance<T>,
) {
balance_manager.validate_proof(proof);
let key = BalanceKey<T> {};
if (balance_manager.balances.contains(key)) {
let balance: &mut Balance<T> = &mut balance_manager.balances[key];
balance.join(to_deposit);
} else {
balance_manager.balances.add(key, to_deposit);
}
}
withdraw_with_proof
Withdraw funds from a balance_manager. Pool will call this to withdraw funds.
public(friend) fun withdraw_with_proof<T>(balance_manager: &mut balance_manager::BalanceManager, proof: &balance_manager::TradeProof, withdraw_amount: u64, withdraw_all: bool): balance::Balance<T>
public(package) fun withdraw_with_proof<T>(
balance_manager: &mut BalanceManager,
proof: &TradeProof,
withdraw_amount: u64,
withdraw_all: bool,
): Balance<T> {
balance_manager.validate_proof(proof);
let key = BalanceKey<T> {};
let key_exists = balance_manager.balances.contains(key);
if (withdraw_all) {
if (key_exists) {
balance_manager.balances.remove(key)
} else {
balance::zero()
}
} else {
assert!(key_exists, EBalanceManagerBalanceTooLow);
let acc_balance: &mut Balance<T> = &mut balance_manager.balances[key];
let acc_value = acc_balance.value();
assert!(acc_value >= withdraw_amount, EBalanceManagerBalanceTooLow);
if (withdraw_amount == acc_value) {
balance_manager.balances.remove(key)
} else {
acc_balance.split(withdraw_amount)
}
}
}
delete
Deletes a balance_manager. This is used for deleting temporary balance_managers for direct swap with pool.
public(friend) fun delete(balance_manager: balance_manager::BalanceManager)
public(package) fun delete(balance_manager: BalanceManager) {
let BalanceManager {
id,
owner: _,
balances,
allow_listed: _,
} = balance_manager;
id.delete();
balances.destroy_empty();
}
trader
public(friend) fun trader(trade_proof: &balance_manager::TradeProof): address
public(package) fun trader(trade_proof: &TradeProof): address {
trade_proof.trader
}
validate_owner
fun validate_owner(balance_manager: &balance_manager::BalanceManager, ctx: &tx_context::TxContext)
fun validate_owner(balance_manager: &BalanceManager, ctx: &TxContext) {
assert!(ctx.sender() == balance_manager.owner(), EInvalidOwner);
}
validate_trader
fun validate_trader(balance_manager: &balance_manager::BalanceManager, trade_cap: &balance_manager::TradeCap)
fun validate_trader(balance_manager: &BalanceManager, trade_cap: &TradeCap) {
assert!(
balance_manager.allow_listed.contains(object::borrow_id(trade_cap)),
EInvalidTrader,
);
}