### Install Rust and WASM Build Tools Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/README.rst This script installs Rust using rustup, sets up the environment path, installs the stable toolchain, adds the wasm32-unknown-unknown target, and installs wasm-pack. These tools are necessary for building Rust projects for WebAssembly. ```shell curl https://sh.rustup.rs -sSf | sh -s -- -y echo 'export PATH=$HOME/.cargo/bin/:$PATH' >> $BASH_ENV rustup install stable rustup target add wasm32-unknown-unknown --toolchain stable curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh ``` -------------------------------- ### Install CDDL Tools Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/specs/README.md Installs the necessary tools for working with CDDL specifications, including ruby, cddl, and cbor-diag. This is a prerequisite for generating CDDL instances. ```bash sudo apt install ruby sudo gem install cddl sudo gem install cbor-diag ``` -------------------------------- ### Build Cardano Transaction with Key Inputs using JavaScript Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/builders/generating_transactions.mdx This snippet demonstrates how to build a Cardano transaction with key and bootstrap inputs using JavaScript and the cardano-multiplatform-lib. It includes adding inputs and outputs, automatically calculating fees, and sending change to a specified address. The example uses predefined protocol parameters and keys. ```javascript // instantiate the tx builder with the Cardano protocol parameters - these may change later on const txBuilder = makeTxBuilder(); const testnetId = 0; // add a keyhash input - for ADA held in a Shelley-era normal address (Base, Enterprise, Pointer) const prvKey = CML.PrivateKey.from_bech32("ed25519e_sk16rl5fqqf4mg27syjzjrq8h3vq44jnnv52mvyzdttldszjj7a64xtmjwgjtfy25lu0xmv40306lj9pcqpa6slry9eh3mtlqvfjz93vuq0grl80"); const inputAddr = CML.EnterpriseAddress.new(testnetId, CML.StakeCredential.new_key(prvKey.to_public().hash())).to_address(); txBuilder.add_input(CML.SingleInputBuilder.new( CML.TransactionInput.new( CML.TransactionHash.from_hex("8561258e210352fba2ac0488afed67b3427a27ccf1d41ec030c98a8199bc22ec"), // tx hash 0, // index ), CML.TransactionOutput.new( inputAddr, CML.Value.from_coin(BigInt(6000000)), ) )); // base address const outputAddress = CML.Address.from_bech32("addr_test1qpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5ewvxwdrt70qlcpeeagscasafhffqsxy36t90ldv06wqrk2qum8x5w"); // pointer address const changeAddress = CML.Address.from_bech32("addr_test1gz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerspqgpsqe70et"); // add output to the tx txBuilder.add_output( CML.TransactionOutputBuilder() .with_address(outputAddress) .next() .with_value(CML.Value.from_coin(BigInt(1000000))) .build() ); // calculate the min fee required and send any change to an address // this moves onto the next step of building the transaction: providing witnesses const signedTxBuilder = tx_builder.build( changeAddress, CML.ChangeSelectionAlgo.Default ); // sign with the key that owns the input used signedTxBuilder.add_vkey(CML.make_vkey_witness(txHash, prvKey)); const tx = signedTxBuilder.build_checked(); // ready to submit, can be converted to CBOR via tx.to_cbor_bytes() or to_cbor_hex() for hex ``` -------------------------------- ### CDDL Example: Tagged Constructor (Arbitrary Variant) Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/tools/plutus-datum-codegen/README.md CDDL example illustrating a tagged constructor with an arbitrary variant and generic format. It includes fields for 'variant' (uint) and 'fields' (an array of 'abc' structures). ```cddl ; tagged constructor (arbitrary variant, generic format) bar = #6.102([ variant: uint, fields: [* abc] ]) ``` -------------------------------- ### CDDL Example: Tagged Constructor (UTF8 Text) Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/tools/plutus-datum-codegen/README.md CDDL example demonstrating a tagged constructor where the user-facing type is text, but on-chain it's serialized as UTF8 bytes. It uses the 'utf8_text' alias. ```cddl ; tagged constructor (variant 2, concise fixed format) ; note that to the user this will be text, but on-chain it will be serialized to utf8 bytes foo = #6.123([* utf8_text]) ``` -------------------------------- ### Perform Multi-Asset Value Operations with Cardano Multiplatform Lib Source: https://context7.com/dcspark/cardano-multiplatform-lib/llms.txt This TypeScript example demonstrates how to create and perform arithmetic operations on multi-asset values, including native tokens and ADA, using the Cardano Multiplatform Library. It showcases addition, subtraction, comparison, and calculating minimum ADA requirements. Ensure the '@dcspark/cardano-multiplatform-lib-nodejs' package is installed. ```typescript import * as CML from '@dcspark/cardano-multiplatform-lib-nodejs'; // Create multi-asset value with ADA and tokens const policyId1 = CML.ScriptHash.from_hex('abc123...'); const policyId2 = CML.ScriptHash.from_hex('def456...'); const multiAsset = CML.MultiAsset.new(); // Add tokens from policy 1 const assets1 = CML.Assets.new(); assets1.insert( CML.AssetName.new(Buffer.from('TokenA')), CML.BigNum.from_str('1000') ); assets1.insert( CML.AssetName.new(Buffer.from('TokenB')), CML.BigNum.from_str('5000') ); multiAsset.insert(policyId1, assets1); // Add tokens from policy 2 const assets2 = CML.Assets.new(); assets2.insert( CML.AssetName.new(Buffer.from('NFT001')), CML.BigNum.from_str('1') ); multiAsset.insert(policyId2, assets2); // Create value with 10 ADA + tokens const value1 = CML.Value.new(CML.BigNum.from_str('10000000'), multiAsset); // Create another value const value2 = CML.Value.new_from_assets(multiAsset2); // Add values (throws on overflow) try { const sum = value1.checked_add(value2); console.log('Total ADA:', sum.coin().to_str()); // Access specific asset const tokenAAmount = sum.multiasset() .get(policyId1) .get(CML.AssetName.new(Buffer.from('TokenA'))); console.log('TokenA amount:', tokenAAmount.to_str()); } catch (error) { console.error('Arithmetic overflow:', error); } // Subtract values (throws if result would be negative) try { const difference = value1.checked_sub(value2); } catch (error) { console.error('Insufficient funds:', error); } // Compare values const isGreater = value1.compare(value2) > 0; // Calculate minimum ADA for output with tokens const minAda = CML.min_ada_required( CML.TransactionOutput.new(address, value1, undefined, undefined), CML.BigNum.from_str('4310') // coins_per_utxo_byte ); console.log('Minimum ADA required:', minAda.to_str()); // Returns: "1500000" (1.5 ADA minimum for this output) ``` -------------------------------- ### Test Cardano Multiplatform Lib Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/README.rst This command executes the test suite for the Cardano Multiplatform Lib. It is used to verify the correctness and stability of the library's functionalities. Ensure all dependencies are installed before running tests. ```shell npm run rust:test ``` -------------------------------- ### Build NodeJS WASM Package for Cardano Multiplatform Lib Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/README.rst This command builds the WASM package for NodeJS, enabling the use of the Cardano Multiplatform Lib in Node.js environments. It requires Node.js and npm to be installed. ```shell git submodule update --init --recursive nvm use npm install npm run rust:build-nodejs ``` -------------------------------- ### Create PlutusData Constructor - JavaScript Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/cbor.mdx Demonstrates creating a PlutusData constructor with a byte string. This example highlights a common scenario where different CBOR encodings can lead to different binary representations and subsequently different hashes. ```javascript let datum = PlutusData.new_constr_plutus_data(ConstrPlutusData.new(0, [PlutusData.new_bytes(0xDE, 0xAD, 0xBE, 0xEF)])); ``` -------------------------------- ### JavaScript Metadata Serialization Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/metadata.mdx Example of how to use the generated Wasm library in JavaScript to create and serialize structured metadata. It demonstrates adding integers and BigNums to a list and constructing a 'Foo' object. ```javascript const tags = OurMetadataLib.Ints.new(); tags.add(OurMetadataLib.Int.new_i32(0)); tags.add(OurMetadataLib.Int.new(CardanoWasm.Int.from_str("264"))); tags.add(OurMetadataLib.Int.new_negative(CardanoWasm.Int.from_str("1024"))); tags.add(OurMetadataLib.Int.new_i32(32)); const map = OurMetadataLib.Foo.new("SJKdj34k3jjKFDKfjFUDfdjkfd", "jkfdsufjdk34h3Sdfjdhfduf873", "happy birthday", tags) let metadata; try { metadata = CardanoWasm.TransactionMetadata.from_bytes(map.to_bytes()); } catch (e) { // this should never happen if OurMetadataLib was generated from compatible CDDL with the metadata definition } ``` -------------------------------- ### CDDL Example: Struct with Bounded Bytes Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/tools/plutus-datum-codegen/README.md CDDL example defining a regular array datum with a forced struct structure. It uses the 'bounded_bytes' alias for byte fields, ensuring they are chunked into <=64-byte chunks, which is an encoding detail but still represents regular bytes. ```cddl ; regular array datum, but with specific struct structure forced on top abc = [ ; note that we MUST use bounded_bytes not regular bytes ; this is only an encoding detail (chunked into <=64-byte chunks) ; it is still regular bytes x: bounded_bytes, y: [* utf8_text], ] ``` -------------------------------- ### Generate Cardano Addresses from Mnemonic (TypeScript) Source: https://context7.com/dcspark/cardano-multiplatform-lib/llms.txt This TypeScript code demonstrates deriving Cardano addresses (base, enterprise, reward) from a BIP39 mnemonic. It utilizes the @dcspark/cardano-multiplatform-lib-nodejs library for key derivation and address creation, following CIP-1852 standards. Ensure 'bip39' and '@dcspark/cardano-multiplatform-lib-nodejs' are installed. ```typescript import * as CML from '@dcspark/cardano-multiplatform-lib-nodejs'; import { mnemonicToEntropy } from 'bip39'; const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; const entropy = Buffer.from(mnemonicToEntropy(mnemonic), 'hex'); const password = Buffer.from(''); // Generate root key from mnemonic const rootKey = CML.Bip32PrivateKey.from_bip39_entropy(entropy, password); // CIP-1852 derivation: m/1852'/1815'/account' const harden = (num) => 0x80000000 + num; const accountIndex = 0; const accountKey = rootKey .derive(harden(1852)) // Purpose: Cardano .derive(harden(1815)) // Coin type: ADA .derive(harden(accountIndex)); // Derive payment key: m/1852'/1815'/0'/0/index const paymentKey = accountKey .derive(0) // External chain .derive(0) // Address index .to_public(); // Derive stake key: m/1852'/1815'/0'/2/0 const stakeKey = accountKey .derive(2) // Stake chain .derive(0) .to_public(); // Create base address (mainnet) const networkId = CML.NetworkId.mainnet(); const baseAddr = CML.BaseAddress.new( networkId, CML.StakeCredential.from_keyhash(paymentKey.to_raw_key().hash()), CML.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash()) ); const address = baseAddr.to_address(); const bech32Address = address.to_bech32(); // Returns: "addr1q9xyzcustomaddress..." // Create enterprise address (no staking) const enterpriseAddr = CML.EnterpriseAddress.new( networkId, CML.StakeCredential.from_keyhash(paymentKey.to_raw_key().hash()) ); const enterpriseBech32 = enterpriseAddr.to_address().to_bech32(); // Returns: "addr1vxyzcustomaddress..." // Create reward address (staking rewards) const rewardAddr = CML.RewardAddress.new( networkId, CML.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash()) ); const stakeBech32 = rewardAddr.to_address().to_bech32(); // Returns: "stake1uxyzcustomaddress..." ``` -------------------------------- ### JavaScript Metadata Deserialization Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/metadata.mdx Example of how to deserialize Cardano metadata bytes back into a structured object using the generated Wasm library in JavaScript. It shows parsing bytes and accessing fields. ```javascript let cddlMetadata; try { cddlMetadata = OurMetadataLib.Foo.from_bytes(metadata.to_bytes()); } catch (e) { // this should never happen if OurMetadataLib was generated from compatible CDDL with the metadata definition } // we can now directly access the fields with cddlMetadata.receiver_id(), etc ``` -------------------------------- ### Example JSON Transaction Metadata Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/metadata.mdx Illustrates a typical JSON object that could be used as transaction metadata. This structure includes fields for receiver ID, sender ID, a comment, and tags, demonstrating a common use case for metadata. ```json { "receiver_id": "SJKdj34k3jjKFDKfjFUDfdjkfd", "sender_id": "jkfdsufjdk34h3Sdfjdhfduf873", "comment": "happy birthday", "tags": [0, 264, -1024, 32] } ``` -------------------------------- ### Mint Native Tokens and NFTs with Cardano Multiplatform Library (TypeScript) Source: https://context7.com/dcspark/cardano-multiplatform-lib/llms.txt This snippet demonstrates minting native tokens or NFTs using native scripts with policy locking and CIP-25 compliant metadata. It covers generating policy keys, creating time-locked policies, building the transaction with minting operations, adding NFT metadata, specifying recipient outputs, and signing the transaction. Dependencies include `@dcspark/cardano-multiplatform-lib-browser` and `@dcspark/cardano-multiplatform-lib-cip25`. ```typescript import * as CML from '@dcspark/cardano-multiplatform-lib-browser'; import * as CIP25 from '@dcspark/cardano-multiplatform-lib-cip25'; // Create policy script (must sign with this key) const policyPrivateKey = CML.PrivateKey.generate_ed25519(); const policyPublicKey = policyPrivateKey.to_public(); const policyKeyHash = policyPublicKey.hash(); // Create time-locked policy (locks after slot 100000000) const scriptPubkey = CML.NativeScript.new_script_pubkey(policyKeyHash); const scriptTimelock = CML.NativeScript.new_script_invalid_hereafter( CML.BigNum.from_str('100000000') ); const scripts = CML.NativeScriptList.new(); scripts.add(scriptPubkey); scripts.add(scriptTimelock); const policyScript = CML.NativeScript.new_script_all(scripts); const policyId = policyScript.hash(); // Build transaction with minting const txBuilder = CML.TransactionBuilder.new(config); // Assuming 'config' is defined elsewhere // Add UTXOs for fees for (const utxo of utxos) { // Assuming 'utxos' is defined elsewhere txBuilder.add_utxo( CML.SingleInputBuilder .from_transaction_unspent_output(utxo) .payment_key() ); } // Create mint operation const assetName = CML.AssetName.from_str('MyNFT001'); const mintBuilder = CML.SingleMintBuilder.new_single_asset( assetName, CML.Int.new_i32(1) // Mint 1 token (negative to burn) ); // Add native script witness const vkeys = CML.Ed25519KeyHashList.new(); vkeys.add(policyKeyHash); const witnessInfo = CML.NativeScriptWitnessInfo.vkeys(vkeys); const mintResult = mintBuilder.native_script(policyScript, witnessInfo); txBuilder.add_mint(mintResult); // Add CIP-25 NFT metadata const labelMd = CIP25.LabelMetadata.new(CIP25.CIP25Version.V2); const mdDetails = CIP25.MetadataDetails.new( CIP25.String64.new('My NFT #001'), CIP25.ChunkableString.from_string('ipfs://QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG') ); // Optional: add description, media type, files mdDetails.set_description( CIP25.ChunkableString.from_string('A beautiful NFT created with CML') ); mdDetails.set_media_type(CIP25.String64.new('image/png')); labelMd.set( CIP25.ScriptHash.from_raw_bytes(policyId.to_raw_bytes()), CIP25.AssetName.from_bytes(assetName.get()), mdDetails ); const metadata = CIP25.CIP25Metadata.new(labelMd); const auxData = CIP25.AuxiliaryData.new_shelley(metadata.to_metadata()); txBuilder.set_auxiliary_data( CML.AuxiliaryData.from_cbor_bytes(auxData.to_cbor_bytes()) ); // Output to recipient (must include minted token) const multiAsset = CML.MultiAsset.new(); const assets = CML.Assets.new(); assets.insert(assetName, CML.BigNum.from_str('1')); multiAsset.insert(policyId, assets); const recipientAddr = CML.Address.from_bech32('addr1q9xyz...'); // Replace with actual address const outputValue = CML.Value.new( CML.BigNum.from_str('2000000'), // Minimum ADA multiAsset ); const output = CML.TransactionOutputBuilder.new() .with_address(recipientAddr) .next() .with_value(outputValue) .build(); txBuilder.add_output(output.output); // Select UTXOs and build txBuilder.select_utxos(CML.CoinSelectionStrategyCIP2.LargestFirstMultiAsset); const txBody = txBuilder.build(CML.ChangeSelectionAlgo.Default, changeAddr); // Assuming 'changeAddr' is defined elsewhere // Sign with both payment key and policy key const witnessSet = CML.TransactionWitnessSet.new(); const vkeyWitnesses = CML.Vkeywitnesses.new(); vkeyWitnesses.add(CML.make_vkey_witness(CML.hash_transaction(txBody.body()), paymentPrivateKey)); // Assuming 'paymentPrivateKey' is defined elsewhere vkeyWitnesses.add(CML.make_vkey_witness(CML.hash_transaction(txBody.body()), policyPrivateKey)); witnessSet.set_vkeys(vkeyWitnesses); witnessSet.set_native_scripts(CML.NativeScriptList.from([policyScript])); const signedTx = CML.Transaction.new(txBody.body(), witnessSet, true, txBody.auxiliary_data()); // Submit transaction to mint NFT (submission logic not shown) ``` -------------------------------- ### Run Plutus Datum Codegen Tool Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/tools/plutus-datum-codegen/README.md Command to execute the Plutus Datum Codegen tool. It requires input CDDL file, output directory, path to cddl-codegen, and a library name. The tool supports single input files and can adapt if cddl-codegen is provided as a source directory or a compiled binary. ```bash cargo run -- --input=input.cddl --output=EXPORT --cddl-codegen=path/to/cddl-codegen --lib-name=plutus-datum-test ``` -------------------------------- ### Rust CDDL Codegen Generation Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/metadata.mdx Commands to build and run the cddl-codegen tool to generate a Wasm-convertible Rust library from a CDDL definition. Assumes 'input.cddl' is in the root directory. ```bash cargo build cargo run ``` -------------------------------- ### Publish Rust Crate to Crates.io Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/README.rst Command to publish a new version of the Cardano Multiplatform Lib Rust crate to crates.io. This is the primary method for distributing the Rust library. Ensure you have the necessary permissions and have bumped the version number. ```shell npm run rust:publish ``` -------------------------------- ### Wasm Package Build Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/metadata.mdx Commands to build a Wasm package from the generated Rust code using wasm-pack. This creates a library ready for use in Node.js or the browser. ```bash cd export wasm-pack build --target=nodejs wasm-pack pack ``` -------------------------------- ### Generate and Convert CDDL Instance to CBOR Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/specs/README.md Combines the generation of a CDDL test instance and its conversion to CBOR format in a single command. This is an efficient way to create CBOR test files. ```bash cddl specs/shelley.cddl generate 1 | diag2cbor.rb > test/name_here.cbor ``` -------------------------------- ### Rust CDDL Codegen Build and Run Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/metadata.mdx Commands to build and run the metadata CDDL checker tool. This is used to validate your CDDL definitions against the metadata CDDL standard before proceeding with code generation. ```bash cd /tools/metadata-cddl-checker/ carp build carp run ``` -------------------------------- ### Publish NPM Packages for Cardano Multiplatform Lib Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/README.rst Commands to publish new versions of the Cardano Multiplatform Lib to NPM. This includes publishing the NodeJS, Browser WASM, and Browser ASM.js packages. Publishing to NPM requires administrative privileges for the project. ```shell npm run js:publish-nodejs npm run js:publish-browser npm run js:publish-asm ``` -------------------------------- ### Loose Parse Metadata Details (Full Example) in Rust Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/CIP25.mdx Demonstrates parsing of non-compliant metadata using `loose_parse()` to extract the 'Name' field. This function is intended for situations where standard CIP25 parsing fails due to minor errors in the metadata. It returns a `MiniMetadataDetails` struct, which may contain name and image. ```rust // { ... } let details = MiniMetadataDetails::loose_parse(&TransactionMetadatum::from_bytes(hex::decode("a664446174656a39204d617920323032316b4465736372697074696f6e782b4861707079204d6f7468657227732044617920746f20616c6c207468652043617264616e6f204d6f6d732165496d616765783b697066732e696f2f697066732f516d61683651504b554b7670364b39585142325341343251337972666643625942626b38456f52724237464e3267644e616d656e53706163654275642023313530376674726169747385695374617220537569746a4368657374706c6174656442656c7464466c616766506973746f6c647479706565416c69656e").unwrap()).unwrap(); let name = details.name.unwrap().0; println!("{name:?}") ``` -------------------------------- ### Build Cardano Transaction with Automatic Fee Calculation (TypeScript) Source: https://context7.com/dcspark/cardano-multiplatform-lib/llms.txt Demonstrates building a complete Cardano transaction using CML in TypeScript. This includes configuring protocol parameters, adding UTXOs as inputs, defining outputs, setting time-to-live (TTL), performing coin selection, and finally building and submitting the signed transaction. It utilizes the `TransactionBuilder` for a fluent API and handles fee calculation, change, and coin selection automatically. ```typescript import * as CML from '@dcspark/cardano-multiplatform-lib-browser'; // Configure protocol parameters (mainnet values as of 2024) const config = CML.TransactionBuilderConfigBuilder.new() .fee_algo(CML.LinearFee.new( CML.BigNum.from_str('44'), // coefficient (minfee_a) CML.BigNum.from_str('155381') // constant (minfee_b) )) .pool_deposit(CML.BigNum.from_str('500000000')) // 500 ADA .key_deposit(CML.BigNum.from_str('2000000')) // 2 ADA .max_value_size(5000) .max_tx_size(16384) .coins_per_utxo_byte(CML.BigNum.from_str('4310')) .ex_unit_prices(CML.ExUnitPrices.new( CML.Rational.new(CML.BigNum.from_str('577'), CML.BigNum.from_str('10000')), CML.Rational.new(CML.BigNum.from_str('721'), CML.BigNum.from_str('10000000')) )) .collateral_percentage(150) .max_collateral_inputs(3) .build(); // Initialize transaction builder const txBuilder = CML.TransactionBuilder.new(config); // Add UTXOs as inputs const utxos = await walletApi.getUtxos(); for (const utxoCbor of utxos) { const utxo = CML.TransactionUnspentOutput.from_cbor_hex(utxoCbor); const input = CML.SingleInputBuilder .from_transaction_unspent_output(utxo) .payment_key(); // Indicates this is a regular payment input txBuilder.add_utxo(input); } // Add output const recipientAddr = CML.Address.from_bech32('addr1q9xyz...'); const output = CML.TransactionOutputBuilder.new() .with_address(recipientAddr) .next() .with_coin(CML.BigNum.from_str('5000000')) // 5 ADA .build(); txBuilder.add_output(output.output); // Set time-to-live (TTL) const currentSlot = await getCurrentSlot(); txBuilder.set_ttl(CML.BigNum.from_str((currentSlot + 3600).toString())); // Perform coin selection (automatically selects UTXOs and adds change) const changeAddr = CML.Address.from_bech32(await walletApi.getChangeAddress()); txBuilder.select_utxos(CML.CoinSelectionStrategyCIP2.LargestFirst); // Build transaction and sign const txBody = txBuilder.build(CML.ChangeSelectionAlgo.Default, changeAddr); const txHash = CML.hash_transaction(txBody.body()); const witnessSet = CML.TransactionWitnessSet.new(); const vkeyWitnesses = CML.Vkeywitnesses.new(); vkeyWitnesses.add(CML.make_vkey_witness(txHash, privateKey)); witnessSet.set_vkeys(vkeyWitnesses); const signedTx = CML.Transaction.new(txBody.body(), witnessSet, true, undefined); const txId = await walletApi.submitTx(signedTx.to_cbor_hex()); // Returns: transaction hash "a3f4b2c1..." ``` -------------------------------- ### Derive BIP32 Keys from Root Key - JavaScript Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/crypto/generating_keys.mdx Demonstrates how to derive account, UTXO, and stake keys from a root BIP32 private key using JavaScript. It utilizes the harden function to ensure derivation path indices are hardened as per BIP32 standards. No external dependencies beyond CardanoWasm. ```javascript function harden(num) { return 0x80000000 + num; } const rootKey = CardanoWasm.BIP32PrivateKey.from_bech32("xprv17qx9vxm6060qjn5fgazfue9nwyf448w7upk60c3epln82vumg9r9kxzsud9uv5rfscxp382j2aku254zj3qfx9fx39t6hjwtmwq85uunsd8x0st3j66lzf5yn30hwq5n75zeuplepx8vxc502txx09ygjgx06n0p"); const accountKey = rootKey .derive(harden(1852)) // purpose .derive(harden(1815)) // coin type .derive(harden(0)); // account #0 const utxoPubKey = accountKey .derive(0) // external .derive(0) .to_public(); const stakeKey = accountKey .derive(2) // chimeric .derive(0) .to_public(); ``` -------------------------------- ### Initialize Transaction Builder with Blockfrost Config (Rust) Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/builders/index.mdx Initializes a transaction builder configuration by fetching the latest epoch parameters from Blockfrost using the cml-blockfrost crate. This requires an active API connection and returns a configuration suitable for creating a new transaction builder. ```rust let cfg = cml_blockfrost::make_tx_builder_cfg(&api).await.unwrap(); let mut tx_builder = TransactionBuilder::new(cfg); ``` -------------------------------- ### Create Cardano Address from Bech32 String Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/crypto/generating_keys.mdx Illustrates how to create a Cardano Address object directly from its Bech32 string representation, which is a common way to represent addresses. ```javascript const addr = CardanoWasm.Address.from_bech32("addr1vyt3w9chzut3w9chzut3w9chzut3w9chzut3w9chzut3w9cj43ltf"); ``` -------------------------------- ### Create Cardano Address Variants with CardanoWasm Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/crypto/generating_keys.mdx Demonstrates creating various Cardano address types such as BaseAddress, EnterpriseAddress, PointerAddress, RewardAddress, and ByronAddress using the CardanoWasm library. It shows how to derive stake credentials from public keys and specifies network information. Note that Byron address creation has specific constraints regarding address formats. ```javascript const baseAddr = CardanoWasm.BaseAddress.new( CardanoWasm.NetworkInfo.mainnet().network_id(), CardanoWasm.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()), CardanoWasm.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash()) ); const enterpriseAddr = CardanoWasm.EnterpriseAddress.new( CardanoWasm.NetworkInfo.mainnet().network_id(), CardanoWasm.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()) ); const ptrAddr = CardanoWasm.PointerAddress.new( CardanoWasm.NetworkInfo.mainnet().network_id(), CardanoWasm.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()), CardanoWasm.Pointer.new( 100, // slot 2, // tx index in slot 0 // cert indiex in tx ) ); const rewardAddr = CardanoWasm.RewardAddress.new( CardanoWasm.NetworkInfo.mainnet().network_id(), CardanoWasm.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash()) ); const byronAddr = CardanoWasm.ByronAddress.icarus_from_key( utxoPubKey, // Ae2* style icarus address CardanoWasm.NetworkInfo.mainnet().protocol_magic() ); ``` -------------------------------- ### Create TransactionBuilderConfigBuilder Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/builders/index.mdx Illustrates the creation of a TransactionBuilderConfigBuilder, which is used to configure the TransactionBuilder with necessary on-chain parameters such as fee costs and key deposits. These parameters are crucial for constructing valid transactions. ```rust let builder = TransactionBuilder::new(config); ``` -------------------------------- ### Build Transaction Body using TransactionBuilder Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/builders/index.mdx Builds a transaction body using the TransactionBuilder. Assumes the builder has been configured with inputs, outputs, and optionally certificates, withdrawals, metadata, or minting. The fee should be set last, either explicitly or implicitly. ```rust const body = builder.build() ``` -------------------------------- ### Generate CDDL Test Instance (diag) Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/specs/README.md Generates a test instance from a CDDL specification in the diag (dialog) format. This is the first step in creating test cases for CDDL-defined structures. ```bash cddl specs/shelley.cddl generate 1 > test/name_here.diag ``` -------------------------------- ### Generate CIP36 Code with cddl-codegen Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/specs/README.md Generates Rust code for CIP36 from its CDDL specification using cddl-codegen. This process includes preserving encodings, canonical form, and deriving JSON serialization/deserialization. ```bash --input=specs/cip36.cddl --output=CML_CIP36_DIR --preserve-encodings=true --canonical-form=true --json-serde-derives=true --json-schema-export=true ``` -------------------------------- ### Convert between BIP32 Private Keys and XPrv Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/crypto/generating_keys.mdx Demonstrates the conversion between BIP32 Private Keys and cardano-cli's 128-byte XPrv format using the CardanoWasm library. It also notes that 96-byte XPrv keys are byte-wise identical to BIP32 Private Keys. ```javascript const bip32PrivateKey = CardanoWasm.BIP32PrivateKey.from_128_xprv(xprvBytes); assert(xprvBytes == CardanoWasm.BIP32PrivateKey.to_128_xprv()); ``` -------------------------------- ### Generate BIP32 Private Key from BIP39 Entropy - JavaScript Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/crypto/generating_keys.mdx Shows how to generate a root BIP32 private key from a BIP39 mnemonic phrase using JavaScript. It first converts the mnemonic to entropy using the 'bip39' npm package and then uses CardanoWasm's from_bip39_entropy function. Requires the 'bip39' package and Node.js Buffer. ```javascript import { mnemonicToEntropy } from 'bip39'; const entropy = mnemonicToEntropy( [ "test", "walk", "nut", "penalty", "hip", "pave", "soap", "entry", "language", "right", "filter", "choice" ].join(' ') ); const rootKey = CardanoWasm.Bip32PrivateKey.from_bip39_entropy( Buffer.from(entropy, 'hex'), Buffer.from(''), ); ``` -------------------------------- ### Convert Diag to CBOR Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/specs/README.md Converts a CDDL test instance from diag format to CBOR format using the cbor-diag tool. This is typically the second step after generating a diag file. ```bash diag2cbor.rb test/name_here.diag > test/name_here.cbor ``` -------------------------------- ### Configure Transaction Builder with Blockfrost Parameters (WASM/JavaScript) Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/builders/index.mdx Manually configures a Cardano transaction builder using parameters obtained from the Blockfrost API's `epochsLatestParameters` endpoint. This involves parsing cost models, fee algorithms, deposit amounts, and other network-specific settings into the CML TransactionBuilderConfigBuilder. ```javascript let params = await blockfrost.epochsLatestParameters(); // cost order is based on lex ordering of keys let costModels = CML.CostModels.new(); let v1Costs = params.cost_models['PlutusV1']; if (v1Costs != null) { let v1CMLCosts = CML.IntList.new(); for (key in Object.keys(v1Costs).toSorted()) { v1CMLCosts.add(CML.Int.new(v1Costs[key])); } costModels.set_plutus_v1(v1CMLCosts); } // cost order is based on lex ordering of keys let v2Costs = params.cost_models['PlutusV2']; if (v2Costs != null) { let v2CMLCosts = CML.IntList.new(); for (key in Object.keys(v2Costs).toSorted()) { v2CMLCosts.add(CML.Int.new(v2Costs[key])); } costModels.set_plutus_v2(v2CMLCosts); } // note: as of writing this the sancho testnet format is different for v3 // compared to v1/v2. this may remain true once mainnet switches over so // please inspect the object you are getting for cost models from blockfrost let configBuilder = CML.TransactionBuilderConfigBuilder.new() .fee_algo(CML.LinearFee.new(params.min_fee_a, params.min_fee_b)) .coins_per_utxo_byte(BigNum(params.coins_per_utxo_size)) .pool_deposit(BigNum(params.pool_deposit)) .key_deposit(BigNum(params.key_deposit)) .max_value_size(Number(params.max_val_size)) .max_tx_size(params.max_tx_size) .ex_unit_prices(CML.ExUnitPrices.new( CML.SubCoin.from_base10_f32(params.price_mem), CML.SubCoin.from_base10_f32(params.price_step) )) .cost_models(costModels) .collateral_percentage(params.collateral_percent) max_collateral_inputs(params.max_collateral_inputs); let mut txBuilder = CML.TransactionBuilder.new(configBuilder.build()); ``` -------------------------------- ### WASM JSON Conversion for TransactionInput Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/json.mdx Demonstrates converting JSON strings to TransactionInput objects and back to JSON strings using WASM. This utilizes the `.to_json()` and `.from_json()` methods available on supported wrappers in the WASM environment. No external dependencies are required beyond the CML library. ```javascript let txInJson = "{\"transaction_id\":\"0fba1404ed9b82b41938ba2e8bda7bec8cce813fb7e7cd7692b43caa76fe891c\",\"index\":3}"; let txIn = CML.TransactionInput.from_json(txInJson); console.log(`txIn JSON: ${txIn.to_json()}`); ``` -------------------------------- ### WASM CBOR Serialization/Deserialization for CIP-30 Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/cbor.mdx Illustrates how to perform CBOR serialization and deserialization for Cardano on-chain types within a WebAssembly environment, as commonly used with CIP-30 dApp connectors. It highlights methods like `.to_cbor_hex()` and `.from_cbor_hex()` for convenience. ```javascript let canonicalCborHex = "825820aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa01"; // these all represent the following CBOR: // [ ; array of 2 elements (transaction input struct) // 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, ; bytes (tx hash) // 1 ; unsigned integer (tx index) // ] let nonCanonicalCbor = [ canonicalCborHex, "825820aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1a00000001", "9f5f48aaaaaaaaaaaaaaaa48aaaaaaaaaaaaaaaa48aaaaaaaaaaaaaaaa48aaaaaaaaaaaaaaaaff01ff", "9900025820aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa190001", "9b00000000000000025f41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aa41aaff1b0000000000000001", ]; for (let origCborHex of nonCanonicalCbor) { let txIn = CML.TransactionInput.from_cbor_hex(origCborHex); // serialize back to cbor bytes using the same cbor encoding details so it will match // the format where it came from console.assert(txIn.to_cbor_hex() == origCborHex); // no matter how it was created it will represent the same data and can be encoded to // canonical cbor bytes which will be the same as all of these are the same transaction input console.assert(txIn.to_canonical_cbor_hex() == canonicalCborHex); } ``` -------------------------------- ### Generate Cardano Chain Code with cddl-codegen Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/specs/README.md Generates Rust code for the Cardano chain from CDDL specifications using cddl-codegen. It preserves encodings, uses canonical form, and derives JSON serialization/deserialization. ```bash --input=specs/babbage --output=CML_CHAIN_DIR --preserve-encodings=true --canonical-form=true --json-serde-derives=true --json-schema-export=true ``` -------------------------------- ### Generate CIP25 Code with cddl-codegen Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/specs/README.md Generates Rust code for CIP25 from its CDDL specification using cddl-codegen. It focuses on deriving JSON serialization/deserialization for the CIP25 data structures. ```bash --input=specs/cip25.cddl --output=CML_CIP25_DIR --json-serde-derives=true --json-schema-export=true ``` -------------------------------- ### Construct Cardano TransactionMetadatum in JavaScript Source: https://github.com/dcspark/cardano-multiplatform-lib/blob/develop/docs/docs/modules/metadata.mdx This snippet demonstrates how to construct a complex TransactionMetadatum object, including nested Maps and Lists, using the CardanoWasm library. It shows the insertion of text, integer, and list types into a MetadataMap. ```javascript const map = CardanoWasm.MetadataMap.new(); map.insert( CardanoWasm.TransactionMetadatum.new_text("receiver_id"), CardanoWasm.TransactionMetadatum.new_text("SJKdj34k3jjKFDKfjFUDfdjkfd") ); map.insert( CardanoWasm.TransactionMetadatum.new_text("sender_id"), CardanoWasm.TransactionMetadatum.new_text("jkfdsufjdk34h3Sdfjdhfduf873") ); map.insert( CardanoWasm.TransactionMetadatum.new_text("comment"), CardanoWasm.TransactionMetadatum.new_text("happy birthday") ); const tags = CardanoWasm.MetadataList.new(); tags.add(CardanoWasm.TransactionMetadatum.new_int(CardanoWasm.Int.new(CardanoWasm.BigNum.from_str("0")))); tags.add(CardanoWasm.TransactionMetadatum.new_int(CardanoWasm.Int.new(CardanoWasm.BigNum.from_str("264")))); tags.add(CardanoWasm.TransactionMetadatum.new_int(CardanoWasm.Int.new_negative(CardanoWasm.BigNum.from_str("1024")))); tags.add(CardanoWasm.TransactionMetadatum.new_int(CardanoWasm.Int.new(CardanoWasm.BigNum.from_str("32")))); map.insert( CardanoWasm.TransactionMetadatum.new_text("tags"), CardanoWasm.TransactionMetadatum.new_list(tags) ); const metadatum = CardanoWasm.TransactionMetadatum.new_map(map); ``` -------------------------------- ### Register Voting Keys for Catalyst (CIP-36) using TypeScript Source: https://context7.com/dcspark/cardano-multiplatform-lib/llms.txt This snippet demonstrates how to register voting keys for Project Catalyst governance using CIP-36. It supports weighted delegation to multiple voting keys and generates the necessary transaction metadata. Dependencies include '@dcspark/cardano-multiplatform-lib-cip36' and '@dcspark/cardano-multiplatform-lib-nodejs'. ```typescript import * as CIP36 from '@dcspark/cardano-multiplatform-lib-cip36'; import * as CML from '@dcspark/cardano-multiplatform-lib-nodejs'; // Generate voting key pair (can be different from payment/stake keys) const votingPrivateKey = CML.PrivateKey.generate_ed25519extended(); const votingPublicKey = votingPrivateKey.to_public(); // Get current slot for nonce const currentSlot = await getCurrentSlot(); // Get stake credential to register const stakeCredential = CIP36.StakeCredential.from_pub_key(stakePublicKey); // Get payment address for rewards const paymentAddress = CML.Address.from_bech32('addr1q9xyz...'); // Create weighted delegation (can split voting power) const delegations = []; delegations.push(CIP36.Delegation.new( CIP36.VotingPubKey.from_bytes(votingPublicKey.as_bytes()), CIP36.Weight.new(1) // Weight: 1 = 100% of voting power )); // Optional: delegate to multiple keys delegations.push(CIP36.Delegation.new( CIP36.VotingPubKey.from_bytes(alternateVotingKey.as_bytes()), CIP36.Weight.new(0) // Weight: 0 = 0% for this example )); const delegationDist = CIP36.DelegationDistribution.new_weighted(delegations); // Create registration const registration = CIP36.KeyRegistration.new( delegationDist, stakeCredential, paymentAddress, CIP36.Nonce.new(currentSlot) // Use current slot as nonce ); // Sign registration with stake key const registrationHash = registration.hash_to_sign(true); const stakeSignature = stakePrivateKey.sign(registrationHash); const witness = CIP36.RegistrationWitness.new_key( CIP36.CIP36VotingPubKey.from_pub_key(stakePublicKey), CIP36.CIP36Signature.from_bytes(stakeSignature.to_bytes()) ); const registrationCbor = CIP36.RegistrationCbor.new(registration, witness); // Convert to transaction metadata (label 61284) const metadata = CML.GeneralTransactionMetadata.new(); metadata.insert( CML.BigNum.from_str('61284'), CML.TransactionMetadatum.from_cbor_bytes(registrationCbor.to_cbor_bytes()) ); const auxData = CML.AuxiliaryData.new_shelley(metadata); // Add to transaction const txBuilder = CML.TransactionBuilder.new(config); // ... add inputs/outputs ... txBuilder.set_auxiliary_data(auxData); // Build and sign with stake key const txBody = txBuilder.build(CML.ChangeSelectionAlgo.Default, changeAddr); const txHash = CML.hash_transaction(txBody.body()); const witnessSet = CML.TransactionWitnessSet.new(); const vkeyWitnesses = CML.Vkeywitnesses.new(); vkeyWitnesses.add(CML.make_vkey_witness(txHash, paymentPrivateKey)); vkeyWitnesses.add(CML.make_vkey_witness(txHash, stakePrivateKey)); witnessSet.set_vkeys(vkeyWitnesses); const signedTx = CML.Transaction.new(txBody.body(), witnessSet, true, auxData); // Voting registration complete - can now participate in Catalyst ```