Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions creator-keys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ pub struct QuoteResponse {
pub total_amount: i128,
}

/// Shared result type for read-only quote methods.
pub type QuoteViewResult = Result<QuoteResponse, ContractError>;

/// Stable protocol state version for read-only consumers.
///
/// Bump this value only when externally consumed protocol state semantics change.
Expand Down Expand Up @@ -182,6 +185,17 @@ pub fn read_creator_profile(env: &Env, creator: &Address) -> Option<CreatorProfi
.get::<DataKey, CreatorProfile>(&key)
}

/// Reads a registered creator profile, returning an error when the creator is missing.
///
/// Use this helper for methods that require an existing creator and should return
/// a structured contract error instead of a default value.
pub fn read_registered_creator_profile(
env: &Env,
creator: &Address,
) -> Result<CreatorProfile, ContractError> {
read_creator_profile(env, creator).ok_or(ContractError::NotRegistered)
}

/// Reads the key balance (supply) for a creator, returning `0` for unregistered creators.
///
/// Use this helper wherever repeated key balance read logic is needed to keep
Expand All @@ -200,7 +214,7 @@ fn checked_format_quote_response(
creator_fee: i128,
protocol_fee: i128,
is_buy: bool,
) -> Result<QuoteResponse, ContractError> {
) -> QuoteViewResult {
let fees = creator_fee
.checked_add(protocol_fee)
.ok_or(ContractError::Overflow)?;
Expand Down Expand Up @@ -280,8 +294,7 @@ impl CreatorKeysContract {
return Err(ContractError::InsufficientPayment);
}

let mut profile: CreatorProfile =
read_creator_profile(&env, &creator).ok_or(ContractError::NotRegistered)?;
let mut profile: CreatorProfile = read_registered_creator_profile(&env, &creator)?;

let balance_key = DataKey::KeyBalance(creator.clone(), buyer.clone());
let current_balance: u32 = env.storage().persistent().get(&balance_key).unwrap_or(0);
Expand Down Expand Up @@ -317,8 +330,7 @@ impl CreatorKeysContract {
pub fn sell_key(env: Env, creator: Address, seller: Address) -> Result<u32, ContractError> {
seller.require_auth();

let mut profile: CreatorProfile =
read_creator_profile(&env, &creator).ok_or(ContractError::NotRegistered)?;
let mut profile: CreatorProfile = read_registered_creator_profile(&env, &creator)?;

let balance_key = DataKey::KeyBalance(creator.clone(), seller);
let current_balance: u32 = env.storage().persistent().get(&balance_key).unwrap_or(0);
Expand Down Expand Up @@ -377,7 +389,7 @@ impl CreatorKeysContract {
}

pub fn get_creator(env: Env, creator: Address) -> Result<CreatorProfile, ContractError> {
read_creator_profile(&env, &creator).ok_or(ContractError::NotRegistered)
read_registered_creator_profile(&env, &creator)
}

/// Read-only view: returns stable creator details.
Expand Down Expand Up @@ -422,6 +434,14 @@ impl CreatorKeysContract {
read_key_balance(&env, &creator)
}

/// Read-only view: returns the current supply for a registered creator.
///
/// Fails with [`ContractError::NotRegistered`] if the creator does not exist.
pub fn get_creator_supply(env: Env, creator: Address) -> Result<u32, ContractError> {
let profile = read_registered_creator_profile(&env, &creator)?;
Ok(profile.supply)
}

/// Read-only view: returns the number of unique holders for a creator.
///
/// Returns `0` if the creator is not registered, avoiding panics for
Expand All @@ -445,7 +465,7 @@ impl CreatorKeysContract {
/// Fails with [`ContractError::NotRegistered`] if the creator is not registered.
/// Reuses current creator storage access patterns.
pub fn get_creator_fee_recipient(env: Env, creator: Address) -> Result<Address, ContractError> {
let profile = read_creator_profile(&env, &creator).ok_or(ContractError::NotRegistered)?;
let profile = read_registered_creator_profile(&env, &creator)?;
Ok(profile.fee_recipient)
}

Expand Down Expand Up @@ -543,7 +563,7 @@ impl CreatorKeysContract {
/// config has been set. Use this method for indexers and read-only callers that need
/// a non-optional result.
pub fn get_creator_fee_config(env: Env, creator: Address) -> CreatorFeeView {
let is_registered = read_creator_profile(&env, &creator).is_some();
let is_registered = read_registered_creator_profile(&env, &creator).is_ok();

if !is_registered {
return CreatorFeeView {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"generators": {
"address": 2,
"nonce": 0
},
"auth": [
[],
[]
],
"ledger": {
"protocol_version": 22,
"sequence_number": 0,
"timestamp": 0,
"network_id": "0000000000000000000000000000000000000000000000000000000000000000",
"base_reserve": 0,
"min_persistent_entry_ttl": 4096,
"min_temp_entry_ttl": 16,
"max_entry_ttl": 6312000,
"ledger_entries": [
[
{
"contract_data": {
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
"key": "ledger_key_contract_instance",
"durability": "persistent"
}
},
[
{
"last_modified_ledger_seq": 0,
"data": {
"contract_data": {
"ext": "v0",
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
"key": "ledger_key_contract_instance",
"durability": "persistent",
"val": {
"contract_instance": {
"executable": {
"wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"storage": null
}
}
}
},
"ext": "v0"
},
4095
]
],
[
{
"contract_code": {
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
},
[
{
"last_modified_ledger_seq": 0,
"data": {
"contract_code": {
"ext": "v0",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"code": ""
}
},
"ext": "v0"
},
4095
]
]
]
},
"events": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
{
"generators": {
"address": 2,
"nonce": 0
},
"auth": [
[],
[
[
"CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
{
"function": {
"contract_fn": {
"contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
"function_name": "register_creator",
"args": [
{
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
},
{
"string": "alice"
}
]
}
},
"sub_invocations": []
}
]
],
[],
[]
],
"ledger": {
"protocol_version": 22,
"sequence_number": 0,
"timestamp": 0,
"network_id": "0000000000000000000000000000000000000000000000000000000000000000",
"base_reserve": 0,
"min_persistent_entry_ttl": 4096,
"min_temp_entry_ttl": 16,
"max_entry_ttl": 6312000,
"ledger_entries": [
[
{
"contract_data": {
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
"key": {
"vec": [
{
"symbol": "Creator"
},
{
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
}
]
},
"durability": "persistent"
}
},
[
{
"last_modified_ledger_seq": 0,
"data": {
"contract_data": {
"ext": "v0",
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
"key": {
"vec": [
{
"symbol": "Creator"
},
{
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
}
]
},
"durability": "persistent",
"val": {
"map": [
{
"key": {
"symbol": "creator"
},
"val": {
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
}
},
{
"key": {
"symbol": "fee_recipient"
},
"val": {
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
}
},
{
"key": {
"symbol": "handle"
},
"val": {
"string": "alice"
}
},
{
"key": {
"symbol": "holder_count"
},
"val": {
"u32": 0
}
},
{
"key": {
"symbol": "supply"
},
"val": {
"u32": 0
}
}
]
}
}
},
"ext": "v0"
},
4095
]
],
[
{
"contract_data": {
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
"key": "ledger_key_contract_instance",
"durability": "persistent"
}
},
[
{
"last_modified_ledger_seq": 0,
"data": {
"contract_data": {
"ext": "v0",
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
"key": "ledger_key_contract_instance",
"durability": "persistent",
"val": {
"contract_instance": {
"executable": {
"wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"storage": null
}
}
}
},
"ext": "v0"
},
4095
]
],
[
{
"contract_data": {
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
"key": {
"ledger_key_nonce": {
"nonce": 801925984706572462
}
},
"durability": "temporary"
}
},
[
{
"last_modified_ledger_seq": 0,
"data": {
"contract_data": {
"ext": "v0",
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
"key": {
"ledger_key_nonce": {
"nonce": 801925984706572462
}
},
"durability": "temporary",
"val": "void"
}
},
"ext": "v0"
},
6311999
]
],
[
{
"contract_code": {
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
},
[
{
"last_modified_ledger_seq": 0,
"data": {
"contract_code": {
"ext": "v0",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"code": ""
}
},
"ext": "v0"
},
4095
]
]
]
},
"events": []
}
Loading
Loading