use linera_base::{
crypto::CryptoHash,
data_types::{
Amount, ApplicationDescription, ApplicationPermissions, BlockHeight, TimeDelta, Timestamp,
},
http,
identifiers::{AccountOwner, ApplicationId, ChainId, DataBlobHash, ModuleId},
ownership::{ChainOwnership, TimeoutConfig},
vm::VmRuntime,
};
use crate::{
contract::wit::base_runtime_api as base_contract_api,
service::wit::base_runtime_api as base_service_api,
};
macro_rules! impl_from_wit {
($wit_base_api:ident) => {
impl From<$wit_base_api::CryptoHash> for CryptoHash {
fn from(hash_value: $wit_base_api::CryptoHash) -> Self {
CryptoHash::from([
hash_value.part1,
hash_value.part2,
hash_value.part3,
hash_value.part4,
])
}
}
impl From<$wit_base_api::DataBlobHash> for DataBlobHash {
fn from(hash_value: $wit_base_api::DataBlobHash) -> Self {
DataBlobHash(hash_value.inner0.into())
}
}
impl From<$wit_base_api::Array20> for [u8; 20] {
fn from(ethereum_address: $wit_base_api::Array20) -> Self {
let mut bytes = [0u8; 20];
bytes[0..8].copy_from_slice(ðereum_address.part1.to_be_bytes());
bytes[8..16].copy_from_slice(ðereum_address.part2.to_be_bytes());
bytes[16..20].copy_from_slice(ðereum_address.part3.to_be_bytes()[0..4]);
bytes
}
}
impl From<$wit_base_api::AccountOwner> for AccountOwner {
fn from(account_owner: $wit_base_api::AccountOwner) -> Self {
match account_owner {
$wit_base_api::AccountOwner::Reserved(value) => AccountOwner::Reserved(value),
$wit_base_api::AccountOwner::Address32(value) => {
AccountOwner::Address32(value.into())
}
$wit_base_api::AccountOwner::Address20(value) => {
AccountOwner::Address20(value.into())
}
}
}
}
impl From<$wit_base_api::Amount> for Amount {
fn from(balance: $wit_base_api::Amount) -> Self {
let (lower_half, upper_half) = balance.inner0;
let value = ((upper_half as u128) << 64) | (lower_half as u128);
Amount::from_attos(value)
}
}
impl From<$wit_base_api::BlockHeight> for BlockHeight {
fn from(block_height: $wit_base_api::BlockHeight) -> Self {
BlockHeight(block_height.inner0)
}
}
impl From<$wit_base_api::ChainId> for ChainId {
fn from(chain_id: $wit_base_api::ChainId) -> Self {
ChainId(chain_id.inner0.into())
}
}
impl From<$wit_base_api::ApplicationId> for ApplicationId {
fn from(application_id: $wit_base_api::ApplicationId) -> Self {
ApplicationId::new(application_id.application_description_hash.into())
}
}
impl From<$wit_base_api::Timestamp> for Timestamp {
fn from(timestamp: $wit_base_api::Timestamp) -> Self {
Timestamp::from(timestamp.inner0)
}
}
impl From<$wit_base_api::TimeDelta> for TimeDelta {
fn from(guest: $wit_base_api::TimeDelta) -> Self {
TimeDelta::from_micros(guest.inner0)
}
}
impl From<$wit_base_api::TimeoutConfig> for TimeoutConfig {
fn from(guest: $wit_base_api::TimeoutConfig) -> TimeoutConfig {
let $wit_base_api::TimeoutConfig {
fast_round_duration,
base_timeout,
timeout_increment,
fallback_duration,
} = guest;
TimeoutConfig {
fast_round_duration: fast_round_duration.map(TimeDelta::from),
base_timeout: base_timeout.into(),
timeout_increment: timeout_increment.into(),
fallback_duration: fallback_duration.into(),
}
}
}
impl From<$wit_base_api::ChainOwnership> for ChainOwnership {
fn from(guest: $wit_base_api::ChainOwnership) -> ChainOwnership {
let $wit_base_api::ChainOwnership {
super_owners,
owners,
multi_leader_rounds,
open_multi_leader_rounds,
timeout_config,
} = guest;
ChainOwnership {
super_owners: super_owners.into_iter().map(Into::into).collect(),
owners: owners
.into_iter()
.map(|(owner, weight)| (owner.into(), weight))
.collect(),
multi_leader_rounds,
open_multi_leader_rounds,
timeout_config: timeout_config.into(),
}
}
}
impl From<$wit_base_api::ApplicationPermissions> for ApplicationPermissions {
fn from(guest: $wit_base_api::ApplicationPermissions) -> ApplicationPermissions {
let $wit_base_api::ApplicationPermissions {
execute_operations,
mandatory_applications,
close_chain,
change_application_permissions,
call_service_as_oracle,
make_http_requests,
} = guest;
ApplicationPermissions {
execute_operations: execute_operations
.map(|apps| apps.into_iter().map(Into::into).collect()),
mandatory_applications: mandatory_applications
.into_iter()
.map(Into::into)
.collect(),
close_chain: close_chain.into_iter().map(Into::into).collect(),
change_application_permissions: change_application_permissions
.into_iter()
.map(Into::into)
.collect(),
call_service_as_oracle: call_service_as_oracle
.map(|apps| apps.into_iter().map(Into::into).collect()),
make_http_requests: make_http_requests
.map(|apps| apps.into_iter().map(Into::into).collect()),
}
}
}
impl From<$wit_base_api::HttpResponse> for http::Response {
fn from(response: $wit_base_api::HttpResponse) -> http::Response {
http::Response {
status: response.status,
headers: response
.headers
.into_iter()
.map(http::Header::from)
.collect(),
body: response.body,
}
}
}
impl From<$wit_base_api::HttpHeader> for http::Header {
fn from(header: $wit_base_api::HttpHeader) -> http::Header {
http::Header::new(header.name, header.value)
}
}
impl From<$wit_base_api::VmRuntime> for VmRuntime {
fn from(vm_runtime: $wit_base_api::VmRuntime) -> Self {
match vm_runtime {
$wit_base_api::VmRuntime::Wasm => VmRuntime::Wasm,
$wit_base_api::VmRuntime::Evm => VmRuntime::Evm,
}
}
}
impl From<$wit_base_api::ModuleId> for ModuleId {
fn from(module_id: $wit_base_api::ModuleId) -> Self {
ModuleId::new(
module_id.contract_blob_hash.into(),
module_id.service_blob_hash.into(),
module_id.vm_runtime.into(),
)
}
}
impl From<$wit_base_api::ApplicationDescription> for ApplicationDescription {
fn from(description: $wit_base_api::ApplicationDescription) -> Self {
ApplicationDescription {
module_id: description.module_id.into(),
creator_chain_id: description.creator_chain_id.into(),
block_height: description.block_height.into(),
application_index: description.application_index,
parameters: description.parameters,
required_application_ids: description
.required_application_ids
.into_iter()
.map(Into::into)
.collect(),
}
}
}
};
}
impl_from_wit!(base_service_api);
impl_from_wit!(base_contract_api);