1use core::marker::PhantomData;
2
3use crate::{
4 api::{
5 BigIntApiImpl, BlockchainApiImpl, CallTypeApi, HandleConstraints, ManagedBufferApiImpl,
6 RawHandle, SendApiImpl, StaticVarApiImpl, const_handles, use_raw_handle,
7 },
8 types::{
9 BigUint, CodeMetadata, EgldOrEsdtTokenPayment, EsdtTokenIdentifier, EsdtTokenPayment,
10 ManagedAddress, ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVec,
11 },
12};
13
14pub struct SyncCallRawResult<Api>(pub ManagedVec<Api, ManagedBuffer<Api>>)
18where
19 Api: CallTypeApi;
20
21pub enum SyncCallRawResultOrError<Api>
25where
26 Api: CallTypeApi,
27{
28 Success(SyncCallRawResult<Api>),
29 Error(u32),
30}
31
32#[derive(Default)]
33pub struct SendRawWrapper<A>
34where
35 A: CallTypeApi,
36{
37 _phantom: PhantomData<A>,
38}
39
40pub struct TransferExecuteFailed;
42
43impl<A> SendRawWrapper<A>
44where
45 A: CallTypeApi,
46{
47 pub fn new() -> Self {
48 SendRawWrapper {
49 _phantom: PhantomData,
50 }
51 }
52
53 fn load_code_metadata_to_mb(
54 &self,
55 code_metadata: CodeMetadata,
56 code_metadata_handle: RawHandle,
57 ) {
58 let code_metadata_bytes = code_metadata.to_byte_array();
59 A::managed_type_impl().mb_overwrite(
60 use_raw_handle(code_metadata_handle),
61 &code_metadata_bytes[..],
62 );
63 }
64
65 pub fn direct_egld<D>(&self, to: &ManagedAddress<A>, egld_value: &BigUint<A>, data: D)
66 where
67 D: Into<ManagedBuffer<A>>,
68 {
69 let empty_mb_handle: A::ManagedBufferHandle =
70 use_raw_handle(const_handles::MBUF_TEMPORARY_1);
71 A::managed_type_impl().mb_overwrite(empty_mb_handle.clone(), &[]);
72
73 A::send_api_impl().transfer_value_execute(
74 to.get_handle().get_raw_handle(),
75 egld_value.get_handle().get_raw_handle(),
76 0,
77 data.into().get_handle().get_raw_handle(),
78 empty_mb_handle.get_raw_handle(),
79 );
80 }
81
82 pub fn direct_egld_execute(
83 &self,
84 to: &ManagedAddress<A>,
85 egld_value: &BigUint<A>,
86 gas_limit: u64,
87 endpoint_name: &ManagedBuffer<A>,
88 arg_buffer: &ManagedArgBuffer<A>,
89 ) {
90 A::send_api_impl().transfer_value_execute(
91 to.get_handle().get_raw_handle(),
92 egld_value.get_handle().get_raw_handle(),
93 gas_limit,
94 endpoint_name.get_handle().get_raw_handle(),
95 arg_buffer.get_handle().get_raw_handle(),
96 );
97 }
98
99 pub fn transfer_esdt_execute(
100 &self,
101 to: &ManagedAddress<A>,
102 token: &EsdtTokenIdentifier<A>,
103 value: &BigUint<A>,
104 gas_limit: u64,
105 endpoint_name: &ManagedBuffer<A>,
106 arg_buffer: &ManagedArgBuffer<A>,
107 ) {
108 self.transfer_esdt_nft_execute(to, token, 0, value, gas_limit, endpoint_name, arg_buffer);
109 }
110
111 #[allow(clippy::too_many_arguments)]
112 pub fn transfer_esdt_nft_execute(
113 &self,
114 to: &ManagedAddress<A>,
115 token: &EsdtTokenIdentifier<A>,
116 nonce: u64,
117 egld_value: &BigUint<A>,
118 gas_limit: u64,
119 endpoint_name: &ManagedBuffer<A>,
120 arg_buffer: &ManagedArgBuffer<A>,
121 ) {
122 let mut payments: ManagedVec<A, EsdtTokenPayment<A>> = ManagedVec::new();
123 payments.push(EsdtTokenPayment::new(
124 token.clone(),
125 nonce,
126 egld_value.clone(),
127 ));
128 self.multi_esdt_transfer_execute(to, &payments, gas_limit, endpoint_name, arg_buffer);
129 }
130
131 pub fn multi_esdt_transfer_execute(
132 &self,
133 to: &ManagedAddress<A>,
134 payments: &ManagedVec<A, EsdtTokenPayment<A>>,
135 gas_limit: u64,
136 endpoint_name: &ManagedBuffer<A>,
137 arg_buffer: &ManagedArgBuffer<A>,
138 ) {
139 A::send_api_impl().multi_transfer_esdt_nft_execute(
140 to.get_handle().get_raw_handle(),
141 payments.get_handle().get_raw_handle(),
142 gas_limit,
143 endpoint_name.get_handle().get_raw_handle(),
144 arg_buffer.get_handle().get_raw_handle(),
145 );
146 }
147
148 fn fallback_to_single_egld_if_necessary(
153 &self,
154 to: &ManagedAddress<A>,
155 payments: &ManagedVec<A, EgldOrEsdtTokenPayment<A>>,
156 gas_limit: u64,
157 endpoint_name: &ManagedBuffer<A>,
158 arg_buffer: &ManagedArgBuffer<A>,
159 ) -> bool {
160 if payments.is_empty() {
161 self.direct_egld_execute(to, &BigUint::zero(), gas_limit, endpoint_name, arg_buffer);
162
163 return true;
164 }
165
166 if let Some(single_item) = payments.is_single_item() {
167 if single_item.token_identifier.is_egld() {
168 self.direct_egld_execute(
169 to,
170 &single_item.amount,
171 gas_limit,
172 endpoint_name,
173 arg_buffer,
174 );
175 return true;
176 }
177 }
178
179 false
180 }
181
182 #[deprecated(
183 since = "0.59.0",
184 note = "Use multi_egld_or_esdt_transfer_execute_fallible instead"
185 )]
186 pub fn multi_egld_or_esdt_transfer_execute(
187 &self,
188 to: &ManagedAddress<A>,
189 payments: &ManagedVec<A, EgldOrEsdtTokenPayment<A>>,
190 gas_limit: u64,
191 endpoint_name: &ManagedBuffer<A>,
192 arg_buffer: &ManagedArgBuffer<A>,
193 ) {
194 if self.fallback_to_single_egld_if_necessary(
195 to,
196 payments,
197 gas_limit,
198 endpoint_name,
199 arg_buffer,
200 ) {
201 return;
202 }
203 A::send_api_impl().multi_transfer_esdt_nft_execute(
204 to.get_handle().get_raw_handle(),
205 payments.get_handle().get_raw_handle(),
206 gas_limit,
207 endpoint_name.get_handle().get_raw_handle(),
208 arg_buffer.get_handle().get_raw_handle(),
209 );
210 }
211
212 pub fn multi_egld_or_esdt_transfer_execute_fallible(
213 &self,
214 to: &ManagedAddress<A>,
215 payments: &ManagedVec<A, EgldOrEsdtTokenPayment<A>>,
216 gas_limit: u64,
217 endpoint_name: &ManagedBuffer<A>,
218 arg_buffer: &ManagedArgBuffer<A>,
219 ) -> Result<(), TransferExecuteFailed> {
220 if payments.is_empty() {
221 use crate::{api::quick_signal_error, err_msg};
222
223 quick_signal_error::<A>(err_msg::TRANSFER_EXECUTE_REQUIRES_PAYMENT);
224 }
225
226 let ret = A::send_api_impl().multi_transfer_esdt_nft_execute_with_return(
227 to.get_handle().get_raw_handle(),
228 payments.get_handle().get_raw_handle(),
229 gas_limit,
230 endpoint_name.get_handle().get_raw_handle(),
231 arg_buffer.get_handle().get_raw_handle(),
232 );
233
234 if ret == 0 {
235 Ok(())
236 } else {
237 Err(TransferExecuteFailed)
238 }
239 }
240
241 pub fn async_call_raw(
242 &self,
243 to: &ManagedAddress<A>,
244 egld_value: &BigUint<A>,
245 endpoint_name: &ManagedBuffer<A>,
246 arg_buffer: &ManagedArgBuffer<A>,
247 ) -> ! {
248 A::send_api_impl().async_call_raw(
249 to.get_handle().get_raw_handle(),
250 egld_value.get_handle().get_raw_handle(),
251 endpoint_name.get_handle().get_raw_handle(),
252 arg_buffer.get_handle().get_raw_handle(),
253 )
254 }
255
256 #[allow(clippy::too_many_arguments)]
257 pub fn create_async_call_raw(
258 &self,
259 to: &ManagedAddress<A>,
260 egld_value: &BigUint<A>,
261 endpoint_name: &ManagedBuffer<A>,
262 arg_buffer: &ManagedArgBuffer<A>,
263 success_callback: &'static str,
264 error_callback: &'static str,
265 gas: u64,
266 extra_gas_for_callback: u64,
267 serialized_callback_closure_args: &ManagedBuffer<A>,
268 ) {
269 A::send_api_impl().create_async_call_raw(
270 to.get_handle().get_raw_handle(),
271 egld_value.get_handle().get_raw_handle(),
272 endpoint_name.get_handle().get_raw_handle(),
273 arg_buffer.get_handle().get_raw_handle(),
274 success_callback,
275 error_callback,
276 gas,
277 extra_gas_for_callback,
278 serialized_callback_closure_args
279 .get_handle()
280 .get_raw_handle(),
281 )
282 }
283
284 pub fn deploy_contract(
289 &self,
290 gas: u64,
291 egld_value: &BigUint<A>,
292 code: &ManagedBuffer<A>,
293 code_metadata: CodeMetadata,
294 arg_buffer: &ManagedArgBuffer<A>,
295 ) -> (ManagedAddress<A>, ManagedVec<A, ManagedBuffer<A>>) {
296 let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
297 self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
298 let new_address_handle = A::static_var_api_impl().next_handle();
299 let result_handle = A::static_var_api_impl().next_handle();
300 A::send_api_impl().deploy_contract(
301 gas,
302 egld_value.get_handle().get_raw_handle(),
303 code.get_handle().get_raw_handle(),
304 code_metadata_handle,
305 arg_buffer.get_handle().get_raw_handle(),
306 new_address_handle,
307 result_handle,
308 );
309 unsafe {
310 (
311 ManagedAddress::from_raw_handle(new_address_handle),
312 ManagedVec::from_raw_handle(result_handle),
313 )
314 }
315 }
316
317 pub fn deploy_from_source_contract(
321 &self,
322 gas: u64,
323 egld_value: &BigUint<A>,
324 source_contract_address: &ManagedAddress<A>,
325 code_metadata: CodeMetadata,
326 arg_buffer: &ManagedArgBuffer<A>,
327 ) -> (ManagedAddress<A>, ManagedVec<A, ManagedBuffer<A>>) {
328 let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
329 self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
330 let new_address_handle = A::static_var_api_impl().next_handle();
331 let result_handle = A::static_var_api_impl().next_handle();
332 A::send_api_impl().deploy_from_source_contract(
333 gas,
334 egld_value.get_handle().get_raw_handle(),
335 source_contract_address.get_handle().get_raw_handle(),
336 code_metadata_handle,
337 arg_buffer.get_handle().get_raw_handle(),
338 new_address_handle,
339 result_handle,
340 );
341 unsafe {
342 (
343 ManagedAddress::from_raw_handle(new_address_handle),
344 ManagedVec::from_raw_handle(result_handle),
345 )
346 }
347 }
348
349 pub fn upgrade_from_source_contract(
350 &self,
351 sc_address: &ManagedAddress<A>,
352 gas: u64,
353 egld_value: &BigUint<A>,
354 source_contract_address: &ManagedAddress<A>,
355 code_metadata: CodeMetadata,
356 arg_buffer: &ManagedArgBuffer<A>,
357 ) {
358 let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
359 self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
360 A::send_api_impl().upgrade_from_source_contract(
361 sc_address.get_handle().get_raw_handle(),
362 gas,
363 egld_value.get_handle().get_raw_handle(),
364 source_contract_address.get_handle().get_raw_handle(),
365 code_metadata_handle,
366 arg_buffer.get_handle().get_raw_handle(),
367 )
368 }
369
370 pub fn upgrade_contract(
374 &self,
375 sc_address: &ManagedAddress<A>,
376 gas: u64,
377 egld_value: &BigUint<A>,
378 code: &ManagedBuffer<A>,
379 code_metadata: CodeMetadata,
380 arg_buffer: &ManagedArgBuffer<A>,
381 ) {
382 let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
383 self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
384 A::send_api_impl().upgrade_contract(
385 sc_address.get_handle().get_raw_handle(),
386 gas,
387 egld_value.get_handle().get_raw_handle(),
388 code.get_handle().get_raw_handle(),
389 code_metadata_handle,
390 arg_buffer.get_handle().get_raw_handle(),
391 )
392 }
393
394 pub fn execute_on_dest_context_raw(
396 &self,
397 gas: u64,
398 address: &ManagedAddress<A>,
399 value: &BigUint<A>,
400 endpoint_name: &ManagedBuffer<A>,
401 arg_buffer: &ManagedArgBuffer<A>,
402 ) -> SyncCallRawResult<A> {
403 let result_handle = A::static_var_api_impl().next_handle();
404 A::send_api_impl().execute_on_dest_context_raw(
405 gas,
406 address.get_handle().get_raw_handle(),
407 value.get_handle().get_raw_handle(),
408 endpoint_name.get_handle().get_raw_handle(),
409 arg_buffer.get_handle().get_raw_handle(),
410 result_handle,
411 );
412 let result_vec = unsafe { ManagedVec::from_raw_handle(result_handle) };
413 SyncCallRawResult(result_vec)
414 }
415
416 pub fn execute_on_same_context_raw(
417 &self,
418 gas: u64,
419 address: &ManagedAddress<A>,
420 value: &BigUint<A>,
421 endpoint_name: &ManagedBuffer<A>,
422 arg_buffer: &ManagedArgBuffer<A>,
423 ) -> ManagedVec<A, ManagedBuffer<A>> {
424 let result_handle = A::static_var_api_impl().next_handle();
425 A::send_api_impl().execute_on_same_context_raw(
426 gas,
427 address.get_handle().get_raw_handle(),
428 value.get_handle().get_raw_handle(),
429 endpoint_name.get_handle().get_raw_handle(),
430 arg_buffer.get_handle().get_raw_handle(),
431 result_handle,
432 );
433 unsafe { ManagedVec::from_raw_handle(result_handle) }
434 }
435
436 pub fn execute_on_dest_context_readonly_raw(
438 &self,
439 gas: u64,
440 address: &ManagedAddress<A>,
441 endpoint_name: &ManagedBuffer<A>,
442 arg_buffer: &ManagedArgBuffer<A>,
443 ) -> ManagedVec<A, ManagedBuffer<A>> {
444 let result_handle = A::static_var_api_impl().next_handle();
445 A::send_api_impl().execute_on_dest_context_readonly_raw(
446 gas,
447 address.get_handle().get_raw_handle(),
448 endpoint_name.get_handle().get_raw_handle(),
449 arg_buffer.get_handle().get_raw_handle(),
450 result_handle,
451 );
452 unsafe { ManagedVec::from_raw_handle(result_handle) }
453 }
454
455 pub fn execute_on_dest_context_error_return_raw(
457 &self,
458 gas: u64,
459 address: &ManagedAddress<A>,
460 value: &BigUint<A>,
461 endpoint_name: &ManagedBuffer<A>,
462 arg_buffer: &ManagedArgBuffer<A>,
463 ) -> SyncCallRawResultOrError<A> {
464 let result_handle = A::static_var_api_impl().next_handle();
465 let result_code = A::send_api_impl().execute_on_dest_context_error_return_raw(
466 gas,
467 address.get_handle().get_raw_handle(),
468 value.get_handle().get_raw_handle(),
469 endpoint_name.get_handle().get_raw_handle(),
470 arg_buffer.get_handle().get_raw_handle(),
471 result_handle,
472 );
473 if result_code == 0 {
474 let result_vec = unsafe { ManagedVec::from_raw_handle(result_handle) };
475 SyncCallRawResultOrError::Success(SyncCallRawResult(result_vec))
476 } else {
477 SyncCallRawResultOrError::Error(result_code as u32)
478 }
479 }
480}
481
482impl<A> SendRawWrapper<A>
483where
484 A: CallTypeApi,
485{
486 pub fn call_local_esdt_built_in_function(
488 &self,
489 gas: u64,
490 function_name: &ManagedBuffer<A>,
491 arg_buffer: &ManagedArgBuffer<A>,
492 ) -> ManagedVec<A, ManagedBuffer<A>> {
493 let own_address_handle: A::ManagedBufferHandle =
495 use_raw_handle(const_handles::MBUF_TEMPORARY_1);
496 A::blockchain_api_impl().load_sc_address_managed(own_address_handle.clone());
497 let egld_value_handle = A::managed_type_impl().bi_new_zero();
498
499 let result_handle = A::static_var_api_impl().next_handle();
500 A::send_api_impl().execute_on_dest_context_raw(
501 gas,
502 own_address_handle.get_raw_handle(),
503 egld_value_handle.get_raw_handle(),
504 function_name.get_handle().get_raw_handle(),
505 arg_buffer.get_handle().get_raw_handle(),
506 result_handle,
507 );
508
509 self.clean_return_data();
510 unsafe { ManagedVec::from_raw_handle(result_handle) }
511 }
512
513 pub fn clean_return_data(&self) {
514 A::send_api_impl().clean_return_data()
515 }
516}