1use core::marker::PhantomData;
2
3use crate::{
4    api::{
5        const_handles, use_raw_handle, BigIntApiImpl, BlockchainApiImpl, CallTypeApi,
6        HandleConstraints, ManagedBufferApiImpl, RawHandle, SendApiImpl, StaticVarApiImpl,
7    },
8    types::{
9        BigUint, CodeMetadata, RewaOrDcdtTokenPayment, DcdtTokenPayment, ManagedAddress,
10        ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVec, TokenIdentifier,
11    },
12};
13
14#[derive(Default)]
15pub struct SendRawWrapper<A>
16where
17    A: CallTypeApi,
18{
19    _phantom: PhantomData<A>,
20}
21
22impl<A> SendRawWrapper<A>
23where
24    A: CallTypeApi,
25{
26    pub fn new() -> Self {
27        SendRawWrapper {
28            _phantom: PhantomData,
29        }
30    }
31
32    fn load_code_metadata_to_mb(
33        &self,
34        code_metadata: CodeMetadata,
35        code_metadata_handle: RawHandle,
36    ) {
37        let code_metadata_bytes = code_metadata.to_byte_array();
38        A::managed_type_impl().mb_overwrite(
39            use_raw_handle(code_metadata_handle),
40            &code_metadata_bytes[..],
41        );
42    }
43
44    pub fn direct_rewa<D>(&self, to: &ManagedAddress<A>, rewa_value: &BigUint<A>, data: D)
45    where
46        D: Into<ManagedBuffer<A>>,
47    {
48        let empty_mb_handle: A::ManagedBufferHandle =
49            use_raw_handle(const_handles::MBUF_TEMPORARY_1);
50        A::managed_type_impl().mb_overwrite(empty_mb_handle.clone(), &[]);
51
52        let _ = A::send_api_impl().transfer_value_execute(
53            to.get_handle().get_raw_handle(),
54            rewa_value.get_handle().get_raw_handle(),
55            0,
56            data.into().get_handle().get_raw_handle(),
57            empty_mb_handle.get_raw_handle(),
58        );
59    }
60
61    pub fn direct_rewa_execute(
62        &self,
63        to: &ManagedAddress<A>,
64        rewa_value: &BigUint<A>,
65        gas_limit: u64,
66        endpoint_name: &ManagedBuffer<A>,
67        arg_buffer: &ManagedArgBuffer<A>,
68    ) -> Result<(), &'static [u8]> {
69        A::send_api_impl().transfer_value_execute(
70            to.get_handle().get_raw_handle(),
71            rewa_value.get_handle().get_raw_handle(),
72            gas_limit,
73            endpoint_name.get_handle().get_raw_handle(),
74            arg_buffer.get_handle().get_raw_handle(),
75        )
76    }
77
78    pub fn transfer_dcdt_execute(
79        &self,
80        to: &ManagedAddress<A>,
81        token: &TokenIdentifier<A>,
82        value: &BigUint<A>,
83        gas_limit: u64,
84        endpoint_name: &ManagedBuffer<A>,
85        arg_buffer: &ManagedArgBuffer<A>,
86    ) -> Result<(), &'static [u8]> {
87        self.transfer_dcdt_nft_execute(to, token, 0, value, gas_limit, endpoint_name, arg_buffer)
88    }
89
90    #[allow(clippy::too_many_arguments)]
91    pub fn transfer_dcdt_nft_execute(
92        &self,
93        to: &ManagedAddress<A>,
94        token: &TokenIdentifier<A>,
95        nonce: u64,
96        rewa_value: &BigUint<A>,
97        gas_limit: u64,
98        endpoint_name: &ManagedBuffer<A>,
99        arg_buffer: &ManagedArgBuffer<A>,
100    ) -> Result<(), &'static [u8]> {
101        let mut payments: ManagedVec<A, DcdtTokenPayment<A>> = ManagedVec::new();
102        payments.push(DcdtTokenPayment::new(
103            token.clone(),
104            nonce,
105            rewa_value.clone(),
106        ));
107        self.multi_dcdt_transfer_execute(to, &payments, gas_limit, endpoint_name, arg_buffer)
108    }
109
110    pub fn multi_dcdt_transfer_execute(
111        &self,
112        to: &ManagedAddress<A>,
113        payments: &ManagedVec<A, DcdtTokenPayment<A>>,
114        gas_limit: u64,
115        endpoint_name: &ManagedBuffer<A>,
116        arg_buffer: &ManagedArgBuffer<A>,
117    ) -> Result<(), &'static [u8]> {
118        A::send_api_impl().multi_transfer_dcdt_nft_execute(
119            to.get_handle().get_raw_handle(),
120            payments.get_handle().get_raw_handle(),
121            gas_limit,
122            endpoint_name.get_handle().get_raw_handle(),
123            arg_buffer.get_handle().get_raw_handle(),
124        )
125    }
126
127    pub fn multi_rewa_or_dcdt_transfer_execute(
128        &self,
129        to: &ManagedAddress<A>,
130        payments: &ManagedVec<A, RewaOrDcdtTokenPayment<A>>,
131        gas_limit: u64,
132        endpoint_name: &ManagedBuffer<A>,
133        arg_buffer: &ManagedArgBuffer<A>,
134    ) -> Result<(), &'static [u8]> {
135        if let Some(single_item) = payments.is_single_item() {
136            if single_item.token_identifier.is_rewa() {
137                return self.direct_rewa_execute(
138                    to,
139                    &single_item.amount,
140                    gas_limit,
141                    endpoint_name,
142                    arg_buffer,
143                );
144            }
145        }
146        A::send_api_impl().multi_transfer_dcdt_nft_execute(
147            to.get_handle().get_raw_handle(),
148            payments.get_handle().get_raw_handle(),
149            gas_limit,
150            endpoint_name.get_handle().get_raw_handle(),
151            arg_buffer.get_handle().get_raw_handle(),
152        )
153    }
154
155    pub fn async_call_raw(
156        &self,
157        to: &ManagedAddress<A>,
158        rewa_value: &BigUint<A>,
159        endpoint_name: &ManagedBuffer<A>,
160        arg_buffer: &ManagedArgBuffer<A>,
161    ) -> ! {
162        A::send_api_impl().async_call_raw(
163            to.get_handle().get_raw_handle(),
164            rewa_value.get_handle().get_raw_handle(),
165            endpoint_name.get_handle().get_raw_handle(),
166            arg_buffer.get_handle().get_raw_handle(),
167        )
168    }
169
170    #[allow(clippy::too_many_arguments)]
171    pub fn create_async_call_raw(
172        &self,
173        to: &ManagedAddress<A>,
174        rewa_value: &BigUint<A>,
175        endpoint_name: &ManagedBuffer<A>,
176        arg_buffer: &ManagedArgBuffer<A>,
177        success_callback: &'static str,
178        error_callback: &'static str,
179        gas: u64,
180        extra_gas_for_callback: u64,
181        serialized_callback_closure_args: &ManagedBuffer<A>,
182    ) {
183        A::send_api_impl().create_async_call_raw(
184            to.get_handle().get_raw_handle(),
185            rewa_value.get_handle().get_raw_handle(),
186            endpoint_name.get_handle().get_raw_handle(),
187            arg_buffer.get_handle().get_raw_handle(),
188            success_callback,
189            error_callback,
190            gas,
191            extra_gas_for_callback,
192            serialized_callback_closure_args
193                .get_handle()
194                .get_raw_handle(),
195        )
196    }
197
198    pub fn deploy_contract(
203        &self,
204        gas: u64,
205        rewa_value: &BigUint<A>,
206        code: &ManagedBuffer<A>,
207        code_metadata: CodeMetadata,
208        arg_buffer: &ManagedArgBuffer<A>,
209    ) -> (ManagedAddress<A>, ManagedVec<A, ManagedBuffer<A>>) {
210        let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
211        self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
212        let new_address_handle = A::static_var_api_impl().next_handle();
213        let result_handle = A::static_var_api_impl().next_handle();
214        A::send_api_impl().deploy_contract(
215            gas,
216            rewa_value.get_handle().get_raw_handle(),
217            code.get_handle().get_raw_handle(),
218            code_metadata_handle,
219            arg_buffer.get_handle().get_raw_handle(),
220            new_address_handle,
221            result_handle,
222        );
223        unsafe {
224            (
225                ManagedAddress::from_raw_handle(new_address_handle),
226                ManagedVec::from_raw_handle(result_handle),
227            )
228        }
229    }
230
231    pub fn deploy_from_source_contract(
235        &self,
236        gas: u64,
237        rewa_value: &BigUint<A>,
238        source_contract_address: &ManagedAddress<A>,
239        code_metadata: CodeMetadata,
240        arg_buffer: &ManagedArgBuffer<A>,
241    ) -> (ManagedAddress<A>, ManagedVec<A, ManagedBuffer<A>>) {
242        let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
243        self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
244        let new_address_handle = A::static_var_api_impl().next_handle();
245        let result_handle = A::static_var_api_impl().next_handle();
246        A::send_api_impl().deploy_from_source_contract(
247            gas,
248            rewa_value.get_handle().get_raw_handle(),
249            source_contract_address.get_handle().get_raw_handle(),
250            code_metadata_handle,
251            arg_buffer.get_handle().get_raw_handle(),
252            new_address_handle,
253            result_handle,
254        );
255        unsafe {
256            (
257                ManagedAddress::from_raw_handle(new_address_handle),
258                ManagedVec::from_raw_handle(result_handle),
259            )
260        }
261    }
262
263    pub fn upgrade_from_source_contract(
264        &self,
265        sc_address: &ManagedAddress<A>,
266        gas: u64,
267        rewa_value: &BigUint<A>,
268        source_contract_address: &ManagedAddress<A>,
269        code_metadata: CodeMetadata,
270        arg_buffer: &ManagedArgBuffer<A>,
271    ) {
272        let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
273        self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
274        A::send_api_impl().upgrade_from_source_contract(
275            sc_address.get_handle().get_raw_handle(),
276            gas,
277            rewa_value.get_handle().get_raw_handle(),
278            source_contract_address.get_handle().get_raw_handle(),
279            code_metadata_handle,
280            arg_buffer.get_handle().get_raw_handle(),
281        )
282    }
283
284    pub fn upgrade_contract(
288        &self,
289        sc_address: &ManagedAddress<A>,
290        gas: u64,
291        rewa_value: &BigUint<A>,
292        code: &ManagedBuffer<A>,
293        code_metadata: CodeMetadata,
294        arg_buffer: &ManagedArgBuffer<A>,
295    ) {
296        let code_metadata_handle = const_handles::MBUF_TEMPORARY_1;
297        self.load_code_metadata_to_mb(code_metadata, code_metadata_handle);
298        A::send_api_impl().upgrade_contract(
299            sc_address.get_handle().get_raw_handle(),
300            gas,
301            rewa_value.get_handle().get_raw_handle(),
302            code.get_handle().get_raw_handle(),
303            code_metadata_handle,
304            arg_buffer.get_handle().get_raw_handle(),
305        )
306    }
307
308    pub fn execute_on_dest_context_raw(
310        &self,
311        gas: u64,
312        address: &ManagedAddress<A>,
313        value: &BigUint<A>,
314        endpoint_name: &ManagedBuffer<A>,
315        arg_buffer: &ManagedArgBuffer<A>,
316    ) -> ManagedVec<A, ManagedBuffer<A>> {
317        let result_handle = A::static_var_api_impl().next_handle();
318        A::send_api_impl().execute_on_dest_context_raw(
319            gas,
320            address.get_handle().get_raw_handle(),
321            value.get_handle().get_raw_handle(),
322            endpoint_name.get_handle().get_raw_handle(),
323            arg_buffer.get_handle().get_raw_handle(),
324            result_handle,
325        );
326        unsafe { ManagedVec::from_raw_handle(result_handle) }
327    }
328
329    pub fn execute_on_same_context_raw(
330        &self,
331        gas: u64,
332        address: &ManagedAddress<A>,
333        value: &BigUint<A>,
334        endpoint_name: &ManagedBuffer<A>,
335        arg_buffer: &ManagedArgBuffer<A>,
336    ) -> ManagedVec<A, ManagedBuffer<A>> {
337        let result_handle = A::static_var_api_impl().next_handle();
338        A::send_api_impl().execute_on_same_context_raw(
339            gas,
340            address.get_handle().get_raw_handle(),
341            value.get_handle().get_raw_handle(),
342            endpoint_name.get_handle().get_raw_handle(),
343            arg_buffer.get_handle().get_raw_handle(),
344            result_handle,
345        );
346        unsafe { ManagedVec::from_raw_handle(result_handle) }
347    }
348
349    pub fn execute_on_dest_context_readonly_raw(
351        &self,
352        gas: u64,
353        address: &ManagedAddress<A>,
354        endpoint_name: &ManagedBuffer<A>,
355        arg_buffer: &ManagedArgBuffer<A>,
356    ) -> ManagedVec<A, ManagedBuffer<A>> {
357        let result_handle = A::static_var_api_impl().next_handle();
358        A::send_api_impl().execute_on_dest_context_readonly_raw(
359            gas,
360            address.get_handle().get_raw_handle(),
361            endpoint_name.get_handle().get_raw_handle(),
362            arg_buffer.get_handle().get_raw_handle(),
363            result_handle,
364        );
365        unsafe { ManagedVec::from_raw_handle(result_handle) }
366    }
367
368    pub fn call_local_dcdt_built_in_function(
370        &self,
371        gas: u64,
372        function_name: &ManagedBuffer<A>,
373        arg_buffer: &ManagedArgBuffer<A>,
374    ) -> ManagedVec<A, ManagedBuffer<A>> {
375        let own_address_handle: A::ManagedBufferHandle =
377            use_raw_handle(const_handles::MBUF_TEMPORARY_1);
378        A::blockchain_api_impl().load_sc_address_managed(own_address_handle.clone());
379        let rewa_value_handle = A::managed_type_impl().bi_new_zero();
380
381        let result_handle = A::static_var_api_impl().next_handle();
382        A::send_api_impl().execute_on_dest_context_raw(
383            gas,
384            own_address_handle.get_raw_handle(),
385            rewa_value_handle.get_raw_handle(),
386            function_name.get_handle().get_raw_handle(),
387            arg_buffer.get_handle().get_raw_handle(),
388            result_handle,
389        );
390
391        self.clean_return_data();
392        unsafe { ManagedVec::from_raw_handle(result_handle) }
393    }
394
395    pub fn clean_return_data(&self) {
396        A::send_api_impl().clean_return_data()
397    }
398}