1use crate::api::managed_types::managed_buffer_api_node::unsafe_buffer_load_address;
2use testnumbat_wasm::{
3 api::BlockchainApi,
4 types::{
5 Address, BigUint, Box, DcdtTokenData, DcdtTokenType, ManagedAddress, ManagedBuffer,
6 ManagedType, ManagedVec, TokenIdentifier, H256,
7 },
8};
9
10#[allow(unused)]
11extern "C" {
12 fn mBufferNew() -> i32;
14
15 fn getSCAddress(resultOffset: *mut u8);
17 #[cfg(not(feature = "unmanaged-ei"))]
18 fn managedSCAddress(resultHandle: i32);
19
20 fn getOwnerAddress(resultOffset: *mut u8);
21 #[cfg(not(feature = "unmanaged-ei"))]
22 fn managedOwnerAddress(resultHandle: i32);
23
24 fn getCaller(resultOffset: *mut u8);
25 #[cfg(not(feature = "unmanaged-ei"))]
26 fn managedCaller(resultHandle: i32);
27
28 fn getShardOfAddress(address_ptr: *const u8) -> i32;
29 fn isSmartContract(address_ptr: *const u8) -> i32;
30
31 #[allow(dead_code)]
33 fn blockHash(nonce: i64, resultOffset: *mut u8) -> i32;
34
35 #[allow(dead_code)]
37 fn getFunction(functionOffset: *const u8) -> i32;
38
39 fn getGasLeft() -> i64;
40 fn getBlockTimestamp() -> i64;
41 fn getBlockNonce() -> i64;
42 fn getBlockRound() -> i64;
43 fn getBlockEpoch() -> i64;
44 fn getBlockRandomSeed(resultOffset: *mut u8);
45 #[allow(dead_code)]
47 fn getStateRootHash(resultOffset: *mut u8);
48 fn getPrevBlockTimestamp() -> i64;
49 fn getPrevBlockNonce() -> i64;
50 fn getPrevBlockRound() -> i64;
51 fn getPrevBlockEpoch() -> i64;
52 fn getPrevBlockRandomSeed(resultOffset: *const u8);
53 fn getOriginalTxHash(resultOffset: *const u8);
54
55 #[cfg(not(feature = "unmanaged-ei"))]
57 fn managedGetPrevBlockRandomSeed(resultHandle: i32);
58 #[cfg(not(feature = "unmanaged-ei"))]
59 fn managedGetBlockRandomSeed(resultHandle: i32);
60 #[cfg(not(feature = "unmanaged-ei"))]
61 fn managedGetStateRootHash(resultHandle: i32);
62 #[cfg(not(feature = "unmanaged-ei"))]
63 fn managedGetOriginalTxHash(resultHandle: i32);
64
65 fn bigIntNew(value: i64) -> i32;
67 fn bigIntGetExternalBalance(address_ptr: *const u8, dest: i32);
68 fn bigIntGetDCDTExternalBalance(
69 address_ptr: *const u8,
70 tokenIDOffset: *const u8,
71 tokenIDLen: i32,
72 nonce: i64,
73 dest: i32,
74 );
75
76 fn getCurrentDCDTNFTNonce(
78 address_ptr: *const u8,
79 tokenIDOffset: *const u8,
80 tokenIDLen: i32,
81 ) -> i64;
82 fn getDCDTTokenData(
83 address_ptr: *const u8,
84 tokenIDOffset: *const u8,
85 tokenIDLen: i32,
86 nonce: i64,
87 valueOffset: i32,
88 propertiesOffset: *const u8,
89 hashOffset: *const u8,
90 nameOffset: *const u8,
91 attributesOffset: *const u8,
92 creatorOffset: *const u8,
93 royaltiesOffset: i32,
94 urisOffset: *const u8,
95 ) -> i32;
96
97 fn getDCDTNFTNameLength(
99 address_ptr: *const u8,
100 tokenIDOffset: *const u8,
101 tokenIDLen: i32,
102 nonce: i64,
103 ) -> i32;
104 fn getDCDTNFTAttributeLength(
105 address_ptr: *const u8,
106 tokenIDOffset: *const u8,
107 tokenIDLen: i32,
108 nonce: i64,
109 ) -> i32;
110 fn getDCDTNFTURILength(
111 address_ptr: *const u8,
112 tokenIDOffset: *const u8,
113 tokenIDLen: i32,
114 nonce: i64,
115 ) -> i32;
116
117 #[cfg(not(feature = "unmanaged-ei"))]
118 fn managedGetDCDTTokenData(
119 addressHandle: i32,
120 tokenIDHandle: i32,
121 nonce: i64,
122 valueHandle: i32,
123 propertiesHandle: i32,
124 hashHandle: i32,
125 nameHandle: i32,
126 attributesHandle: i32,
127 creatorHandle: i32,
128 royaltiesHandle: i32,
129 urisHandle: i32,
130 );
131}
132
133impl BlockchainApi for crate::AndesApiImpl {
134 #[inline]
135 fn get_sc_address_legacy(&self) -> Address {
136 unsafe {
137 let mut res = Address::zero();
138 getSCAddress(res.as_mut_ptr());
139 res
140 }
141 }
142
143 #[inline]
144 #[cfg(not(feature = "unmanaged-ei"))]
145 fn get_sc_address(&self) -> ManagedAddress<Self> {
146 unsafe {
147 let handle = mBufferNew();
148 managedSCAddress(handle);
149 ManagedAddress::from_raw_handle(self.clone(), handle)
150 }
151 }
152
153 #[inline]
154 fn get_owner_address_legacy(&self) -> Address {
155 unsafe {
156 let mut res = Address::zero();
157 getOwnerAddress(res.as_mut_ptr());
158 res
159 }
160 }
161
162 #[inline]
163 #[cfg(not(feature = "unmanaged-ei"))]
164 fn get_owner_address(&self) -> ManagedAddress<Self> {
165 unsafe {
166 let handle = mBufferNew();
167 managedOwnerAddress(handle);
168 ManagedAddress::from_raw_handle(self.clone(), handle)
169 }
170 }
171
172 #[inline]
173 fn get_shard_of_address_legacy(&self, address: &Address) -> u32 {
174 unsafe { getShardOfAddress(address.as_ref().as_ptr()) as u32 }
175 }
176
177 #[inline]
178 fn get_shard_of_address(&self, address: &ManagedAddress<Self>) -> u32 {
179 unsafe { getShardOfAddress(unsafe_buffer_load_address(address.get_raw_handle())) as u32 }
180 }
181
182 #[inline]
183 fn is_smart_contract_legacy(&self, address: &Address) -> bool {
184 unsafe { isSmartContract(address.as_ref().as_ptr()) > 0 }
185 }
186
187 #[inline]
188 fn is_smart_contract(&self, address: &ManagedAddress<Self>) -> bool {
189 unsafe { isSmartContract(unsafe_buffer_load_address(address.get_raw_handle())) > 0 }
190 }
191
192 #[inline]
193 fn get_caller_legacy(&self) -> Address {
194 unsafe {
195 let mut res = Address::zero();
196 getCaller(res.as_mut_ptr());
197 res
198 }
199 }
200
201 #[inline]
202 #[cfg(not(feature = "unmanaged-ei"))]
203 fn get_caller(&self) -> ManagedAddress<Self> {
204 unsafe {
205 let handle = mBufferNew();
206 managedCaller(handle);
207 ManagedAddress::from_raw_handle(self.clone(), handle)
208 }
209 }
210
211 fn get_balance_legacy(&self, address: &Address) -> BigUint<Self> {
212 unsafe {
213 let balance_handle = bigIntNew(0);
214 bigIntGetExternalBalance(address.as_ref().as_ptr(), balance_handle);
215 BigUint::from_raw_handle(self.clone(), balance_handle)
216 }
217 }
218
219 fn get_balance(&self, address: &ManagedAddress<Self>) -> BigUint<Self> {
220 unsafe {
221 let balance_handle = bigIntNew(0);
222 bigIntGetExternalBalance(
223 unsafe_buffer_load_address(address.get_raw_handle()),
224 balance_handle,
225 );
226 BigUint::from_raw_handle(self.clone(), balance_handle)
227 }
228 }
229
230 #[inline]
231 fn get_state_root_hash_legacy(&self) -> H256 {
232 unsafe {
233 let mut res = H256::zero();
234 getOriginalTxHash(res.as_mut_ptr());
235 res
236 }
237 }
238
239 #[inline]
240 #[cfg(not(feature = "unmanaged-ei"))]
241 fn get_state_root_hash(&self) -> testnumbat_wasm::types::ManagedByteArray<Self, 32> {
242 unsafe {
243 let result_handle = mBufferNew();
244 managedGetStateRootHash(result_handle);
245 testnumbat_wasm::types::ManagedByteArray::from_raw_handle(self.clone(), result_handle)
246 }
247 }
248
249 #[inline]
250 fn get_tx_hash_legacy(&self) -> H256 {
251 unsafe {
252 let mut res = H256::zero();
253 getOriginalTxHash(res.as_mut_ptr());
254 res
255 }
256 }
257
258 #[inline]
259 #[cfg(not(feature = "unmanaged-ei"))]
260 fn get_tx_hash(&self) -> testnumbat_wasm::types::ManagedByteArray<Self, 32> {
261 unsafe {
262 let result_handle = mBufferNew();
263 managedGetOriginalTxHash(result_handle);
264 testnumbat_wasm::types::ManagedByteArray::from_raw_handle(self.clone(), result_handle)
265 }
266 }
267
268 #[inline]
269 fn get_gas_left(&self) -> u64 {
270 unsafe { getGasLeft() as u64 }
271 }
272
273 #[inline]
274 fn get_block_timestamp(&self) -> u64 {
275 unsafe { getBlockTimestamp() as u64 }
276 }
277
278 #[inline]
279 fn get_block_nonce(&self) -> u64 {
280 unsafe { getBlockNonce() as u64 }
281 }
282
283 #[inline]
284 fn get_block_round(&self) -> u64 {
285 unsafe { getBlockRound() as u64 }
286 }
287
288 #[inline]
289 fn get_block_epoch(&self) -> u64 {
290 unsafe { getBlockEpoch() as u64 }
291 }
292
293 #[inline]
294 fn get_block_random_seed_legacy(&self) -> Box<[u8; 48]> {
295 unsafe {
296 let mut res = [0u8; 48];
297 getBlockRandomSeed(res.as_mut_ptr());
298 Box::new(res)
299 }
300 }
301
302 #[inline]
303 #[cfg(not(feature = "unmanaged-ei"))]
304 fn get_block_random_seed(&self) -> testnumbat_wasm::types::ManagedByteArray<Self, 48> {
305 unsafe {
306 let result_handle = mBufferNew();
307 managedGetBlockRandomSeed(result_handle);
308 testnumbat_wasm::types::ManagedByteArray::from_raw_handle(self.clone(), result_handle)
309 }
310 }
311
312 #[inline]
313 fn get_prev_block_timestamp(&self) -> u64 {
314 unsafe { getPrevBlockTimestamp() as u64 }
315 }
316
317 #[inline]
318 fn get_prev_block_nonce(&self) -> u64 {
319 unsafe { getPrevBlockNonce() as u64 }
320 }
321
322 #[inline]
323 fn get_prev_block_round(&self) -> u64 {
324 unsafe { getPrevBlockRound() as u64 }
325 }
326
327 #[inline]
328 fn get_prev_block_epoch(&self) -> u64 {
329 unsafe { getPrevBlockEpoch() as u64 }
330 }
331
332 #[inline]
333 fn get_prev_block_random_seed_legacy(&self) -> Box<[u8; 48]> {
334 unsafe {
335 let mut res = [0u8; 48];
336 getPrevBlockRandomSeed(res.as_mut_ptr());
337 Box::new(res)
338 }
339 }
340
341 #[inline]
342 #[cfg(not(feature = "unmanaged-ei"))]
343 fn get_prev_block_random_seed(&self) -> testnumbat_wasm::types::ManagedByteArray<Self, 48> {
344 unsafe {
345 let result_handle = mBufferNew();
346 managedGetPrevBlockRandomSeed(result_handle);
347 testnumbat_wasm::types::ManagedByteArray::from_raw_handle(self.clone(), result_handle)
348 }
349 }
350
351 #[inline]
352 fn get_current_dcdt_nft_nonce(&self, address: &Address, token: &TokenIdentifier<Self>) -> u64 {
353 unsafe {
354 getCurrentDCDTNFTNonce(
355 address.as_ref().as_ptr(),
356 token.to_dcdt_identifier().as_ptr(),
357 token.len() as i32,
358 ) as u64
359 }
360 }
361
362 #[inline]
363 fn get_dcdt_balance(
364 &self,
365 m_address: &ManagedAddress<Self>,
366 token: &TokenIdentifier<Self>,
367 nonce: u64,
368 ) -> BigUint<Self> {
369 let address = m_address.to_address();
370 unsafe {
371 let balance_handle = bigIntNew(0);
372 bigIntGetDCDTExternalBalance(
373 address.as_ref().as_ptr(),
374 token.to_dcdt_identifier().as_ptr(),
375 token.len() as i32,
376 nonce as i64,
377 balance_handle,
378 );
379
380 BigUint::from_raw_handle(self.clone(), balance_handle)
381 }
382 }
383
384 #[cfg(feature = "unmanaged-ei")]
385 fn get_dcdt_token_data(
386 &self,
387 m_address: &ManagedAddress<Self>,
388 token: &TokenIdentifier<Self>,
389 nonce: u64,
390 ) -> DcdtTokenData<Self> {
391 use testnumbat_wasm::types::BoxedBytes;
392 let address = m_address.to_address();
393 unsafe {
394 let value_handle = bigIntNew(0);
395 let mut properties = [0u8; 2]; let mut hash = BoxedBytes::allocate(128);
397
398 let name_len = getDCDTNFTNameLength(
399 address.as_ref().as_ptr(),
400 token.to_dcdt_identifier().as_ptr(),
401 token.len() as i32,
402 nonce as i64,
403 ) as usize;
404 let mut name_bytes = BoxedBytes::allocate(name_len);
405
406 let attr_len = getDCDTNFTAttributeLength(
407 address.as_ref().as_ptr(),
408 token.to_dcdt_identifier().as_ptr(),
409 token.len() as i32,
410 nonce as i64,
411 ) as usize;
412 let mut attr_bytes = BoxedBytes::allocate(attr_len);
413
414 let uris_len = getDCDTNFTURILength(
418 address.as_ref().as_ptr(),
419 token.to_dcdt_identifier().as_ptr(),
420 token.len() as i32,
421 nonce as i64,
422 ) as usize;
423 let mut uri_bytes = BoxedBytes::allocate(uris_len);
424
425 let mut creator = Address::zero();
426 let royalties_handle = bigIntNew(0);
427
428 getDCDTTokenData(
429 address.as_ref().as_ptr(),
430 token.to_dcdt_identifier().as_ptr(),
431 token.len() as i32,
432 nonce as i64,
433 value_handle,
434 properties.as_mut_ptr(),
435 hash.as_mut_ptr(),
436 name_bytes.as_mut_ptr(),
437 attr_bytes.as_mut_ptr(),
438 creator.as_mut_ptr(),
439 royalties_handle,
440 uri_bytes.as_mut_ptr(),
441 );
442
443 let nonce = getCurrentDCDTNFTNonce(
445 address.as_ref().as_ptr(),
446 token.to_dcdt_identifier().as_ptr(),
447 token.len() as i32,
448 );
449 let token_type = if nonce == 0 {
450 DcdtTokenType::Fungible
451 } else {
452 DcdtTokenType::NonFungible
453 };
454
455 let frozen = properties[0] == 0 && properties[1] == 0;
457
458 let mut uris_vec = ManagedVec::new(self.clone());
459 uris_vec.push(ManagedBuffer::new_from_bytes(
460 self.clone(),
461 uri_bytes.as_slice(),
462 ));
463
464 DcdtTokenData {
465 token_type,
466 amount: BigUint::from_raw_handle(self.clone(), value_handle),
467 frozen,
468 hash: ManagedBuffer::new_from_bytes(self.clone(), hash.as_slice()),
469 name: ManagedBuffer::new_from_bytes(self.clone(), name_bytes.as_slice()),
470 attributes: ManagedBuffer::new_from_bytes(self.clone(), attr_bytes.as_slice()),
471 creator: ManagedAddress::from_address(self.clone(), &creator),
472 royalties: BigUint::from_raw_handle(self.clone(), royalties_handle),
473 uris: uris_vec,
474 }
475 }
476 }
477
478 #[cfg(not(feature = "unmanaged-ei"))]
479 fn get_dcdt_token_data(
480 &self,
481 address: &ManagedAddress<Self>,
482 token: &TokenIdentifier<Self>,
483 nonce: u64,
484 ) -> DcdtTokenData<Self> {
485 let managed_token_id = token.as_managed_buffer();
486 unsafe {
487 let value_handle = bigIntNew(0);
488 let properties_handle = mBufferNew();
489 let hash_handle = mBufferNew();
490 let name_handle = mBufferNew();
491 let attributes_handle = mBufferNew();
492 let creator_handle = mBufferNew();
493 let royalties_handle = bigIntNew(0);
494 let uris_handle = mBufferNew();
495
496 managedGetDCDTTokenData(
497 address.get_raw_handle(),
498 managed_token_id.get_raw_handle(),
499 nonce as i64,
500 value_handle,
501 properties_handle,
502 hash_handle,
503 name_handle,
504 attributes_handle,
505 creator_handle,
506 royalties_handle,
507 uris_handle,
508 );
509
510 let token_type = if nonce == 0 {
511 DcdtTokenType::Fungible
512 } else {
513 DcdtTokenType::NonFungible
514 };
515
516 let properties_buffer = ManagedBuffer::from_raw_handle(self.clone(), properties_handle);
518 let mut properties_bytes = [0u8; 2];
519 let _ = properties_buffer.load_slice(0, &mut properties_bytes[..]);
520 let frozen = properties_bytes[0] == 0 && properties_bytes[1] == 0; DcdtTokenData {
523 token_type,
524 amount: BigUint::from_raw_handle(self.clone(), value_handle),
525 frozen,
526 hash: ManagedBuffer::from_raw_handle(self.clone(), hash_handle),
527 name: ManagedBuffer::from_raw_handle(self.clone(), name_handle),
528 attributes: ManagedBuffer::from_raw_handle(self.clone(), attributes_handle),
529 creator: ManagedAddress::from_raw_handle(self.clone(), creator_handle),
530 royalties: BigUint::from_raw_handle(self.clone(), royalties_handle),
531 uris: ManagedVec::from_raw_handle(self.clone(), uris_handle),
532 }
533 }
534 }
535}