# @demox-labs/miden-sdk
The @demox-labs/miden-sdk is a toolkit designed for interacting with the Miden virtual machine. It offers essential tools and functionalities for developers aiming to integrate or utilize Miden VM capabilities in their applications.
## Installation
To install the package via npm, run the following command:
```javascript
npm i @demox-labs/miden-sdk
```
For yarn:
```javascript
yarn add @demox-labs/miden-sdk
```
## Usage
```typescript
import { WebClient } from "@demox-labs/miden-sdk";
const webClient = new WebClient();
await webClient.create_client();
// Use WebClient to create accounts, notes, transactions, etc.
// This will create a mutable, off-chain account and store it in IndexedDB
const accountId = await webClient.new_wallet("OffChain", true);
```
## Examples
### The WebClient
The WebClient is your gateway to creating and interacting with anything miden vm related.
Example:
```typescript
// Creates a new WebClient instance which can then be configured after
const webClient = new WebClient();
// Creates the internal client of a previously instantiated WebClient.
// Can provide `node_url` as an optional parameter. Defaults to "http://18.203.155.106:57291" which is the URL
// of the remote miden node.
await webClient.create_client();
```
Example specifying a specific node URL:
```typescript
const webClient = new WebClient();
let remote_node_url = "http://18.203.155.106:57291"
await webClient.create_client(remote_node_url);
```
### Accounts
You can use the WebClient to create and retrieve account information.
```typescript
const webClient = new WebClient();
await webClient.create_client();
/**
* Creates a new wallet account.
*
* @param storage_mode String. Either "OffChain" or "OnChain".
* @param mutable Boolean. Whether the wallet code is mutable or not
*
* Returns: Wallet Id
*/
const walletId = await webClient.new_wallet("OffChain", true);
/**
* Creates a new faucet account.
*
* @param storage_mode String. Either "OffChain" or "OnChain".
* @param non_fungible Boolean. Whether the faucet is non_fungible or not. NOTE: Non-fungible faucets are not supported yet
* @param token_symbol String. Token symbol of the token the faucet creates
* @param decimals String. Decimal precision of token.
* @param max_supply String. Maximum token supply
*/
const faucetId = await webClient.new_faucet("OffChain", true, "TOK", 6, 1_000_000)
/**
* Returns all accounts. Both wallets and faucets. Returns the following object per account
* {
* id: string
* nonce: string
* vault_root: string
* storage_root: string
* code_root: string
* }/
const accounts = await webClient.get_accounts()
console.log(accounts[0].id) // Prints account id of first account retrieved as hex value
// Gets a single account by id
const account = await webClient.get_account("0x9258fec00ad6d9bc");
// Imports an account. This example adds a simple button to an HTML page, creates a listener for an account file selection, serializes that file into bytes, then calls the client to import it.
document.getElementById('accountFileInput').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = async function(e) {
let webClient = await createMidenWebClient();
const arrayBuffer = e.target.result;
const byteArray = new Uint8Array(arrayBuffer);
await webClient.importAccount(accountAsBytes);
};
reader.readAsArrayBuffer(file);
}
});
```
### Transactions
You can use the WebClient to facilitate transactions between accounts.
Let's mint some tokens for our wallet from our faucet:
```typescript
const webClient = new WebClient();
await webClient.create_client();
const walletId = await webClient.new_wallet("OffChain", true);
const faucetId = await webClient.new_faucet("OffChain", true, "TOK", 6, 1_000_000);
// Syncs web client with node state.
await webClient.sync_state();
// Caches faucet account auth. A workaround to allow for synchronicity in the transaction flow.
await webClient.fetch_and_cache_account_auth_by_pub_key(faucetId);
/**
* Mints 10_000 tokens for the previously created wallet via a Private Note and returns a transaction the following result object:
* {
* transaction_id: string
* created_note_ids: string[]
* }
*/
const newTxnResult = await webClient.new_mint_transaction(walletId, faucetId, "Private", 10_000);
console.log(newTxnResult.created_note_ids); // Prints the list of note ids created from this transaction
// Sync state again
await webClient.sync_state();
/**
* Gets all of your existing transactions
* Returns string[] of transaction ids
*/
const transactions = await webClient.get_transactions()
```
### Notes
You can use the WebClient to query for existing notes, export notes, and import notes
Here is an example of how to import a note from a file (generated, say, from the faucet at https://testnet.miden.io/ for a given account). This code exposes a simple button on an HTML page for a user to select a file. A listener is setup to capture this event, serialize the note file, and import it.
```typescript
let webClient = await createMidenWebClient();
let walletAccount = await webClient.new_wallet("OffChain", true);
console.log(walletAccount); // Prints the id that can be used to plug in to the deployed Miden faucet
document.getElementById('noteFileInput').addEventListener('change', async function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = async function(e) {
let webClient = await createMidenWebClient();
const arrayBuffer = e.target.result;
const byteArray = new Uint8Array(arrayBuffer);
await webClient.import_note(byteArray, true); // imports the file generated from the faucet previously
};
reader.readAsArrayBuffer(file);
}
});
```
Example of exporting a note:
```typescript
console.log("testExportNote started");
let webClient = await createMidenWebClient();
// Create a faucet and mint a mint transaction
let faucetId = await createNewFaucet(webClient, "OffChain", false, "DEN", "10", "1000000");
await syncState(webClient);
await new Promise(r => setTimeout(r, 20000)); // Artificial delays to ensure sync is processed on remote node before continuing
await webClient.fetch_and_cache_account_auth_by_pub_key(faucetId);
let mintTransactionResult = await createNewMintTransaction(
webClient,
"0x9186b96f559e852f", // Insert target account id here
faucetId,
"Private",
"1000"
);
await new Promise(r => setTimeout(r, 20000));
await syncState(webClient);
// Take the note created from the mint transaction, serialize it, and download it via the browser immediately
let result = await exportNote(webClient, mintTransactionResult.created_note_ids[0]);
const blob = new Blob([result], {type: 'application/octet-stream'});
// Create a URL for the Blob
const url = URL.createObjectURL(blob);
// Create a temporary anchor element
const a = document.createElement('a');
a.href = url;
a.download = 'exportNoteTest.mno'; // Specify the file name
// Append the anchor to the document
document.body.appendChild(a);
// Programmatically click the anchor to trigger the download
a.click();
// Remove the anchor from the document
document.body.removeChild(a);
// Revoke the object URL to free up resources
URL.revokeObjectURL(url);
```
Get All Input Notes Example:
```typescript
let webClient = await createMidenWebClient();
/**
* get_input_notes takes a filter to retrieve notes based on a specific status. The options are the following:
* "All"
* "Consumed"
* "Committed"
* "Expected"
* "Processing"
*/
const notes = await webClient.get_input_notes("All")
```
## API Reference
```typescript
/**
* @returns {Promise}
*
* Example of returned object:
* {
* id: string,
* nonce: string,
* vault_root: string,
* storage_root: string,
* code_root: string
* }
*/
get_accounts(): Promise;
/**
* @param {string} account_id
* @returns {Promise}
*/
get_account(account_id: string): Promise;
/**
* @param {any} pub_key_bytes
* @returns {any}
*/
get_account_auth_by_pub_key(pub_key_bytes: any): any;
/**
* @param {string} account_id
* @returns {Promise}
*/
fetch_and_cache_account_auth_by_pub_key(account_id: string): Promise;
/**
* @param {string} note_id
* @param {string} export_type
* @returns {Promise}
*
* export_type can be any of the following:
*
* "Full"
* "Partial"
* "Id"
*/
export_note(note_id: string, export_type: string): Promise;
/**
* @param {any} account_bytes
* @returns created account id as {Promise}
*
*/
import_account(account_bytes: any): Promise;
/**
* @param {string} note_bytes
* @param {boolean} verify
* @returns {Promise}
*/
import_note(note_bytes: string, verify: boolean): Promise;
/**
* @param {string} storage_mode
* @param {boolean} mutable
* @returns {Promise}
*/
new_wallet(storage_mode: string, mutable: boolean): Promise;
/**
* @param {string} storage_mode
* @param {boolean} non_fungible
* @param {string} token_symbol
* @param {string} decimals
* @param {string} max_supply
* @returns {Promise}
*/
new_faucet(storage_mode: string, non_fungible: boolean, token_symbol: string, decimals: string, max_supply: string): Promise;
/**
* @param {string} target_account_id
* @param {string} faucet_id
* @param {string} note_type
* @param {string} amount
* @returns {Promise}
*
* Example of a NewTransactionResult object:
* {
* transaction_id: string,
* created_note_ids: string[]
* }
*/
new_mint_transaction(target_account_id: string, faucet_id: string, note_type: string, amount: string): Promise;
/**
* @param {string} sender_account_id
* @param {string} target_account_id
* @param {string} faucet_id
* @param {string} note_type
* @param {string} amount
* @param {string | undefined} [recall_height]
* @returns {Promise}
*
* Example of a NewTransactionResult object:
* {
* transaction_id: string,
* created_note_ids: string[]
* }
*/
new_send_transaction(sender_account_id: string, target_account_id: string, faucet_id: string, note_type: string, amount: string, recall_height?: string): Promise;
/**
* @param {string} account_id
* @param {(string)[]} list_of_notes
* @returns {Promise}
*
* Example of a NewTransactionResult object:
* {
* transaction_id: string,
* created_note_ids: string[]
* }
*/
new_consume_transaction(account_id: string, list_of_notes: (string)[]): Promise;
/**
* @param {string} sender_account_id
* @param {string} offered_asset_faucet_id
* @param {string} offered_asset_amount
* @param {string} requested_asset_faucet_id
* @param {string} requested_asset_amount
* @param {string} note_type
* @returns {Promise}
*
* Example of a NewSwapTransactionResult object:
* {
* transaction_id: string,
* expected_output_note_ids: string[],
*. expected_partial_note_ids: string[],
* payback_note_tag: string,
* }
*/
new_swap_transaction(sender_account_id: string, offered_asset_faucet_id: string, offered_asset_amount: string, requested_asset_faucet_id: string, requested_asset_amount: string, note_type: string): Promise;
/**
* @param {any} filter
* @returns {Promise}
*
* Examples of valid filters:
* "All"
* "Consumed"
* "Committed"
* "Expected"
* "Processing"
*/
get_input_notes(filter: any): Promise;
/**
* @param {string} note_id
* @returns note id as {Promise}
*/
get_input_note(note_id: string): Promise;
/**
* @param {any} filter
* @returns {Promise}
*/
get_output_notes(filter: any): Promise;
/**
* @param {string} note_id
* @returns {Promise}
*
* Examples of valid filters:
* "All"
* "Consumed"
* "Committed"
* "Expected"
* "Processing"
*/
get_output_note(note_id: string): Promise;
/**
* @returns block number of latest block you synced to {Promise}
*/
sync_state(): Promise;
/**
* @returns list of existing transaction ids {Promise}
*/
get_transactions(): Promise;
/**
* @param {string} tag
* @returns {Promise}
*/
add_tag(tag: string): Promise;
/**
*/
constructor();
/**
* @param {string | undefined} [node_url]
* @returns {Promise}
*/
create_client(node_url?: string): Promise;
```
## License
This project is licensed under the MIT License - see the LICENSE file for details.