Skip to content

Commit 14da70e

Browse files
Merge pull request #2025 from multiversx/fix-uris
fix uris for esdt_metadata_recreate and esdt_metadata_update
2 parents 41b5398 + c9231e0 commit 14da70e

File tree

5 files changed

+145
-40
lines changed

5 files changed

+145
-40
lines changed

framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ where
301301
new_attributes: &T,
302302
uris: ManagedVec<Env::Api, ManagedBuffer<Env::Api>>,
303303
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
304-
let tx = self
304+
let mut tx = self
305305
.wrapped_tx
306306
.payment(NotPayable)
307307
.raw_call(ESDT_METADATA_RECREATE_FUNC_NAME)
@@ -310,8 +310,18 @@ where
310310
.argument(&name)
311311
.argument(&royalties)
312312
.argument(&hash)
313-
.argument(&new_attributes)
314-
.argument(&uris);
313+
.argument(&new_attributes);
314+
315+
if uris.is_empty() {
316+
// at least one URI is required, so we push an empty one
317+
tx = tx.argument(&Empty);
318+
} else {
319+
// The API function has the last argument as variadic,
320+
// so we top-encode each and send as separate argument
321+
for uri in uris {
322+
tx = tx.argument(&uri);
323+
}
324+
}
315325

316326
tx.original_result()
317327
}
@@ -334,7 +344,7 @@ where
334344
new_attributes: &T,
335345
uris: ManagedVec<Env::Api, ManagedBuffer<Env::Api>>,
336346
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
337-
let tx = self
347+
let mut tx = self
338348
.wrapped_tx
339349
.payment(NotPayable)
340350
.raw_call(ESDT_METADATA_UPDATE_FUNC_NAME)
@@ -343,8 +353,18 @@ where
343353
.argument(&name)
344354
.argument(&royalties)
345355
.argument(&hash)
346-
.argument(&new_attributes)
347-
.argument(&uris);
356+
.argument(&new_attributes);
357+
358+
if uris.is_empty() {
359+
// at least one URI is required, so we push an empty one
360+
tx = tx.argument(&Empty);
361+
} else {
362+
// The API function has the last argument as variadic,
363+
// so we top-encode each and send as separate argument
364+
for uri in uris {
365+
tx = tx.argument(&uri);
366+
}
367+
}
348368

349369
tx.original_result()
350370
}

framework/snippets/src/interactor/interactor_sender.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ use crate::sdk::{data::transaction::Transaction, wallet::Wallet};
44
use log::debug;
55
use multiversx_sc_scenario::multiversx_sc::types::Address;
66
use multiversx_sdk::data::account::Account;
7-
use multiversx_sdk::gateway::{GatewayAsyncService, GetAccountRequest, GetAccountStorageRequest};
7+
use multiversx_sdk::data::esdt::EsdtBalance;
8+
use multiversx_sdk::gateway::{
9+
GatewayAsyncService, GetAccountEsdtTokensRequest, GetAccountRequest, GetAccountStorageRequest,
10+
};
811

912
use crate::InteractorBase;
1013

@@ -42,6 +45,13 @@ where
4245
.expect("failed to retrieve account")
4346
}
4447

48+
pub async fn get_account_esdt(&self, address: &Address) -> HashMap<String, EsdtBalance> {
49+
self.proxy
50+
.request(GetAccountEsdtTokensRequest::new(address))
51+
.await
52+
.expect("failed to retrieve account")
53+
}
54+
4555
pub(crate) async fn set_nonce_and_sign_tx(
4656
&mut self,
4757
sender_address: &Address,

sdk/core/src/data/esdt.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::collections::HashMap;
77
pub struct EsdtBalance {
88
pub token_identifier: String,
99
pub balance: String,
10+
pub uris: Vec<String>,
1011
}
1112

1213
// EsdtBalanceDataholds the esdt balance data

tools/interactor-system-func-calls/src/system_sc_interact.rs

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ mod system_sc_interact_cli;
22
mod system_sc_interact_config;
33
mod system_sc_interact_state;
44

5+
use std::collections::HashMap;
6+
57
use clap::Parser;
68
pub use system_sc_interact_cli::NftDummyAttributes;
79
pub use system_sc_interact_config::Config;
810
use system_sc_interact_state::State;
911

10-
use multiversx_sc_snippets::imports::*;
12+
use multiversx_sc_snippets::{
13+
imports::*,
14+
sdk::{data::esdt::EsdtBalance, utils::base64_decode},
15+
};
1116

1217
pub async fn system_sc_interact_cli() {
1318
env_logger::init();
@@ -131,7 +136,7 @@ pub async fn system_sc_interact_cli() {
131136
creation_epoch: 2u64,
132137
cool_factor: 3u8,
133138
},
134-
Vec::new(),
139+
&Vec::new(),
135140
)
136141
.await;
137142
},
@@ -746,12 +751,12 @@ impl SysFuncCallsInteract {
746751
royalties: u64,
747752
hash: &[u8],
748753
attributes: &T,
749-
uris: Vec<String>,
754+
uris: &[String],
750755
) -> u64 {
751756
println!("Minting NFT...");
752757

753758
let uris = uris
754-
.into_iter()
759+
.iter()
755760
.map(ManagedBuffer::from)
756761
.collect::<ManagedVec<StaticApi, ManagedBuffer<StaticApi>>>();
757762

@@ -860,11 +865,11 @@ impl SysFuncCallsInteract {
860865
.await;
861866
}
862867

863-
pub async fn set_new_uris(&mut self, token_id: &[u8], nonce: u64, new_uris: Vec<String>) {
868+
pub async fn set_new_uris(&mut self, token_id: &[u8], nonce: u64, new_uris: &[String]) {
864869
println!("Setting new uris for token {token_id:?} with nonce {nonce:?}...");
865870

866871
let uris = new_uris
867-
.into_iter()
872+
.iter()
868873
.map(ManagedBuffer::from)
869874
.collect::<ManagedVec<StaticApi, ManagedBuffer<StaticApi>>>();
870875

@@ -917,12 +922,12 @@ impl SysFuncCallsInteract {
917922
royalties: u64,
918923
hash: &[u8],
919924
new_attributes: &T,
920-
uris: Vec<String>,
925+
uris: &[String],
921926
) {
922927
println!("Recreating the token {token_id:?} with nonce {nonce:?} with new attributes...");
923928

924929
let uris = uris
925-
.into_iter()
930+
.iter()
926931
.map(ManagedBuffer::from)
927932
.collect::<ManagedVec<StaticApi, ManagedBuffer<StaticApi>>>();
928933

@@ -946,12 +951,12 @@ impl SysFuncCallsInteract {
946951
royalties: u64,
947952
hash: &[u8],
948953
new_attributes: &T,
949-
uris: Vec<String>,
954+
uris: &[String],
950955
) {
951956
println!("Updating the token {token_id:?} with nonce {nonce:?} with new attributes...");
952957

953958
let uris = uris
954-
.into_iter()
959+
.iter()
955960
.map(ManagedBuffer::from)
956961
.collect::<ManagedVec<StaticApi, ManagedBuffer<StaticApi>>>();
957962

@@ -965,4 +970,47 @@ impl SysFuncCallsInteract {
965970
.run()
966971
.await;
967972
}
973+
974+
pub async fn get_account_esdt_tokens(&mut self) -> HashMap<String, EsdtBalance> {
975+
println!(
976+
"Retrieving ESDT tokens for {}...",
977+
self.wallet_address.to_bech32_str()
978+
);
979+
980+
self.interactor
981+
.get_account_esdt(&self.wallet_address.to_address())
982+
.await
983+
}
984+
985+
pub async fn check_nft_uris(
986+
&mut self,
987+
token_id: &String,
988+
nonce: u64,
989+
expected_uris: &[String],
990+
) {
991+
let esdt_tokens = self.get_account_esdt_tokens().await;
992+
let nft_token_id = if nonce <= 10 {
993+
format!("{}-0{:x}", token_id, nonce)
994+
} else {
995+
format!("{}-{:x}", token_id, nonce)
996+
};
997+
998+
let uris = esdt_tokens
999+
.get(&nft_token_id)
1000+
.expect("nft token not owned by account")
1001+
.uris
1002+
.clone();
1003+
1004+
if expected_uris.is_empty() {
1005+
assert_eq!(1, uris.len());
1006+
assert_eq!(String::new(), uris[0]);
1007+
return;
1008+
}
1009+
1010+
assert_eq!(expected_uris.len(), uris.len());
1011+
for (index, uri) in uris.iter().enumerate() {
1012+
let uri_string = String::from_utf8(base64_decode(uri)).unwrap();
1013+
assert_eq!(expected_uris[index], uri_string);
1014+
}
1015+
}
9681016
}

tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ use system_sc_interact::{Config, NftDummyAttributes, SysFuncCallsInteract};
33

44
const ISSUE_COST: u64 = 50000000000000000u64;
55

6-
// real blockchain tests for now, fixes needed for chain simulator
76
#[tokio::test]
8-
#[ignore = "run on demand"]
9-
async fn cs_builtin_func_tokens_test() {
10-
// let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await;
7+
#[cfg_attr(not(feature = "chain-simulator-tests"), ignore)]
8+
async fn cs_builtin_run_tests() {
9+
cs_builtin_func_tokens_test().await;
10+
change_to_dynamic_test().await;
11+
update_token_test().await;
12+
modify_creator().await;
13+
transfer_role().await;
14+
}
1115

12-
let mut interact = SysFuncCallsInteract::init(Config::load_config()).await;
16+
async fn cs_builtin_func_tokens_test() {
17+
let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await;
1318

1419
// issue dynamic NFT
1520
interact
@@ -91,7 +96,7 @@ async fn cs_builtin_func_tokens_test() {
9196
creation_epoch: 2u64,
9297
cool_factor: 3u8,
9398
},
94-
Vec::new(),
99+
&[],
95100
)
96101
.await;
97102

@@ -107,11 +112,15 @@ async fn cs_builtin_func_tokens_test() {
107112
// set new uris
108113
let uris = vec!["thisianuri.com".to_string()];
109114
interact
110-
.set_new_uris(dynamic_nft_token_id.as_bytes(), nonce, uris)
115+
.set_new_uris(dynamic_nft_token_id.as_bytes(), nonce, &uris)
116+
.await;
117+
interact
118+
.check_nft_uris(&dynamic_nft_token_id, nonce, &uris)
111119
.await;
112120

113121
println!("New uris set for {dynamic_nft_token_id:?} with nonce {nonce:?}");
114122

123+
let uris = vec!["uri1_update1".to_string(), "uri2_update2".to_string()];
115124
// metadata update
116125
interact
117126
.metadata_update(
@@ -124,12 +133,15 @@ async fn cs_builtin_func_tokens_test() {
124133
creation_epoch: 3u64,
125134
cool_factor: 5u8,
126135
},
127-
Vec::new(),
136+
&uris,
128137
)
129138
.await;
130-
139+
interact
140+
.check_nft_uris(&dynamic_nft_token_id, nonce, &uris)
141+
.await;
131142
println!("Metadata updated for {dynamic_nft_token_id:?} with nonce {nonce:?}");
132143

144+
let uris = vec!["uri1_recreate1".to_string(), "uri2_recreate2".to_string()];
133145
// metadata recreate
134146
interact
135147
.metadata_recreate(
@@ -142,17 +154,37 @@ async fn cs_builtin_func_tokens_test() {
142154
creation_epoch: 100u64,
143155
cool_factor: 1u8,
144156
},
145-
Vec::new(),
157+
&uris,
146158
)
147159
.await;
160+
interact
161+
.check_nft_uris(&dynamic_nft_token_id, nonce, &uris)
162+
.await;
163+
println!("Metadata recreated for {dynamic_nft_token_id:?} with nonce {nonce:?}. A new token has been created.");
148164

165+
// metadata recreate with empty uris
166+
interact
167+
.metadata_recreate(
168+
dynamic_nft_token_id.as_bytes(),
169+
nonce,
170+
b"TESTNFT",
171+
30u64,
172+
b"new_hash_recreated",
173+
&NftDummyAttributes {
174+
creation_epoch: 100u64,
175+
cool_factor: 1u8,
176+
},
177+
&[],
178+
)
179+
.await;
180+
interact
181+
.check_nft_uris(&dynamic_nft_token_id, nonce, &[])
182+
.await;
149183
println!("Metadata recreated for {dynamic_nft_token_id:?} with nonce {nonce:?}. A new token has been created.");
150184
}
151185

152-
#[tokio::test]
153-
#[ignore = "run on demand"]
154186
async fn change_to_dynamic_test() {
155-
let mut interact = SysFuncCallsInteract::init(Config::load_config()).await;
187+
let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await;
156188

157189
// issue NFT with all roles
158190
let _ = interact
@@ -194,10 +226,8 @@ async fn change_to_dynamic_test() {
194226
interact.change_to_dynamic(sft_token_id.as_bytes()).await;
195227
}
196228

197-
#[tokio::test]
198-
#[ignore = "run on demand"]
199229
async fn update_token_test() {
200-
let mut interact = SysFuncCallsInteract::init(Config::load_config()).await;
230+
let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await;
201231

202232
// issue NFT with all roles
203233
let nft_token_id = interact
@@ -214,10 +244,8 @@ async fn update_token_test() {
214244
interact.update_token(nft_token_id.as_bytes()).await;
215245
}
216246

217-
#[tokio::test]
218-
#[ignore = "run on demand"]
219247
async fn modify_creator() {
220-
let mut interact = SysFuncCallsInteract::init(Config::load_config()).await;
248+
let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await;
221249

222250
// issue dynamic NFT
223251
let dynamic_nft_token_id = interact
@@ -250,7 +278,7 @@ async fn modify_creator() {
250278
creation_epoch: 2u64,
251279
cool_factor: 3u8,
252280
},
253-
Vec::new(),
281+
&[],
254282
)
255283
.await;
256284

@@ -275,10 +303,8 @@ async fn modify_creator() {
275303
.await;
276304
}
277305

278-
#[tokio::test]
279-
#[ignore = "run on demand"]
280306
async fn transfer_role() {
281-
let mut interact = SysFuncCallsInteract::init(Config::load_config()).await;
307+
let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await;
282308

283309
// issue dynamic NFT
284310
let dynamic_nft_token_id = interact

0 commit comments

Comments
 (0)