@@ -5,9 +5,9 @@ use std::collections::HashSet;
55use crate :: asset_registry:: { AssetId , AssetRegistry } ;
66use acropolis_common:: {
77 queries:: assets:: { AssetHistory , PolicyAssets } ,
8- Address , AddressDelta , AssetAddressEntry , AssetInfoRecord , AssetMetadataStandard ,
9- AssetMintRecord , AssetName , Datum , Lovelace , NativeAssetsDelta , PolicyAsset , PolicyId ,
10- ShelleyAddress , TxIdentifier , TxUTxODeltas ,
8+ Address , AddressDelta , AssetAddressEntry , AssetInfoRecord , AssetMetadata ,
9+ AssetMetadataStandard , AssetMintRecord , AssetName , Datum , Lovelace , NativeAssets ,
10+ NativeAssetsDelta , PolicyAsset , PolicyId , ShelleyAddress , TxIdentifier , TxUTxODeltas ,
1111} ;
1212use anyhow:: Result ;
1313use imbl:: { HashMap , Vector } ;
@@ -143,8 +143,8 @@ impl State {
143143 // Overwrite asset metadata if an associated CIP68 reference token is found
144144 if let Some ( ref_info) = self . resolve_cip68_metadata ( asset_id, registry) {
145145 if let Some ( info_mut) = info. as_mut ( ) {
146- info_mut. onchain_metadata = ref_info. onchain_metadata ;
147- info_mut. metadata_standard = ref_info. metadata_standard ;
146+ info_mut. metadata . cip68_metadata = ref_info. metadata . cip68_metadata ;
147+ info_mut. metadata . cip68_version = ref_info. metadata . cip68_version ;
148148 } else {
149149 info = Some ( ref_info) ;
150150 }
@@ -240,6 +240,44 @@ impl State {
240240 Ok ( Some ( result) )
241241 }
242242
243+ pub fn get_assets_metadata (
244+ & self ,
245+ assets : & NativeAssets ,
246+ registry : & AssetRegistry ,
247+ ) -> Result < Option < Vec < AssetMetadata > > > {
248+ if !self . config . store_info || !self . config . store_assets {
249+ return Err ( anyhow:: anyhow!( "asset info storage disabled in config" ) ) ;
250+ }
251+
252+ let mut out = Vec :: new ( ) ;
253+
254+ for ( policy_id, policy_assets) in assets {
255+ for asset in policy_assets {
256+ let asset_id = match registry. lookup_id ( policy_id, & asset. name ) {
257+ Some ( id) => id,
258+ None => {
259+ return Ok ( None ) ;
260+ }
261+ } ;
262+
263+ let info = match self . info . as_ref ( ) . and_then ( |map| map. get ( & asset_id) ) {
264+ Some ( rec) => rec,
265+ None => {
266+ return Err ( anyhow:: anyhow!(
267+ "asset info missing in state for {}:{}" ,
268+ hex:: encode( policy_id) ,
269+ hex:: encode( asset. name. as_slice( ) )
270+ ) ) ;
271+ }
272+ } ;
273+
274+ out. push ( info. metadata . clone ( ) ) ;
275+ }
276+ }
277+
278+ Ok ( Some ( out) )
279+ }
280+
243281 pub fn tick ( & self ) -> Result < ( ) > {
244282 if let Some ( supply) = & self . supply {
245283 self . log_assets ( supply. len ( ) ) ;
@@ -312,8 +350,12 @@ impl State {
312350 . or_insert ( AssetInfoRecord {
313351 initial_mint_tx : * tx_identifier,
314352 mint_or_burn_count : 1 ,
315- onchain_metadata : None ,
316- metadata_standard : None ,
353+ metadata : AssetMetadata {
354+ cip25_metadata : None ,
355+ cip25_version : None ,
356+ cip68_metadata : None ,
357+ cip68_version : None ,
358+ } ,
317359 } ) ;
318360 }
319361
@@ -525,8 +567,8 @@ impl State {
525567 if let Some ( asset_id) = registry. lookup_id ( & policy_id, & asset_name) {
526568 if let Ok ( metadata_raw) = serde_cbor:: to_vec ( & metadata_val) {
527569 if let Some ( record) = info_map. get_mut ( & asset_id) {
528- record. onchain_metadata = Some ( metadata_raw) ;
529- record. metadata_standard = Some ( standard) ;
570+ record. metadata . cip25_metadata = Some ( metadata_raw) ;
571+ record. metadata . cip25_version = Some ( standard) ;
530572 }
531573 }
532574 }
@@ -554,6 +596,21 @@ impl State {
554596 continue ;
555597 } ;
556598
599+ let mut cip68_version = None ;
600+
601+ if let Ok ( serde_cbor:: Value :: Map ( m) ) =
602+ serde_cbor:: from_slice :: < serde_cbor:: Value > ( blob)
603+ {
604+ let version_key = serde_cbor:: Value :: Text ( "version" . to_string ( ) ) ;
605+
606+ if let Some ( serde_cbor:: Value :: Text ( ver) ) = m. get ( & version_key) {
607+ cip68_version = match ver. as_str ( ) {
608+ "2.0" => Some ( AssetMetadataStandard :: CIP68v2 ) ,
609+ _ => Some ( AssetMetadataStandard :: CIP68v1 ) ,
610+ } ;
611+ }
612+ }
613+
557614 for ( policy_id, native_assets) in & output. value . assets {
558615 for asset in native_assets {
559616 let name = & asset. name ;
@@ -568,7 +625,8 @@ impl State {
568625 if let Some ( record) =
569626 new_info. as_mut ( ) . and_then ( |m| m. get_mut ( & asset_id) )
570627 {
571- record. onchain_metadata = Some ( blob. clone ( ) ) ;
628+ record. metadata . cip68_metadata = Some ( blob. clone ( ) ) ;
629+ record. metadata . cip68_version = cip68_version;
572630 }
573631 }
574632 None => {
@@ -607,8 +665,8 @@ impl State {
607665 match label {
608666 CIP68_LABEL_100 => self . info . as_ref ( ) ?. get ( asset_id) . cloned ( ) . map ( |mut rec| {
609667 // Hide metadata on the reference itself (Per Blockfrost spec)
610- rec. onchain_metadata = None ;
611- rec. metadata_standard = None ;
668+ rec. metadata . cip68_metadata = None ;
669+ rec. metadata . cip68_version = None ;
612670 rec
613671 } ) ,
614672
@@ -998,10 +1056,10 @@ mod tests {
9981056 let record = info. get ( & asset_id) . unwrap ( ) ;
9991057
10001058 // Onchain metadata has been set
1001- assert ! ( record. onchain_metadata . is_some( ) ) ;
1059+ assert ! ( record. metadata . cip25_metadata . is_some( ) ) ;
10021060 // Metadata standard defaults to v1 if not present in map
10031061 assert_eq ! (
1004- record. metadata_standard ,
1062+ record. metadata . cip25_version ,
10051063 Some ( AssetMetadataStandard :: CIP25v1 )
10061064 ) ;
10071065 }
@@ -1028,10 +1086,10 @@ mod tests {
10281086 let record = info. get ( & asset_id) . unwrap ( ) ;
10291087
10301088 // Onchain metadata has been set
1031- assert ! ( record. onchain_metadata . is_some( ) ) ;
1089+ assert ! ( record. metadata . cip25_metadata . is_some( ) ) ;
10321090 // Metadata standard set to v2 when present in map
10331091 assert_eq ! (
1034- record. metadata_standard ,
1092+ record. metadata . cip25_version ,
10351093 Some ( AssetMetadataStandard :: CIP25v2 )
10361094 ) ;
10371095 }
@@ -1059,7 +1117,7 @@ mod tests {
10591117
10601118 // Metadata for known asset unchanged by unknown asset
10611119 assert ! (
1062- record. onchain_metadata . is_none( ) ,
1120+ record. metadata . cip25_metadata . is_none( ) ,
10631121 "unknown asset should not update records"
10641122 ) ;
10651123 }
@@ -1085,12 +1143,12 @@ mod tests {
10851143
10861144 // Metadata not set when CBOR is invalid
10871145 assert ! (
1088- record. onchain_metadata . is_none( ) ,
1146+ record. metadata . cip25_metadata . is_none( ) ,
10891147 "invalid CBOR should be ignored"
10901148 ) ;
10911149 // Metadata standard not set when CBOR is invalid
10921150 assert ! (
1093- record. metadata_standard . is_none( ) ,
1151+ record. metadata . cip25_version . is_none( ) ,
10941152 "invalid CBOR should not set a standard"
10951153 ) ;
10961154 }
@@ -1124,7 +1182,7 @@ mod tests {
11241182 let record = info. get ( & reference_id) . expect ( "record should exist" ) ;
11251183
11261184 // Onchain metadata set when asset already exists and TxOutput with inline datum is processed
1127- assert_eq ! ( record. onchain_metadata , Some ( datum_blob) ) ;
1185+ assert_eq ! ( record. metadata . cip68_metadata , Some ( datum_blob) ) ;
11281186 }
11291187
11301188 #[ test]
@@ -1156,7 +1214,7 @@ mod tests {
11561214 let record = info. get ( & normal_id) . expect ( "non reference asset should exist" ) ;
11571215
11581216 // Onchain metadata not updated for non reference asset
1159- assert_eq ! ( record. onchain_metadata , None ) ;
1217+ assert_eq ! ( record. metadata . cip68_metadata , None ) ;
11601218 }
11611219
11621220 #[ test]
@@ -1223,7 +1281,7 @@ mod tests {
12231281
12241282 // Metadata not populated for inputs or outputs without inline datum
12251283 assert ! (
1226- record. onchain_metadata . is_none( ) ,
1284+ record. metadata . cip68_metadata . is_none( ) ,
12271285 "inputs and outputs without datums should both be ignored"
12281286 ) ;
12291287 }
@@ -1244,8 +1302,8 @@ mod tests {
12441302
12451303 let mut info = state. info . take ( ) . unwrap ( ) ;
12461304 let rec = info. get_mut ( & ref_id) . unwrap ( ) ;
1247- rec. onchain_metadata = Some ( vec ! [ 1 , 2 , 3 ] ) ;
1248- rec. metadata_standard = Some ( AssetMetadataStandard :: CIP68v1 ) ;
1305+ rec. metadata . cip68_metadata = Some ( vec ! [ 1 , 2 , 3 ] ) ;
1306+ rec. metadata . cip68_version = Some ( AssetMetadataStandard :: CIP68v1 ) ;
12491307 state. info = Some ( info) ;
12501308
12511309 state. supply = Some ( imbl:: HashMap :: new ( ) ) ;
@@ -1257,59 +1315,9 @@ mod tests {
12571315 // Supply unchanged
12581316 assert_eq ! ( supply, 42 ) ;
12591317 // Metadata removed for reference asset
1260- assert ! ( rec. onchain_metadata . is_none( ) ) ;
1318+ assert ! ( rec. metadata . cip68_metadata . is_none( ) ) ;
12611319 // Metadata standard removed for reference asset
1262- assert ! ( rec. metadata_standard. is_none( ) ) ;
1263- }
1264-
1265- #[ test]
1266- fn resolve_cip68_metadata_overwrites_cip25_user_token_metadata ( ) {
1267- let mut registry = AssetRegistry :: new ( ) ;
1268- let policy_id: PolicyId = [ 10u8 ; 28 ] ;
1269-
1270- let user_name = AssetName :: new ( & [ 0x00 , 0x0d , 0xe1 , 0x40 , 0xaa ] ) . unwrap ( ) ;
1271- let user_id = registry. get_or_insert ( policy_id, user_name) ;
1272-
1273- let mut ref_bytes = user_name. as_slice ( ) . to_vec ( ) ;
1274- ref_bytes[ 0 ..4 ] . copy_from_slice ( & [ 0x00 , 0x06 , 0x43 , 0xb0 ] ) ;
1275- let ref_name = AssetName :: new ( & ref_bytes) . unwrap ( ) ;
1276- let ref_id = registry. get_or_insert ( policy_id, ref_name) ;
1277-
1278- let mut state = State :: new ( AssetsStorageConfig {
1279- store_info : true ,
1280- store_assets : true ,
1281- ..Default :: default ( )
1282- } ) ;
1283- let mut info_map = imbl:: HashMap :: new ( ) ;
1284-
1285- let user_record = AssetInfoRecord {
1286- onchain_metadata : Some ( vec ! [ 1 , 2 , 3 ] ) ,
1287- metadata_standard : Some ( AssetMetadataStandard :: CIP25v1 ) ,
1288- ..Default :: default ( )
1289- } ;
1290- info_map. insert ( user_id, user_record) ;
1291-
1292- let ref_record = AssetInfoRecord {
1293- onchain_metadata : Some ( vec ! [ 9 , 9 , 9 ] ) ,
1294- metadata_standard : Some ( AssetMetadataStandard :: CIP68v2 ) ,
1295- ..Default :: default ( )
1296- } ;
1297- info_map. insert ( ref_id, ref_record) ;
1298-
1299- state. info = Some ( info_map) ;
1300-
1301- state. supply = Some ( imbl:: HashMap :: new ( ) ) ;
1302- state. supply . as_mut ( ) . unwrap ( ) . insert ( user_id, 100 ) ;
1303-
1304- let result = state. get_asset_info ( & user_id, & registry) . unwrap ( ) . unwrap ( ) ;
1305- let ( supply, rec) = result;
1306-
1307- // User asset supply unchanged
1308- assert_eq ! ( supply, 100 ) ;
1309- // User asset metadata overwritten with reference token metadata
1310- assert_eq ! ( rec. onchain_metadata, Some ( vec![ 9 , 9 , 9 ] ) ) ;
1311- // User asset metadata standard overwritten with reference token metadata standard
1312- assert_eq ! ( rec. metadata_standard, Some ( AssetMetadataStandard :: CIP68v2 ) ) ;
1320+ assert ! ( rec. metadata. cip68_version. is_none( ) ) ;
13131321 }
13141322
13151323 #[ test]
0 commit comments