Skip to content

Commit

Permalink
WASM wrappers for chain utility functionality
Browse files Browse the repository at this point in the history
Wrappers around custom-written code written earlier for the rust crate.
  • Loading branch information
rooooooooob committed May 31, 2023
1 parent 99ffb1c commit 22de0c5
Show file tree
Hide file tree
Showing 9 changed files with 595 additions and 0 deletions.
7 changes: 7 additions & 0 deletions chain/rust/src/plutus/utils.rs
Expand Up @@ -339,6 +339,13 @@ impl PlutusScript {
Self::PlutusV2(script) => script.hash(),
}
}

pub fn version(&self) -> Language {
match self {
Self::PlutusV1(_) => Language::PlutusV1,
Self::PlutusV2(_) => Language::PlutusV2,
}
}
}
use cml_crypto::ScriptHash;
use crate::crypto::hash::{hash_script, ScriptHashNamespace};
Expand Down
65 changes: 65 additions & 0 deletions chain/wasm/src/assets/mod.rs
@@ -0,0 +1,65 @@
use wasm_bindgen::prelude::{wasm_bindgen, JsValue};

pub mod utils;

pub use utils::{Mint, MultiAsset, Value};

pub use cml_chain::assets::Coin;

// Code below here was code-generated using an experimental CDDL to rust tool:
// https://github.com/dcSpark/cddl-codegen

#[derive(Clone, Debug)]
#[wasm_bindgen]
pub struct AssetName(cml_chain::assets::AssetName);

#[wasm_bindgen]
impl AssetName {
pub fn to_cbor_bytes(&self) -> Vec<u8> {
cml_chain::serialization::Serialize::to_cbor_bytes(&self.0)
}

pub fn from_cbor_bytes(cbor_bytes: &[u8]) -> Result<AssetName, JsValue> {
cml_chain::serialization::Deserialize::from_cbor_bytes(cbor_bytes)
.map(Self)
.map_err(|e| JsValue::from_str(&format!("from_bytes: {}", e)))
}

pub fn to_json(&self) -> Result<String, JsValue> {
serde_json::to_string_pretty(&self.0)
.map_err(|e| JsValue::from_str(&format!("to_json: {}", e)))
}

pub fn to_json_value(&self) -> Result<JsValue, JsValue> {
serde_wasm_bindgen::to_value(&self.0)
.map_err(|e| JsValue::from_str(&format!("to_js_value: {}", e)))
}

pub fn from_json(json: &str) -> Result<AssetName, JsValue> {
serde_json::from_str(json)
.map(Self)
.map_err(|e| JsValue::from_str(&format!("from_json: {}", e)))
}

pub fn get(&self) -> Vec<u8> {
self.0.get().clone()
}
}

impl From<cml_chain::assets::AssetName> for AssetName {
fn from(native: cml_chain::assets::AssetName) -> Self {
Self(native)
}
}

impl From<AssetName> for cml_chain::assets::AssetName {
fn from(wasm: AssetName) -> Self {
wasm.0
}
}

impl AsRef<cml_chain::assets::AssetName> for AssetName {
fn as_ref(&self) -> &cml_chain::assets::AssetName {
&self.0
}
}
200 changes: 200 additions & 0 deletions chain/wasm/src/assets/utils.rs
@@ -0,0 +1,200 @@
use std::ops::Deref;

use wasm_bindgen::{prelude::wasm_bindgen, JsError};
use crate::{PolicyId, MapAssetNameToI64, PolicyIdList, assets::AssetName, AssetNameList};

use cml_core_wasm::{impl_wasm_map, impl_wasm_conversions};

use super::Coin;

impl_wasm_map!(
cml_chain::AssetName, Coin,
AssetName, Coin,
AssetNameList,
MapAssetNameToCoin
);

#[derive(Clone, Debug)]
#[wasm_bindgen]
pub struct MultiAsset(cml_chain::assets::MultiAsset);

#[wasm_bindgen]
impl MultiAsset {
pub fn new() -> Self {
Self(cml_chain::assets::MultiAsset::default())
}

pub fn policy_count(&self) -> usize {
self.0.len()
}

pub fn insert_assets(
&mut self,
policy_id: &PolicyId,
assets: &MapAssetNameToCoin,
) -> Option<MapAssetNameToCoin> {
self.0
.insert(policy_id.clone().into(), assets.clone().into())
.map(Into::into)
}

pub fn get_assets(&self, key: &PolicyId) -> Option<MapAssetNameToCoin> {
self.0.deref().get(key.as_ref()).map(|v| v.clone().into())
}

/// Get the value of policy_id:asset_name if it exists.
pub fn get(&self, policy_id: &PolicyId, asset: &AssetName) -> Option<Coin> {
self.0.get(policy_id.as_ref(), asset.as_ref())
}

/// Set the value of policy_id:asset_name to value.
/// Returns the previous value, or None if it didn't exist
pub fn set(&mut self, policy_id: &PolicyId, asset: &AssetName, value: Coin) -> Option<Coin> {
self.0.set(policy_id.clone().into(), asset.clone().into(), value)
}

pub fn keys(&self) -> PolicyIdList {
PolicyIdList(self.0.iter().map(|(k, _v)| k.clone()).collect::<Vec<_>>())
}

/// Adds to multiassets together, checking value bounds.
/// Does not modify self, and instead returns the result.
pub fn checked_add(&self, rhs: &MultiAsset) -> Result<MultiAsset, JsError> {
self.0.checked_add(rhs.as_ref())
.map(Into::into)
.map_err(Into::into)
}

/// Subtracts rhs from this multiasset.
/// This does not modify self, and instead returns the result.
/// If this would cause there to be fewer than 0 of a given asset
/// an error will be returned.
/// Use clamped_sub if you need to only try to remove assets when they exist
/// and ignore them when they don't.
pub fn checked_sub(&self, rhs: &MultiAsset) -> Result<MultiAsset, JsError> {
self.0.checked_sub(rhs.as_ref())
.map(Into::into)
.map_err(Into::into)
}

/// Sybtracts rhs from this multiasset.
/// If this would cause there to be 0 or fewer of a given asset
/// it will simply be removed entirely from the result.
pub fn clamped_sub(&self, rhs: &MultiAsset) -> Self {
use cml_chain::assets::ClampedSub;
self.0.clamped_sub(rhs.as_ref()).into()
}
}

impl_wasm_conversions!(cml_chain::assets::MultiAsset, MultiAsset);

#[derive(Clone, Debug)]
#[wasm_bindgen]
pub struct Mint(cml_chain::assets::Mint);

#[wasm_bindgen]
impl Mint {
pub fn new() -> Self {
Self(cml_chain::assets::Mint::default())
}

pub fn policy_count(&self) -> usize {
self.0.len()
}

pub fn insert_assets(
&mut self,
policy_id: &PolicyId,
assets: &MapAssetNameToI64,
) -> Option<MapAssetNameToI64> {
self.0
.insert(policy_id.clone().into(), assets.clone().into())
.map(Into::into)
}

pub fn get_assets(&self, key: &PolicyId) -> Option<MapAssetNameToI64> {
self.0.deref().get(key.as_ref()).map(|v| v.clone().into())
}

/// Get the value of policy_id:asset_name if it exists.
pub fn get(&self, policy_id: &PolicyId, asset: &AssetName) -> Option<i64> {
self.0.get(policy_id.as_ref(), asset.as_ref())
}

/// Set the value of policy_id:asset_name to value.
/// Returns the previous value, or None if it didn't exist
pub fn set(&mut self, policy_id: &PolicyId, asset: &AssetName, value: i64) -> Option<i64> {
self.0.set(policy_id.clone().into(), asset.clone().into(), value)
}

pub fn keys(&self) -> PolicyIdList {
PolicyIdList(self.0.iter().map(|(k, _v)| k.clone()).collect::<Vec<_>>())
}

/// Adds two mints together, checking value bounds.
/// Does not modify self, and instead returns the result.
pub fn checked_add(&self, rhs: &Mint) -> Result<Mint, JsError> {
self.0.checked_add(rhs.as_ref())
.map(Into::into)
.map_err(Into::into)
}

/// Subtracts rhs from this mint.
/// This does not modify self, and instead returns the result.
pub fn checked_sub(&self, rhs: &Mint) -> Result<Mint, JsError> {
self.0.checked_sub(rhs.as_ref())
.map(Into::into)
.map_err(Into::into)
}
}

impl_wasm_conversions!(cml_chain::assets::Mint, Mint);

#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct Value(cml_chain::assets::Value);

#[wasm_bindgen]
impl Value {
pub fn from_coin(coin: Coin) -> Self {
cml_chain::assets::Value::from(coin).into()
}

pub fn new(coin: Coin, multiasset: &MultiAsset) -> Self {
cml_chain::assets::Value::new(coin, multiasset.clone().into()).into()
}

pub fn zero() -> Value {
cml_chain::assets::Value::zero().into()
}

pub fn is_zero(&self) -> bool {
self.0.is_zero()
}

pub fn has_multiassets(&self) -> bool {
self.0.has_multiassets()
}

pub fn checked_add(&self, rhs: &Value) -> Result<Value, JsError> {
self.0.checked_add(rhs.as_ref())
.map(Into::into)
.map_err(Into::into)
}

/// Subtract ADA and/or assets
/// Removes an asset from the list if the result is 0 or less
/// Does not modify this object, instead the result is returned
/// None is returned if there would be integer underflow
pub fn checked_sub(&self, rhs: &Value) -> Result<Value, JsError> {
self.0.checked_sub(rhs.as_ref())
.map(Into::into)
.map_err(Into::into)
}

pub fn clamped_sub(&self, rhs: &Value) -> Value {
self.0.clamped_sub(rhs.as_ref()).into()
}
}

impl_wasm_conversions!(cml_chain::assets::Value, Value);
56 changes: 56 additions & 0 deletions chain/wasm/src/auxdata/utils.rs
@@ -0,0 +1,56 @@
use cml_core_wasm::metadata::Metadata;
use wasm_bindgen::prelude::wasm_bindgen;
use crate::{NativeScriptList, PlutusV1ScriptList, PlutusV2ScriptList};

use super::AuxiliaryData;

#[wasm_bindgen]
impl AuxiliaryData {
pub fn new() -> Self {
cml_chain::auxdata::AuxiliaryData::new().into()
}

pub fn metadata(&self) -> Option<Metadata> {
self.0.metadata().map(|m| m.clone().into())
}

pub fn native_scripts(&self) -> Option<NativeScriptList> {
self.0.native_scripts().cloned().map(Into::into)
}

pub fn plutus_v1_scripts(&self) -> Option<PlutusV1ScriptList> {
self.0.plutus_v1_scripts().cloned().map(Into::into)
}

pub fn plutus_v2_scripts(&self) -> Option<PlutusV2ScriptList> {
self.0.plutus_v2_scripts().cloned().map(Into::into)
}

/// Warning: overwrites any conflicting metadatum labels present
pub fn add_metadata(&mut self, other: &Metadata) {
self.0.add_metadata(other.clone().into())
}

/// Warning: does not check for duplicates and may migrate eras
pub fn add_native_scripts(&mut self, scripts: &NativeScriptList) {
self.0.add_native_scripts(scripts.clone().into())
}

/// Warning: does not check for duplicates and may migrate eras
pub fn add_plutus_v1_scripts(&mut self, scripts: &PlutusV1ScriptList) {
self.0.add_plutus_v1_scripts(scripts.clone().into())
}

/// Warning: does not check for duplicates and may migrate eras
pub fn add_plutus_v2_scripts(&mut self, scripts: &PlutusV2ScriptList) {
self.0.add_plutus_v2_scripts(scripts.clone().into())
}

/// Adds everything present in other to self
/// May change the era the aux data is in if necessary
/// Warning: overwrites any metadatum labels present
/// also does not check for duplicates in scripts
pub fn add(&mut self, other: &AuxiliaryData) {
self.0.add(other.clone().into())
}
}
10 changes: 10 additions & 0 deletions chain/wasm/src/certs/utils.rs
@@ -0,0 +1,10 @@
use wasm_bindgen::prelude::wasm_bindgen;
use super::StakeCredential;

#[wasm_bindgen]
impl StakeCredential {
// we don't implement RawBytesEncoding as from_raw_bytes() would be unable to distinguish
pub fn to_raw_bytes(&self) -> Vec<u8> {
self.0.to_raw_bytes().into()
}
}

0 comments on commit 22de0c5

Please sign in to comment.