Skip to content

Commit

Permalink
fix(dan): refactor nft address parse
Browse files Browse the repository at this point in the history
  • Loading branch information
therealdannzor committed Sep 4, 2024
1 parent 0f4679e commit 8dbaee2
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 90 deletions.
56 changes: 17 additions & 39 deletions dan_layer/engine_types/src/substate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,10 @@ use tari_bor::{decode, decode_exact, encode, BorError};
use tari_common_types::types::FixedHash;
use tari_template_lib::{
models::{
ComponentAddress,
NonFungibleAddress,
NonFungibleIndexAddress,
ObjectKey,
ResourceAddress,
UnclaimedConfidentialOutputAddress,
VaultId,
ComponentAddress, NonFungibleAddress, NonFungibleIndexAddress, ObjectKey, ResourceAddress,
UnclaimedConfidentialOutputAddress, VaultId,
},
prelude::{NonFungibleId, PUBLIC_IDENTITY_RESOURCE_ADDRESS},
prelude::PUBLIC_IDENTITY_RESOURCE_ADDRESS,
Hash,
};
#[cfg(feature = "ts")]
Expand Down Expand Up @@ -152,14 +147,14 @@ impl SubstateId {
/// Returns true for any substate that has is "versionable" i.e. can have a version > 0, otherwise false.
pub fn is_versioned(&self) -> bool {
match self {
SubstateId::Component(_) |
SubstateId::Resource(_) |
SubstateId::Vault(_) |
SubstateId::NonFungibleIndex(_) |
SubstateId::NonFungible(_) => true,
SubstateId::UnclaimedConfidentialOutput(_) |
SubstateId::TransactionReceipt(_) |
SubstateId::FeeClaim(_) => false,
SubstateId::Component(_)
| SubstateId::Resource(_)
| SubstateId::Vault(_)
| SubstateId::NonFungibleIndex(_)
| SubstateId::NonFungible(_) => true,
SubstateId::UnclaimedConfidentialOutput(_)
| SubstateId::TransactionReceipt(_)
| SubstateId::FeeClaim(_) => false,
}
}

Expand Down Expand Up @@ -351,31 +346,14 @@ impl FromStr for SubstateId {
Ok(SubstateId::Component(addr))
},
Some(("resource", addr)) => {
if addr.split_once('_').is_none() {
// resource_xxxxx
let addr = ResourceAddress::from_hex(addr).map_err(|_| InvalidSubstateIdFormat(s.to_string()))?;
return Ok(SubstateId::Resource(addr));
}
Err(InvalidSubstateIdFormat("Missing resource address".to_string()))
// resource_xxxxx
let addr = ResourceAddress::from_hex(addr).map_err(|_| InvalidSubstateIdFormat(s.to_string()))?;
Ok(SubstateId::Resource(addr))
},
Some(("nft", rest)) => {
// nft_{resource_addr}_{id_type}_{id}
let (resource, nft_rest) = rest
.split_once('_')
.ok_or_else(|| InvalidSubstateIdFormat(s.to_string()))?;

let resource_addr =
ResourceAddress::from_hex(resource).map_err(|_| InvalidSubstateIdFormat(s.to_string()))?;

let (id_type, id) = nft_rest
.split_once('_')
.ok_or_else(|| InvalidSubstateIdFormat(s.to_string()))?;

let nft_id = NonFungibleId::try_from_canonical_string(&format!("{id_type}_{id}"))
.map_err(|_| InvalidSubstateIdFormat(s.to_string()))?;

let full_addr = NonFungibleAddress::new(resource_addr, nft_id);
Ok(SubstateId::NonFungible(full_addr))
// nft_{resource_hex}_{id_type}_{id}
let addr = NonFungibleAddress::from_str(rest).map_err(|_| InvalidSubstateIdFormat(s.to_string()))?;
Ok(SubstateId::NonFungible(addr))
},
Some(("nftindex", rest)) => {
// nftindex_{resource_id}_{index}
Expand Down
62 changes: 11 additions & 51 deletions dan_layer/template_lib/src/models/non_fungible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,25 +133,7 @@ impl NonFungibleId {
}

pub fn try_from_canonical_string(s: &str) -> Result<Self, ParseNonFungibleIdError> {
let mut splitted = s.split('_');

// ideally wanted this method to receive `id_type` and `id` but since it is used elsewhere,
// this will keep it compatible with the rest of the code, so potentially doing the same token parsing
// again is easier
let id_type: &str;
if let Some(token) = splitted.next() {
id_type = token;
} else {
return Err(ParseNonFungibleIdError::InvalidFormat);
}

let id: &str;
if let Some(token) = splitted.next() {
id = token;
} else {
return Err(ParseNonFungibleIdError::InvalidFormat);
}

let (id_type, id) = s.split_once('_').ok_or(ParseNonFungibleIdError::InvalidFormat)?;
match id_type {
"uuid" => Ok(NonFungibleId::U256(
Hash::from_hex(id)
Expand Down Expand Up @@ -281,41 +263,19 @@ impl FromStr for NonFungibleAddress {
type Err = ParseNonFungibleAddressError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// the expected format is nft_{resource_hex}_{type}_{id}
let mut splitted = s.split('_');
// nft_{resource_hex}_{type}_{id}

if let Some(token) = splitted.next() {
if token != "nft" {
return Err(ParseNonFungibleAddressError::InvalidFormat);
}
} else {
return Err(ParseNonFungibleAddressError::InvalidFormat);
}
let rest = s.strip_prefix("nft_").unwrap_or(s);
let (resource, nft_rest) = rest
.split_once('_')
.ok_or(ParseNonFungibleAddressError::InvalidFormat)?;

let resource_addr: ResourceAddress;
if let Some(token) = splitted.next() {
resource_addr = ResourceAddress::from_str(token)
.map_err(|e| ParseNonFungibleAddressError::InvalidResource(e.to_string()))?;
} else {
return Err(ParseNonFungibleAddressError::InvalidFormat);
}

let id_type: &str;
if let Some(token) = splitted.next() {
id_type = token;
} else {
return Err(ParseNonFungibleAddressError::InvalidFormat);
}

let id: NonFungibleId;
if let Some(token) = splitted.next() {
id = NonFungibleId::try_from_canonical_string(&format!("{id_type}_{token}"))
.map_err(ParseNonFungibleAddressError::InvalidId)?;
} else {
return Err(ParseNonFungibleAddressError::InvalidFormat);
}
let resource_addr =
ResourceAddress::from_hex(resource).map_err(|_| ParseNonFungibleAddressError::InvalidFormat)?;
let nft_id = NonFungibleId::try_from_canonical_string(nft_rest)
.map_err(|_| ParseNonFungibleAddressError::InvalidFormat)?;

Ok(NonFungibleAddress::new(resource_addr, id))
Ok(NonFungibleAddress::new(resource_addr, nft_id))
}
}

Expand Down

0 comments on commit 8dbaee2

Please sign in to comment.