Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Onboarding with Expanded Tutorial Series #512

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc-site/docs/tutorials/bond-issuance.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This shows how to leverage the [Noto](../../architecture/noto/) and [Pente](../.

## Running the example

Follow the [Getting Started](../../getting-started/installation/) instructions to set up a Paldin environment, and
Follow the [Getting Started](../../getting-started/installation/) instructions to set up a Paladin environment, and
then follow the example [README](https://github.com/LF-Decentralized-Trust-labs/paladin/blob/main/example/bond/README.md)
to run the code.

Expand Down
137 changes: 137 additions & 0 deletions doc-site/docs/tutorials/hello-world.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Hello World with Paladin

This tutorial walks you through deploying and interacting with a simple `HelloWorld` smart contract using the Paladin SDK. The example demonstrates how to:
1. Deploy the contract,
2. Interact with it by calling its `sayHello` function,
3. Retrieve and verify the emitted event.

---

## Running the Example

The example code can be found in the [Paladin example repository](https://github.com/LF-Decentralized-Trust-labs/paladin/blob/main/example/public-storage).

The storage solidity contract can be found [here](https://github.com/LF-Decentralized-Trust-labs/paladin/blob/main/solidity/contracts/tutorial/Storage.sol).

Follow the [Getting Started](../../getting-started/installation/) instructions to set up a Paladin environment. Then, follow the example [README](https://github.com/LF-Decentralized-Trust-labs/paladin/blob/main/example/helloworld/README.md) to run the code.

---

### Overview

We have a `HelloWorld` smart contract, which:
- Emits a "welcome" message as an event when its `sayHello` function is called.

### Key Artifacts
To deploy and interact with the contract, we use:
1. **ABI**: Describes the contract's interface, including its functions and events.
2. **Bytecode**: The compiled contract code.

These are pre-compiled and provided in the `helloWorldJson` object.

---

### Step 1: Deploy the Contract

```typescript
const deploymentTxID = await paladin.sendTransaction({
type: TransactionType.PUBLIC, // Deploy publicly
abi: helloWorldJson.abi, // ABI of the HelloWorld contract
bytecode: helloWorldJson.bytecode, // Compiled bytecode
function: "", // No constructor arguments
from: owner.lookup, // Account signing the transaction
data: {}, // No additional data
});
```

- **What happens**:
- The `sendTransaction` method sends a deployment transaction to the Paladin network.
- The function returns a `deploymentTxID` that uniquely identifies the transaction.

### Step 2: Confirm the Deployment

```typescript
const deploymentReceipt = await paladin.pollForReceipt(deploymentTxID, 10000, true);
if (!deploymentReceipt?.contractAddress) {
logger.error("Deployment failed!");
return false;
}
logger.log("Contract deployed successfully at address:", deploymentReceipt.contractAddress);
```

- **What happens**:
- We use `pollForReceipt` to wait for the deployment transaction to be confirmed.
- If successful, the receipt includes the new `contractAddress`.

---

### Step 3: Call the `sayHello` Function

```typescript
const name = "Blocky McChainface"; // Example name for the greeting

const sayHelloTxID = await paladin.sendTransaction({
type: TransactionType.PUBLIC,
abi: helloWorldJson.abi,
function: "sayHello",
from: owner.lookup,
to: deploymentReceipt.contractAddress,
data: { name: name },
});
```

- **What happens**:
- The `sendTransaction` method sends a transaction to call the `sayHello` function of the deployed contract.
- The `data` object includes the function arguments—in this case, the `name` of the person being greeted.

---

### Step 4: Confirm the Function Call

```typescript
const functionReceipt = await paladin.pollForReceipt(sayHelloTxID, 10000, true);
if (!functionReceipt?.transactionHash) {
logger.error("Receipt retrieval failed!");
return false;
}
logger.log("sayHello function executed successfully!");
```

- **What happens**:
- Similar to the deployment step, we wait for confirmation of the `sayHello` function call using `pollForReceipt`.

---

### Step 5: Retrieve the Emitted Event

```typescript
const events = await paladin.decodeTransactionEvents(
functionReceipt.transactionHash,
helloWorldJson.abi,
"pretty=true",
);

logger.log(events[0].data["message"]);
```

- **What happens**:
- We use `decodeTransactionEvents` to extract event data from the `sayHello` transaction.

---

## Conclusion

Congratulations! You've successfully:
1. Deployed the `HelloWorld` contract,
2. Called its `sayHello` function,
3. Retrieved and validated the emitted event.

This simple example demonstrates how to interact with smart contracts using the Paladin SDK.

---

## Next Steps

Now that you’ve deployed and interacted with the `HelloWorld` contract, you’re ready to explore more complex interactions with smart contracts. In the next tutorial, we will introduce you to a **Storage** contract where you will write and read from from the blockchain!

[Continue to the Storage Contract Tutorial →](./public-storage.md)
52 changes: 37 additions & 15 deletions doc-site/docs/tutorials/index.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,56 @@
## Pre-requisites
## Prerequisites

* git
* [NodeJS 20.x or newer](https://nodejs.org/en/download/package-manager) installed
- **Git**
- **Node.js 20.x or newer**
Follow the [official Node.js documentation](https://nodejs.org/en/download/package-manager) for your platform to install the appropriate version.

Clone the Paladin repository to access the examples:
To access the tutorial code, clone the Paladin repository:

```shell
git clone https://github.com/LF-Decentralized-Trust-labs/paladin.git
```

## Next Steps

The tutorials on this page provide an introduction to building on the Paladin platform. If you haven’t already, visit the [Getting Started guide](../getting-started/installation.md) to familiarize yourself with running Paladin before proceeding with any of the tutorials below.

The tutorials on this page provide a starting point for running code on top of Paladin.
<div class="grid cards" markdown>

If you haven't already, you should visit [Getting Started](../getting-started/installation/) to
ensure you're familiar with running Paladin before walking through any of the tutorials.
- :fontawesome-solid-rocket:{ .lg .middle } **[Hello World](hello-world.md)**

---

Begin with a simple “Hello World” example to get familiar with some of the basics.

- :fontawesome-solid-rocket:{ .lg .middle } **[Public Storage](public-storage.md)**

---

Explore fundamental SDK functionality for deploying and interacting with a publicly visible contract.

- :fontawesome-solid-rocket:{ .lg .middle } **[Private Storage](private-storage.md)**

---

Discover how to use **Privacy Groups** and keep contract data confidential among authorized members.

- :fontawesome-solid-rocket:{ .lg .middle } **[Notarized Tokens](notarized-tokens.md)**

---

Learn how to issue, mint, and transfer tokens using Paladin’s **Notarized Tokens** domain.

<div class="grid cards" markdown>

- :fontawesome-solid-stamp:{ .lg .middle } __[Bond Issuance](bond-issuance.md)__
- :fontawesome-solid-stamp:{ .lg .middle } **[Wholesale CBDC](zkp-cbdc.md)**

---
---

Learn how Noto and Pente work together to represent a bond issuance process.
Implement a wholesale CBDC with **zero-knowledge proof** features for enhanced privacy and regulatory compliance.

- :fontawesome-solid-stamp:{ .lg .middle } __[Wholesale CBDC](zkp-cbdc.md)__
- :fontawesome-solid-stamp:{ .lg .middle } **[Bond Issuance](bond-issuance.md)**

---
---

Learn how to implement a wholesale CBDC with Zeto.
Understand how **Notarized Tokens** and **Privacy Groups** work together to model and manage a bond issuance process.

</div>
</div>
135 changes: 135 additions & 0 deletions doc-site/docs/tutorials/notarized-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Notarized Tokens

In this tutorial, you’ll learn how to create and manage a basic token using the **Notarized Tokens (noto)** domain. Unlike the private storage example, these tokens can be transferred between nodes publicly, demonstrating how assets (e.g., “cash”) can be issued and tracked on the blockchain using Paladin.

## Prerequisites

Make sure you have:

1. Completed the [Private Storage Tutorial](./private-storage.md).
2. A **running Paladin network** with at least three nodes (Node1, Node2, Node3).

---

## Overview

This tutorial will guide you through:

1. **Deploying a Noto Token**: Use the `NotoFactory` to create a “cash token” with a specific notary.
2. **Minting Tokens**: Issue tokens to a particular node’s account.
3. **Transferring Tokens**: Send tokens between different nodes to simulate basic payments.

You can find the complete example code in the [Paladin example repository](https://github.com/LF-Decentralized-Trust-labs/paladin/tree/main/example/notarized-tokens).

---

## Step 1: Deploy a Noto Token

First, create a **Noto Factory** instance and deploy a new token. In this scenario, Node1 will act as both the notary (the entity allowed to mint tokens) and the initial recipient of the minted cash.

```typescript
logger.log("Step 1: Deploying a Noto cash token...");
const notoFactory = new NotoFactory(paladinClientNode1, "noto");
const cashToken = await notoFactory.newNoto(verifierNode1, {
notary: verifierNode1, // The notary for this token
restrictMinting: true, // Restrict minting to the notary only
});
if (!cashToken) {
logger.error("Failed to deploy the Noto cash token!");
return false;
}
logger.log("Noto cash token deployed successfully!");
```

**Key Points**:
- **`notary`**: Specifies which verifier (account) can mint new tokens.
- **`restrictMinting`**: If `true`, only the `notary` can mint additional tokens.

---

## Step 2: Mint Tokens

Now that the token contract exists, **mint** an initial supply of tokens to Node1. This step simulates creating new “cash” in the system.

```typescript
logger.log("Step 2: Minting 2000 units of cash to Node1...");
const mintReceipt = await cashToken.mint(verifierNode1, {
to: verifierNode1, // Mint cash to Node1
amount: 2000, // Amount to mint
data: "0x", // Additional data (optional)
});
if (!mintReceipt) {
logger.error("Failed to mint cash tokens!");
return false;
}
logger.log("Successfully minted 2000 units of cash to Node1!");
```

**Key Points**:
- **`amount`**: Number of tokens to create.
- **`data`**: Can include extra metadata or encoding, if needed.

---

## Step 3: Transfer Tokens to Node2

With tokens minted on Node1, you can **transfer** some of them to Node2. This step demonstrates a simple token transfer, much like sending money to another account.

```typescript
logger.log("Step 3: Transferring 1000 units of cash from Node1 to Node2...");
const transferToNode2 = await cashToken.transfer(verifierNode1, {
to: verifierNode2, // Transfer to Node2
amount: 1000, // Amount to transfer
data: "0x", // Optional additional data
});
if (!transferToNode2) {
logger.error("Failed to transfer cash to Node2!");
return false;
}
logger.log("Successfully transferred 1000 units of cash to Node2!");
```

---

## Step 4: Transfer Tokens to Node3

Now let’s see how Node2 can pass tokens to Node3. This step involves calling `.using(paladinClientNode2)` so that **Node2** signs the transaction rather than Node1.

```typescript
logger.log("Step 4: Transferring 800 units of cash from Node2 to Node3...");
const transferToNode3 = await cashToken.using(paladinClientNode2).transfer(verifierNode2, {
to: verifierNode3, // Transfer to Node3
amount: 800, // Amount to transfer
data: "0x", // Optional additional data
});
if (!transferToNode3) {
logger.error("Failed to transfer cash to Node3!");
return false;
}
logger.log("Successfully transferred 800 units of cash to Node3!");
```

**Key Points**:
- **`.using(paladinClientNode2)`** ensures the transaction is signed by Node2.
- If Node2 does not have sufficient tokens (e.g., tries to transfer 1200 while only having 1000), the transfer should fail and return an error.

---

## Conclusion

Congratulations! You’ve successfully:

1. **Deployed a Noto token** to represent cash within the Paladin network.
2. **Minted tokens** from a designated notary account.
3. **Transferred tokens** between different nodes, demonstrating how digital assets move across participants.

At this point, you have a basic grasp of how to issue and manage tokens using the Noto domain.

---

## Next Steps

Now that you’ve explored how to create, mint, and transfer tokens using the Noto domain, you’re ready to delve into Zeto, Paladin’s zero-knowledge domain for more advanced privacy features. In the next tutorial, you’ll learn how to build a cash payment solution—for example, a wholesale CBDC or a commercial bank money rail—while leveraging powerful privacy techniques such as private minting and selective disclosure.

[Continue to the Zero-Knowledge Proof Tutorial →](./zkp-cbdc.md)

Loading
Loading