This tutorial will guide you on how to set up a Machine using the mintBlue SDK. You will set up a new project directory, install the SDK, and create a small demo Machine tracking the plantation of trees to offset carbon emissions. Let's get green 🌲
If you don't want to copy code, you can run the example explained in this tutorial by cloning the mintBlue SDK and running the example.
You can now interact with the example.
Open your terminal and create a directory called forest-app. After you create the project directory, navigate to the directory by running the following command:
Initialize a Node.js project in this new directory by running the following command:
Install the mintBlue SDK with NPM.
Next, let's create two files. The first file main.ts holds the Machine logic while the second file forest.ts holds the application logic.
And finally, let's add some skeleton code to our main.js file. Make sure to replace the placeholder <YOUR-SDK-TOKEN> with your SDK token and <YOUR-PROJECT-ID> with your project ID.
The App represents a class that contains the logic for your application interacting with a blockchain. Each App maintains a state and includes one or multiple functions that modify the state.
It's time to implement the business logic for our tree-planting application. Open your forest.js file, and import the App object from the mintBlue SDK to create our application logic.
Now, we can add the Forest class that implements the SDK App class. It expects an AppState called state. The state object contains our planted trees and an estimation of the carbon we've offset.
The plantTrees function expects a location and the amount of trees we've planted. Notice the _ctx context argument, a mandatory argument containing the application context. If a public function modifies the state, it requires the _ctx argument as the first argument.
When you plant a new tree, we automatically update the estimated carbon offset in the state with the result of a private function. This function doesn't require the _ctx because it doesn't directly modify the state.
The forest application logic is ready to create our forest Machine.
The Forest class has already been imported. We must create a new MemoryRecorder and our blockchain Reader and Writer. Besides that, we tell the machine to emit application events with the same name as our app function and send the latest snapshot.
And finally, the getInstance() method lets us get an instance of our machine that we can use in the next step to interact with. The app object represents a proxied version of the application logic where our plantTrees() method is wrapped to write actions to the action storage automatically. In this example, the action storage is a blockchain, but it can also be an alternative storage solution like an S3 bucket.
When we call a function on the app object, like plantTrees(), it won't execute it. It will write the function name and arguments to the blockchain.
When the MintblueReader receives an event from the mintBlue platform, the plantTrees() function is executed, and the application state is updated.
📚 If you want to learn more about this software design pattern, it's called Command-Query Responsibility Segregation (CQRS) in Event Sourcing.
Let's have some fun with our Forest application 🥳 We would like to add an event handler to listen for freshly planted trees, plant a new tree in Brussels, and start dispatching events from the Reader to update our application state.
First, let's listen for plantTrees evens. You can add a new event listener to the machine object using the .on keyword and provide it with the function name you want to listen for. Make sure the function exists in your AppLogic, like our plantTrees function.
To verify our state has been updated, let's log the application state by accessing the state property of the app object.
Now, let's plant a new tree by calling our application instance. Remember, we are not executing the function in the AppLogic. We are sending the function name and arguments to the mintBlue platform to be recorded on the blockchain.
Let's log the application state here. You'll find an empty state because the state is only updated when our Reader receives an event.
Therefore, let's start our Reader in the next step.
Let's start dispatching events by calling the start() function on the machine object. It instructs the Reader to begin dispatching events, like our plantTrees events.
When this function is called, we expect the event listener to print the text A tree was planted with its location and update the state by executing our plantTrees function. This will update the state. You should see the following state, including three planted trees in Brussels.
Below, you can find the full code implementation.