1use std::{any::Any, collections::HashMap, marker::PhantomData};
5
6use linera_base::{
7 data_types::{
8 Amount, ApplicationDescription, ApplicationPermissions, BlockHeight, Bytecode,
9 SendMessageRequest, Timestamp,
10 },
11 http,
12 identifiers::{Account, AccountOwner, ApplicationId, ChainId, StreamName},
13 ownership::{ChainOwnership, ManageChainError},
14 vm::VmRuntime,
15};
16use linera_views::batch::{Batch, WriteOperation};
17use linera_witty::{wit_export, Instance, RuntimeError};
18use tracing::log;
19
20use super::WasmExecutionError;
21use crate::{BaseRuntime, ContractRuntime, DataBlobHash, ExecutionError, ModuleId, ServiceRuntime};
22
23pub struct RuntimeApiData<Runtime> {
25 runtime: Runtime,
26 active_promises: HashMap<u32, Box<dyn Any + Send + Sync>>,
27 promise_counter: u32,
28}
29
30impl<Runtime> RuntimeApiData<Runtime> {
31 pub fn new(runtime: Runtime) -> Self {
33 RuntimeApiData {
34 runtime,
35 active_promises: HashMap::new(),
36 promise_counter: 0,
37 }
38 }
39
40 pub fn runtime_mut(&mut self) -> &mut Runtime {
42 &mut self.runtime
43 }
44
45 fn register_promise<Promise>(&mut self, promise: Promise) -> u32
48 where
49 Promise: Send + Sync + 'static,
50 {
51 let id = self.promise_counter;
52
53 self.active_promises.insert(id, Box::new(promise));
54 self.promise_counter += 1;
55
56 id
57 }
58
59 fn take_promise<Promise>(&mut self, promise_id: u32) -> Result<Promise, RuntimeError>
61 where
62 Promise: Send + Sync + 'static,
63 {
64 let type_erased_promise = self
65 .active_promises
66 .remove(&promise_id)
67 .ok_or_else(|| RuntimeError::Custom(WasmExecutionError::UnknownPromise.into()))?;
68
69 type_erased_promise
70 .downcast()
71 .map(|boxed_promise| *boxed_promise)
72 .map_err(|_| RuntimeError::Custom(WasmExecutionError::IncorrectPromise.into()))
73 }
74}
75
76#[derive(Default)]
79pub struct BaseRuntimeApi<Caller>(PhantomData<Caller>);
80
81#[wit_export(package = "linera:app")]
82impl<Caller, Runtime> BaseRuntimeApi<Caller>
83where
84 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
85 Runtime: BaseRuntime + 'static,
86{
87 fn get_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
89 caller
90 .user_data_mut()
91 .runtime
92 .chain_id()
93 .map_err(|error| RuntimeError::Custom(error.into()))
94 }
95
96 fn get_block_height(caller: &mut Caller) -> Result<BlockHeight, RuntimeError> {
98 caller
99 .user_data_mut()
100 .runtime
101 .block_height()
102 .map_err(|error| RuntimeError::Custom(error.into()))
103 }
104
105 fn get_application_id(caller: &mut Caller) -> Result<ApplicationId, RuntimeError> {
107 caller
108 .user_data_mut()
109 .runtime
110 .application_id()
111 .map_err(|error| RuntimeError::Custom(error.into()))
112 }
113
114 fn get_application_creator_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
116 caller
117 .user_data_mut()
118 .runtime
119 .application_creator_chain_id()
120 .map_err(|error| RuntimeError::Custom(error.into()))
121 }
122
123 fn read_application_description(
125 caller: &mut Caller,
126 application_id: ApplicationId,
127 ) -> Result<ApplicationDescription, RuntimeError> {
128 caller
129 .user_data_mut()
130 .runtime
131 .read_application_description(application_id)
132 .map_err(|error| RuntimeError::Custom(error.into()))
133 }
134
135 fn application_parameters(caller: &mut Caller) -> Result<Vec<u8>, RuntimeError> {
137 caller
138 .user_data_mut()
139 .runtime
140 .application_parameters()
141 .map_err(|error| RuntimeError::Custom(error.into()))
142 }
143
144 fn get_chain_ownership(caller: &mut Caller) -> Result<ChainOwnership, RuntimeError> {
146 caller
147 .user_data_mut()
148 .runtime
149 .chain_ownership()
150 .map_err(|error| RuntimeError::Custom(error.into()))
151 }
152
153 fn get_application_permissions(
155 caller: &mut Caller,
156 ) -> Result<ApplicationPermissions, RuntimeError> {
157 caller
158 .user_data_mut()
159 .runtime
160 .application_permissions()
161 .map_err(|error| RuntimeError::Custom(error.into()))
162 }
163
164 fn read_system_timestamp(caller: &mut Caller) -> Result<Timestamp, RuntimeError> {
166 caller
167 .user_data_mut()
168 .runtime
169 .read_system_timestamp()
170 .map_err(|error| RuntimeError::Custom(error.into()))
171 }
172
173 fn read_chain_balance(caller: &mut Caller) -> Result<Amount, RuntimeError> {
175 caller
176 .user_data_mut()
177 .runtime
178 .read_chain_balance()
179 .map_err(|error| RuntimeError::Custom(error.into()))
180 }
181
182 fn read_owner_balance(
184 caller: &mut Caller,
185 owner: AccountOwner,
186 ) -> Result<Amount, RuntimeError> {
187 caller
188 .user_data_mut()
189 .runtime
190 .read_owner_balance(owner)
191 .map_err(|error| RuntimeError::Custom(error.into()))
192 }
193
194 fn read_owner_balances(
196 caller: &mut Caller,
197 ) -> Result<Vec<(AccountOwner, Amount)>, RuntimeError> {
198 caller
199 .user_data_mut()
200 .runtime
201 .read_owner_balances()
202 .map_err(|error| RuntimeError::Custom(error.into()))
203 }
204
205 fn read_balance_owners(caller: &mut Caller) -> Result<Vec<AccountOwner>, RuntimeError> {
207 caller
208 .user_data_mut()
209 .runtime
210 .read_balance_owners()
211 .map_err(|error| RuntimeError::Custom(error.into()))
212 }
213
214 fn read_allowance(
216 caller: &mut Caller,
217 owner: AccountOwner,
218 spender: AccountOwner,
219 ) -> Result<Amount, RuntimeError> {
220 caller
221 .user_data_mut()
222 .runtime
223 .read_allowance(owner, spender)
224 .map_err(|error| RuntimeError::Custom(error.into()))
225 }
226
227 fn read_allowances(
229 caller: &mut Caller,
230 ) -> Result<Vec<(AccountOwner, AccountOwner, Amount)>, RuntimeError> {
231 caller
232 .user_data_mut()
233 .runtime
234 .read_allowances()
235 .map_err(|error| RuntimeError::Custom(error.into()))
236 }
237
238 fn perform_http_request(
240 caller: &mut Caller,
241 request: http::Request,
242 ) -> Result<http::Response, RuntimeError> {
243 caller
244 .user_data_mut()
245 .runtime
246 .perform_http_request(request)
247 .map_err(|error| RuntimeError::Custom(error.into()))
248 }
249
250 fn assert_before(caller: &mut Caller, timestamp: Timestamp) -> Result<(), RuntimeError> {
254 caller
255 .user_data_mut()
256 .runtime
257 .assert_before(timestamp)
258 .map_err(|error| RuntimeError::Custom(error.into()))
259 }
260
261 fn read_data_blob(caller: &mut Caller, hash: DataBlobHash) -> Result<Vec<u8>, RuntimeError> {
263 caller
264 .user_data_mut()
265 .runtime
266 .read_data_blob(hash)
267 .map_err(|error| RuntimeError::Custom(error.into()))
268 }
269
270 fn assert_data_blob_exists(
272 caller: &mut Caller,
273 hash: DataBlobHash,
274 ) -> Result<(), RuntimeError> {
275 caller
276 .user_data_mut()
277 .runtime
278 .assert_data_blob_exists(hash)
279 .map_err(|error| RuntimeError::Custom(error.into()))
280 }
281
282 fn log(caller: &mut Caller, message: String, level: log::Level) -> Result<(), RuntimeError> {
284 let allowed = caller
285 .user_data_mut()
286 .runtime
287 .allow_application_logs()
288 .map_err(|error| RuntimeError::Custom(error.into()))?;
289
290 if !allowed {
291 return Ok(());
292 }
293
294 #[cfg(web)]
295 {
296 caller
298 .user_data_mut()
299 .runtime
300 .send_log(message.clone(), level);
301 }
302
303 match level {
305 log::Level::Trace => tracing::trace!("{message}"),
306 log::Level::Debug => tracing::debug!("{message}"),
307 log::Level::Info => tracing::info!("{message}"),
308 log::Level::Warn => tracing::warn!("{message}"),
309 log::Level::Error => tracing::error!("{message}"),
310 }
311 Ok(())
312 }
313
314 fn contains_key_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
316 let mut data = caller.user_data_mut();
317 let promise = data
318 .runtime
319 .contains_key_new(key)
320 .map_err(|error| RuntimeError::Custom(error.into()))?;
321
322 Ok(data.register_promise(promise))
323 }
324
325 fn contains_key_wait(caller: &mut Caller, promise_id: u32) -> Result<bool, RuntimeError> {
327 let mut data = caller.user_data_mut();
328 let promise = data.take_promise(promise_id)?;
329
330 data.runtime
331 .contains_key_wait(&promise)
332 .map_err(|error| RuntimeError::Custom(error.into()))
333 }
334
335 fn contains_keys_new(caller: &mut Caller, keys: Vec<Vec<u8>>) -> Result<u32, RuntimeError> {
337 let mut data = caller.user_data_mut();
338 let promise = data
339 .runtime
340 .contains_keys_new(keys)
341 .map_err(|error| RuntimeError::Custom(error.into()))?;
342
343 Ok(data.register_promise(promise))
344 }
345
346 fn contains_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<bool>, RuntimeError> {
348 let mut data = caller.user_data_mut();
349 let promise = data.take_promise(promise_id)?;
350
351 data.runtime
352 .contains_keys_wait(&promise)
353 .map_err(|error| RuntimeError::Custom(error.into()))
354 }
355
356 fn read_multi_values_bytes_new(
358 caller: &mut Caller,
359 keys: Vec<Vec<u8>>,
360 ) -> Result<u32, RuntimeError> {
361 let mut data = caller.user_data_mut();
362 let promise = data
363 .runtime
364 .read_multi_values_bytes_new(keys)
365 .map_err(|error| RuntimeError::Custom(error.into()))?;
366
367 Ok(data.register_promise(promise))
368 }
369
370 fn read_multi_values_bytes_wait(
372 caller: &mut Caller,
373 promise_id: u32,
374 ) -> Result<Vec<Option<Vec<u8>>>, RuntimeError> {
375 let mut data = caller.user_data_mut();
376 let promise = data.take_promise(promise_id)?;
377
378 data.runtime
379 .read_multi_values_bytes_wait(&promise)
380 .map_err(|error| RuntimeError::Custom(error.into()))
381 }
382
383 fn read_value_bytes_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
385 let mut data = caller.user_data_mut();
386 let promise = data
387 .runtime
388 .read_value_bytes_new(key)
389 .map_err(|error| RuntimeError::Custom(error.into()))?;
390
391 Ok(data.register_promise(promise))
392 }
393
394 fn read_value_bytes_wait(
396 caller: &mut Caller,
397 promise_id: u32,
398 ) -> Result<Option<Vec<u8>>, RuntimeError> {
399 let mut data = caller.user_data_mut();
400 let promise = data.take_promise(promise_id)?;
401
402 data.runtime
403 .read_value_bytes_wait(&promise)
404 .map_err(|error| RuntimeError::Custom(error.into()))
405 }
406
407 fn find_keys_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
409 let mut data = caller.user_data_mut();
410 let promise = data
411 .runtime
412 .find_keys_by_prefix_new(key_prefix)
413 .map_err(|error| RuntimeError::Custom(error.into()))?;
414
415 Ok(data.register_promise(promise))
416 }
417
418 fn find_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<Vec<u8>>, RuntimeError> {
420 let mut data = caller.user_data_mut();
421 let promise = data.take_promise(promise_id)?;
422
423 data.runtime
424 .find_keys_by_prefix_wait(&promise)
425 .map_err(|error| RuntimeError::Custom(error.into()))
426 }
427
428 fn find_key_values_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
430 let mut data = caller.user_data_mut();
431 let promise = data
432 .runtime
433 .find_key_values_by_prefix_new(key_prefix)
434 .map_err(|error| RuntimeError::Custom(error.into()))?;
435
436 Ok(data.register_promise(promise))
437 }
438
439 #[expect(clippy::type_complexity)]
441 fn find_key_values_wait(
442 caller: &mut Caller,
443 promise_id: u32,
444 ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, RuntimeError> {
445 let mut data = caller.user_data_mut();
446 let promise = data.take_promise(promise_id)?;
447
448 data.runtime
449 .find_key_values_by_prefix_wait(&promise)
450 .map_err(|error| RuntimeError::Custom(error.into()))
451 }
452}
453
454#[derive(Default)]
456pub struct ContractRuntimeApi<Caller>(PhantomData<Caller>);
457
458#[wit_export(package = "linera:app")]
459impl<Caller, Runtime> ContractRuntimeApi<Caller>
460where
461 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
462 Runtime: ContractRuntime + 'static,
463{
464 fn authenticated_owner(caller: &mut Caller) -> Result<Option<AccountOwner>, RuntimeError> {
466 caller
467 .user_data_mut()
468 .runtime
469 .authenticated_owner()
470 .map_err(|error| RuntimeError::Custom(error.into()))
471 }
472
473 fn message_is_bouncing(caller: &mut Caller) -> Result<Option<bool>, RuntimeError> {
477 caller
478 .user_data_mut()
479 .runtime
480 .message_is_bouncing()
481 .map_err(|error| RuntimeError::Custom(error.into()))
482 }
483
484 fn message_origin_chain_id(caller: &mut Caller) -> Result<Option<ChainId>, RuntimeError> {
487 caller
488 .user_data_mut()
489 .runtime
490 .message_origin_chain_id()
491 .map_err(|error| RuntimeError::Custom(error.into()))
492 }
493
494 fn authenticated_caller_id(caller: &mut Caller) -> Result<Option<ApplicationId>, RuntimeError> {
496 caller
497 .user_data_mut()
498 .runtime
499 .authenticated_caller_id()
500 .map_err(|error| RuntimeError::Custom(error.into()))
501 }
502
503 fn send_message(
505 caller: &mut Caller,
506 message: SendMessageRequest<Vec<u8>>,
507 ) -> Result<(), RuntimeError> {
508 caller
509 .user_data_mut()
510 .runtime
511 .send_message(message)
512 .map_err(|error| RuntimeError::Custom(error.into()))
513 }
514
515 fn transfer(
518 caller: &mut Caller,
519 source: AccountOwner,
520 destination: Account,
521 amount: Amount,
522 ) -> Result<(), RuntimeError> {
523 caller
524 .user_data_mut()
525 .runtime
526 .transfer(source, destination, amount)
527 .map_err(|error| RuntimeError::Custom(error.into()))
528 }
529
530 fn claim(
532 caller: &mut Caller,
533 source: Account,
534 destination: Account,
535 amount: Amount,
536 ) -> Result<(), RuntimeError> {
537 caller
538 .user_data_mut()
539 .runtime
540 .claim(source, destination, amount)
541 .map_err(|error| RuntimeError::Custom(error.into()))
542 }
543
544 fn approve(
546 caller: &mut Caller,
547 owner: AccountOwner,
548 spender: AccountOwner,
549 amount: Amount,
550 ) -> Result<(), RuntimeError> {
551 caller
552 .user_data_mut()
553 .runtime
554 .approve(owner, spender, amount)
555 .map_err(|error| RuntimeError::Custom(error.into()))
556 }
557
558 fn transfer_from(
560 caller: &mut Caller,
561 owner: AccountOwner,
562 spender: AccountOwner,
563 destination: Account,
564 amount: Amount,
565 ) -> Result<(), RuntimeError> {
566 caller
567 .user_data_mut()
568 .runtime
569 .transfer_from(owner, spender, destination, amount)
570 .map_err(|error| RuntimeError::Custom(error.into()))
571 }
572
573 fn open_chain(
576 caller: &mut Caller,
577 chain_ownership: ChainOwnership,
578 application_permissions: ApplicationPermissions,
579 balance: Amount,
580 ) -> Result<ChainId, RuntimeError> {
581 caller
582 .user_data_mut()
583 .runtime
584 .open_chain(chain_ownership, application_permissions, balance)
585 .map_err(|error| RuntimeError::Custom(error.into()))
586 }
587
588 fn close_chain(caller: &mut Caller) -> Result<Result<(), ManageChainError>, RuntimeError> {
591 match caller.user_data_mut().runtime.close_chain() {
592 Ok(()) => Ok(Ok(())),
593 Err(ExecutionError::UnauthorizedApplication(_)) => {
594 Ok(Err(ManageChainError::NotPermitted))
595 }
596 Err(error) => Err(RuntimeError::Custom(error.into())),
597 }
598 }
599
600 fn change_ownership(
603 caller: &mut Caller,
604 ownership: ChainOwnership,
605 ) -> Result<Result<(), ManageChainError>, RuntimeError> {
606 match caller.user_data_mut().runtime.change_ownership(ownership) {
607 Ok(()) => Ok(Ok(())),
608 Err(ExecutionError::UnauthorizedApplication(_)) => {
609 Ok(Err(ManageChainError::NotPermitted))
610 }
611 Err(error) => Err(RuntimeError::Custom(error.into())),
612 }
613 }
614
615 fn change_application_permissions(
618 caller: &mut Caller,
619 application_permissions: ApplicationPermissions,
620 ) -> Result<Result<(), ManageChainError>, RuntimeError> {
621 match caller
622 .user_data_mut()
623 .runtime
624 .change_application_permissions(application_permissions)
625 {
626 Ok(()) => Ok(Ok(())),
627 Err(ExecutionError::UnauthorizedApplication(_)) => {
628 Ok(Err(ManageChainError::NotPermitted))
629 }
630 Err(error) => Err(RuntimeError::Custom(error.into())),
631 }
632 }
633
634 fn create_application(
637 caller: &mut Caller,
638 module_id: ModuleId,
639 parameters: Vec<u8>,
640 argument: Vec<u8>,
641 required_application_ids: Vec<ApplicationId>,
642 ) -> Result<ApplicationId, RuntimeError> {
643 caller
644 .user_data_mut()
645 .runtime
646 .create_application(module_id, parameters, argument, required_application_ids)
647 .map_err(|error| RuntimeError::Custom(error.into()))
648 }
649
650 fn create_data_blob(caller: &mut Caller, bytes: Vec<u8>) -> Result<DataBlobHash, RuntimeError> {
652 caller
653 .user_data_mut()
654 .runtime
655 .create_data_blob(bytes)
656 .map_err(|error| RuntimeError::Custom(error.into()))
657 }
658
659 fn publish_module(
661 caller: &mut Caller,
662 contract: Bytecode,
663 service: Bytecode,
664 vm_runtime: VmRuntime,
665 ) -> Result<ModuleId, RuntimeError> {
666 caller
667 .user_data_mut()
668 .runtime
669 .publish_module(contract, service, vm_runtime)
670 .map_err(|error| RuntimeError::Custom(error.into()))
671 }
672
673 fn try_call_application(
675 caller: &mut Caller,
676 authenticated: bool,
677 callee_id: ApplicationId,
678 argument: Vec<u8>,
679 ) -> Result<Vec<u8>, RuntimeError> {
680 caller
681 .user_data_mut()
682 .runtime
683 .try_call_application(authenticated, callee_id, argument)
684 .map_err(|error| RuntimeError::Custom(error.into()))
685 }
686
687 fn emit(caller: &mut Caller, name: StreamName, value: Vec<u8>) -> Result<u32, RuntimeError> {
689 caller
690 .user_data_mut()
691 .runtime
692 .emit(name, value)
693 .map_err(|error| RuntimeError::Custom(error.into()))
694 }
695
696 fn read_event(
700 caller: &mut Caller,
701 chain_id: ChainId,
702 name: StreamName,
703 index: u32,
704 ) -> Result<Vec<u8>, RuntimeError> {
705 caller
706 .user_data_mut()
707 .runtime
708 .read_event(chain_id, name, index)
709 .map_err(|error| RuntimeError::Custom(error.into()))
710 }
711
712 fn subscribe_to_events(
714 caller: &mut Caller,
715 chain_id: ChainId,
716 application_id: ApplicationId,
717 name: StreamName,
718 ) -> Result<(), RuntimeError> {
719 caller
720 .user_data_mut()
721 .runtime
722 .subscribe_to_events(chain_id, application_id, name)
723 .map_err(|error| RuntimeError::Custom(error.into()))
724 }
725
726 fn unsubscribe_from_events(
728 caller: &mut Caller,
729 chain_id: ChainId,
730 application_id: ApplicationId,
731 name: StreamName,
732 ) -> Result<(), RuntimeError> {
733 caller
734 .user_data_mut()
735 .runtime
736 .unsubscribe_from_events(chain_id, application_id, name)
737 .map_err(|error| RuntimeError::Custom(error.into()))
738 }
739
740 fn query_service(
742 caller: &mut Caller,
743 application_id: ApplicationId,
744 query: Vec<u8>,
745 ) -> Result<Vec<u8>, RuntimeError> {
746 caller
747 .user_data_mut()
748 .runtime
749 .query_service(application_id, query)
750 .map_err(|error| RuntimeError::Custom(error.into()))
751 }
752
753 fn consume_fuel(caller: &mut Caller, fuel: u64) -> Result<(), RuntimeError> {
758 caller
759 .user_data_mut()
760 .runtime_mut()
761 .consume_fuel(fuel, VmRuntime::Wasm)
762 .map_err(|e| RuntimeError::Custom(e.into()))
763 }
764
765 fn remaining_fuel(caller: &mut Caller) -> Result<u64, RuntimeError> {
767 caller
768 .user_data_mut()
769 .runtime_mut()
770 .remaining_fuel(VmRuntime::Wasm)
771 .map_err(|error| RuntimeError::Custom(error.into()))
772 }
773
774 fn validation_round(caller: &mut Caller) -> Result<Option<u32>, RuntimeError> {
776 caller
777 .user_data_mut()
778 .runtime_mut()
779 .validation_round()
780 .map_err(|error| RuntimeError::Custom(error.into()))
781 }
782
783 fn write_batch(
785 caller: &mut Caller,
786 operations: Vec<WriteOperation>,
787 ) -> Result<(), RuntimeError> {
788 caller
789 .user_data_mut()
790 .runtime_mut()
791 .write_batch(Batch { operations })
792 .map_err(|error| RuntimeError::Custom(error.into()))
793 }
794
795 fn has_empty_storage(
797 caller: &mut Caller,
798 application: ApplicationId,
799 ) -> Result<bool, RuntimeError> {
800 caller
801 .user_data_mut()
802 .runtime_mut()
803 .has_empty_storage(application)
804 .map_err(|error| RuntimeError::Custom(error.into()))
805 }
806}
807
808#[derive(Default)]
810pub struct ServiceRuntimeApi<Caller>(PhantomData<Caller>);
811
812#[wit_export(package = "linera:app")]
813impl<Caller, Runtime> ServiceRuntimeApi<Caller>
814where
815 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
816 Runtime: ServiceRuntime + 'static,
817{
818 fn schedule_operation(caller: &mut Caller, operation: Vec<u8>) -> Result<(), RuntimeError> {
820 caller
821 .user_data_mut()
822 .runtime
823 .schedule_operation(operation)
824 .map_err(|error| RuntimeError::Custom(error.into()))
825 }
826
827 fn try_query_application(
829 caller: &mut Caller,
830 application: ApplicationId,
831 argument: Vec<u8>,
832 ) -> Result<Vec<u8>, RuntimeError> {
833 caller
834 .user_data_mut()
835 .runtime
836 .try_query_application(application, argument)
837 .map_err(|error| RuntimeError::Custom(error.into()))
838 }
839
840 #[expect(unused_variables)]
845 fn check_execution_time(caller: &mut Caller, fuel_consumed: u64) -> Result<(), RuntimeError> {
846 caller
847 .user_data_mut()
848 .runtime_mut()
849 .check_execution_time()
850 .map_err(|error| RuntimeError::Custom(error.into()))
851 }
852}