1use anyhow::{anyhow, Result};
2use mpl_token_metadata::types::{Creator, DataV2};
3use solana_sdk::pubkey::Pubkey;
4use std::str::FromStr;
5
6use crate::data::{NftCreator, NftData};
7
8pub fn convert_local_to_remote_data(local: NftData) -> Result<DataV2> {
9 let creators = local
10 .creators
11 .ok_or_else(|| anyhow!("No creators specified in json file!"))?
12 .iter()
13 .map(convert_creator)
14 .collect::<Result<Vec<Creator>>>()?;
15
16 let data = DataV2 {
17 name: local.name,
18 symbol: local.symbol,
19 uri: local.uri,
20 seller_fee_basis_points: local.seller_fee_basis_points,
21 creators: Some(creators),
22 collection: None,
23 uses: None,
24 };
25 Ok(data)
26}
27
28fn convert_creator(c: &NftCreator) -> Result<Creator> {
29 Ok(Creator {
30 address: Pubkey::from_str(&c.address)?,
31 verified: c.verified,
32 share: c.share,
33 })
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 fn make_creator(address: &str, verified: bool, share: u8) -> NftCreator {
41 NftCreator {
42 address: address.to_string(),
43 verified,
44 share,
45 }
46 }
47
48 fn make_nft_data(creators: Option<Vec<NftCreator>>) -> NftData {
49 NftData {
50 name: "Test NFT".to_string(),
51 symbol: "TNFT".to_string(),
52 uri: "https://example.com/nft.json".to_string(),
53 seller_fee_basis_points: 500,
54 creators,
55 }
56 }
57
58 #[test]
59 fn test_convert_local_to_remote_data_valid() {
60 let pubkey_str = "11111111111111111111111111111111";
61 let creators = vec![make_creator(pubkey_str, true, 100)];
62 let nft_data = make_nft_data(Some(creators));
63
64 let result = convert_local_to_remote_data(nft_data).unwrap();
65
66 assert_eq!(result.name, "Test NFT");
67 assert_eq!(result.symbol, "TNFT");
68 assert_eq!(result.uri, "https://example.com/nft.json");
69 assert_eq!(result.seller_fee_basis_points, 500);
70 assert!(result.collection.is_none());
71 assert!(result.uses.is_none());
72
73 let creators = result.creators.unwrap();
74 assert_eq!(creators.len(), 1);
75 assert_eq!(creators[0].address, Pubkey::from_str(pubkey_str).unwrap());
76 assert!(creators[0].verified);
77 assert_eq!(creators[0].share, 100);
78 }
79
80 #[test]
81 fn test_convert_local_to_remote_data_none_creators() {
82 let nft_data = make_nft_data(None);
83 let result = convert_local_to_remote_data(nft_data);
84 assert!(result.is_err());
85 }
86
87 #[test]
88 fn test_convert_local_to_remote_data_invalid_pubkey() {
89 let creators = vec![make_creator("not-a-pubkey", false, 100)];
90 let nft_data = make_nft_data(Some(creators));
91 let result = convert_local_to_remote_data(nft_data);
92 assert!(result.is_err());
93 }
94
95 #[test]
96 fn test_convert_local_to_remote_data_multiple_creators() {
97 let pubkey_str = "11111111111111111111111111111111";
98 let creators = vec![
99 make_creator(pubkey_str, true, 50),
100 make_creator(pubkey_str, false, 30),
101 make_creator(pubkey_str, true, 20),
102 ];
103 let nft_data = make_nft_data(Some(creators));
104
105 let result = convert_local_to_remote_data(nft_data).unwrap();
106 let creators = result.creators.unwrap();
107
108 assert_eq!(creators.len(), 3);
109
110 assert!(creators[0].verified);
111 assert_eq!(creators[0].share, 50);
112
113 assert!(!creators[1].verified);
114 assert_eq!(creators[1].share, 30);
115
116 assert!(creators[2].verified);
117 assert_eq!(creators[2].share, 20);
118 }
119}