This is a short guide for those of you who want to create your own NFTs using the new Enjin ecosystem.
My assumption is that you are a Windows dev with limited knowledge of Docker and Linux. If you are a Mac dev or have extensive Linux and Docker experience some points of this guide will be more ‘nice to know’ stuff.
The end goal here is to end up with an ENJIN wallet Daemon running in your own cloud/hosted server.
Lets get started.
To make test faster we START with a local (Windows) deployment. When that works we deploy to our final cloud destination.
Setting Up your Enjin account
Create or Login to your Enjin account : https://platform.enjin.io/login
Goto your Settings page and create a new API KEY. NOTE the API Key will disappear after initial creation SO COPY IT.
Setting Up Windows
- Install Docker Desktop (you must be on Win11 or Win 10 with WSL2): https://www.docker.com/products/docker-desktop/
- Install Ubuntu from from the Windows Store. (Remember to save your sudo password which you will be prompted for during install)
- You should now see a new Linux folder in your Windows Explorer..cool.
- Open Docker Desktop. Goto Settings(right hand side top bar)->Resources->WSL integration and activate the Ubuntu toggle under “Enable integration with additional distros:”. This way we don’t need to seperately install Docker on our Ubuntu instance
- Install WinSCP: https://winscp.net/eng/index.php
Prep for Docker/Wallet build.
- Open Ubuntu (you should see a teminal pop up)
- Check git is installed by typing
git version. #or if git is not install install if with sudo git install -y
3. Check docker and docker compose version
docker --version
docker-compose --version
4. If docker / docker-compose are not setup see : https://cloudkatha.com/how-to-install-docker-on-amazon-linux-2023/?utm_content=cmp-true%27. Note that the docker install is OPTIONAL as we will mainly be relying on the Docker Engine provided by Docker Desktop,
5. Now we can pull the main enjin platform repo:
Git clone https://github.com/enjin/platform.git
6. Depending on your Git setuo this pull might not have pulle the latest Wallet Daemon. So if the new platform folder does NOT contain a wallet-daemon folder you need to:
cd platform #move into the new platform folder
https://github.com/enjin/wallet-daemon.git
7. It is now time to BUILD the wallet.
First we need to understand some basics about how the wallet opeerates.
1. Building the wallet needs to be done on an environment similar to the one it will eventually be running in. This is why we should build the wallet in the same Dockerfile we use to create the docker container.
2. The build wallet is just a binary file independent of any keys/codes etc. This is why we can build the wallet locally and then copy it to our build (see below)
3. When the wallet starts up it does the following:
- Check in ENV variable KEY_STORE is set. If so it will check ENV KEY_PASS and validate they match.
- If ENV var KEY_STORE is empty it will look in /store for a Key file and if found load it. It will then again validate they Key file match the ENV var KEY_PASS.
- If KEY_STORE is not found in neither ENV or /store it will generate a new Key file using the ENV var KEY_PASS as seed. If ENV KEY_PASS is not set I’m note sure what happens. So KEY_PASS – KEY file pair must match but can be used with any properly generate wallet.
Now let us proceed to build the wallet and and run it for the first time to let the wallet create our new Key file
8. first check in the wallet-daemon/store/ folder and DELETE any demo key you might find there (you can do this from Windows Explorer)
9. Update the config.json file in the /platform/configs/daemon/ folder to
{
"node": "wss://rpc.matrix.blockchain.enjin.io:443",
"api": "https://platform.enjin.io/graphql",
"master_key": "/opt/app/storage"
}
11. Update the .env file in the /platform/configs/daemon/ folder to
KEY_PASS=MySecretKeyPass
CONFIG_FILE=/opt/app/config.json
PLATFORM_KEY=YourEnjinAPIKey
RUST_LOG=trace
3. Update the Dockerfile in the /platform/configs/daemon to
FROM debian as sources
WORKDIR /wallet
COPY /wallet-daemon .
FROM rust:1.59.0-buster as cargo-build
ARG PROFILE=release
ENV CARGO_HOME=/wallet/.cargo
WORKDIR /wallet
COPY --from=sources '/wallet' '/wallet'
RUN cargo build --$PROFILE --package bin
# Stage: slim
FROM debian:buster-slim as slim
RUN apt-get -y update && apt -y install nano
ARG PROFILE=release
# Reqwest needs libssl and curl is needed to install the ca-certificates.
RUN apt-get update && \
apt-get install -y libssl-dev wait-for-it jq curl zip dos2unix
RUN rm -rf /var/lib/apt/lists/*
# Copy wallet daemon binary.
COPY --from=cargo-build /wallet/target/$PROFILE/wallet /usr/local/bin
# Stage: wallet-daemon
FROM slim as wallet-daemon
LABEL org.opencontainers.image.source=https://github.com/enjin/wallet-daemon
LABEL org.opencontainers.image.description="Platform - Matrix Wallet Daemon"
LABEL org.opencontainers.image.licenses=LGPL-3.0-only
COPY configs/daemon/config.json /opt/app/config.json
COPY configs/daemon/.env /usr/local/bin/.env
COPY configs/daemon/start.sh /usr/local/bin/start
RUN dos2unix /opt/app/config.json
RUN dos2unix /usr/local/bin/.env
RUN dos2unix /usr/local/bin/start
# ENTRYPOINT ["/usr/local/bin/start.sh"]
CMD ["/usr/local/bin/start"]
3. Update the start.sh file in the /platform/configs/daemon to
#!/bin/bash
set -o allexport
source .env set
set +o allexport
# Run wallet
wallet
DOCKER BUILD AND DEPLOY
We are now ready to create our Image and Container. This step will also CREATE our new wallet AND run it for the first time.
MAKE SURE DOCKER DESKTOP IS RUNNING.
sudo docker-compose build --no-cache daemon
sudo docker-compose up -d daemon
Open Docker Desktop and under Containers select your new Container (it should be running). Check the Logs and here you should see a ton of TRACE and DEBUG items but if all went well no ERROR (in red) entries. At the very beginning of the Dockere Log you will find 3 substrate address printed.
Your new daemon wallet is the Efinity: ef…….. one.
In Docker Desktop select the Container and view files:
-Find /opt/app/Storage and here you should find a new Key file…right click and SAVE (we will need it later).
– Find /usr/local/bin and here you should find the generated Wallet..right click and SAVE (we will need it later).
To complete this step Log back into your enjin account. Goto Settings and here Edit + Paste your new ef…. wallet in the Wallet Account field. Save.
CONGRATZ you got your wallet.
Now some of you might wonder why I don’t just use the start.bat or start.sh scripts in the platform repo…I tried and could not get it to work properly…but if some of you has some experiences using these scripts for wallet-damon builds only..let me know.
Next step : Deploy to Clound instance
CLOUD DEPLOY
There are many options when it comes to cloud servers, but first you need to realize that the wallet is a poll based encryption sw. This means it is NOT suitable for deployment on serverless applications like GCR or AWS Lamba. We need a basic linux server. I will be using AWS EC2 t3.micro here but DigitalOcean droplets or similar can be used as well…it’s up to you. Going price for these small servers are around $5 per month..but free tier options and cheaper option might be out there.
Spin up a Cloud Server.
In this care I’m using an EC2 AWS Linux3 t3.micro server.
From the server admin panel Create and download an SHH key (.PEM) which we will need for easy file and terminal access.
Note that newer .PEM keys have to be ‘private’ and sometimes you need to remove the Users group on the .PEM file (Properties.Security delete Users group and apply)
Setup WinSCP for access to your new Server. Create a SCP connection to your server using the downloaded .PEM file (Note that WinSCP might want to convert your .PEM file into a Putty key format..do so)
Upload docker platform build:
First we going into Windows Explorer and COPY our platform from Ubuntu (/home/<username>/platform) to a location on our Windows box (“C:/.).
We DELETE the C:…/platform/wallet-daemon folder as we do not need it anymore.
We now MOVE the Wallet binary we saved early (the one which was created in the docker build above) into C:…/platform/configs/daemon/ (where .env and config.json resides)
Now we make a couple of changes to the Windows platform folder (C:…/platform/configs/daemon/)
Update C:…/platform/configs/daemon/.env to:
KEY_PASS=MySecretKeyPass
STORE_NAME=7372323..your key file name.c246022f
KEY="the key file phrases found inside the key file"
CONFIG_FILE=/opt/app/config.json
PLATFORM_KEY=YourEnjinAPIKey
RUST_LOG=trace
Update C:…/platform/configs/daemon/Dockerfile to:
FROM debian as sources
WORKDIR /wallet
COPY /wallet-daemon .
FROM rust:1.59.0-buster as cargo-build
ARG PROFILE=release
ENV CARGO_HOME=/wallet/.cargo
WORKDIR /wallet
COPY --from=sources '/wallet' '/wallet'
# Stage: slim
FROM debian:buster-slim as slim
ARG PROFILE=release
# Reqwest needs libssl and curl is needed to install the ca-certificates.
RUN apt-get update && \
apt-get install -y libssl-dev wait-for-it jq curl zip dos2unix
RUN rm -rf /var/lib/apt/lists/*
# Stage: wallet-daemon
FROM slim as wallet-daemon
LABEL org.opencontainers.image.source=https://github.com/enjin/wallet-daemon
LABEL org.opencontainers.image.description="Platform - Efinity Wallet Daemon"
LABEL org.opencontainers.image.licenses=LGPL-3.0-only
COPY configs/daemon/config.json /opt/app/config.json
COPY configs/daemon/.env /usr/local/bin/.env
COPY configs/daemon/start.sh /usr/local/bin/start
COPY configs/daemon/wallet /usr/local/bin/wallet
RUN dos2unix /opt/app/config.json
RUN dos2unix /usr/local/bin/.env
RUN dos2unix /usr/local/bin/start
RUN dos2unix /usr/local/bin/wallet
CMD ["/usr/local/bin/start"]
We now open WinSCP and open a connection to our Server.
MOVE/COPY the entire C:…/platform folder to the root/home folder on your server.
When you move files between Linux and Windows you sometimes lose file permission flags. This is not an issue for you are a hardcore linux dev who wanna move the platform files directly from the local box to the server!.
We reset the permission flags on the server by EITHER using WInSCP where you right click the files on the Server and select Properties and there enable all the X flags. OR we do it on the Server itself by opening your server terminal (PowerShell is my preferred) and go to /platform/configs/deamon/ and type
cd platform/configs/daemon
chmod +x start.sh
chmod +x config.json
chmod +x .env
chmod +x wallet
chmod +x Dockerfile
We now now need to prepare our cloud server for Docker..
sudo dnf update //To Install Latest Update
sudo dnf install -y docker // Install Docker
docker --version //to check install
//install Docker Compose
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version //to double check
We might need to start the Docker engine:
sudo systemctl start docker.service // To start Docker Service
sudo systemctl enable docker // To Automatically start Docker on Reboot
We now now get to the scary bit.
In the Server terminal we ensure that we are in the /platform folder and then type
sudo docker-compose build --no-cache daemon
sudo docker-compose up -d daemon
We now need to check if the new Docker Container is running successfully
docker ps -aq //This will show the ID of the running container
docker logs <containerid>
The Logs SHOULD show similar logs from Docker Desktop with tons to Trace and Debugs and alittle down in the log also a HelloClient and HelloServer handshakes.
NOTE I’m not sure why but sometimes this build will generate NEW substrate addresses (even we have used the SAME wallet and SAME key we used in our Docker Desktop test). Anyways it is THIS Efinity (ef….) address you want use (in your Enjin Account.Settings link THIS new ef addres as you Wallet Account )
Now while Docker logs do have some cycling I really don’t like have a server spitting out detailed logs (both from a performance and cybersecurity point of view).
So first we need to stop our Container..
docker-compose down
Open WinSCP again and connect to he Server. Open the /platform/configs/daemon/.env file and change the RUDT_LOG setting. Note that I have added Nano in case you want to do this directly from server terminal.
RUST_LOG=info
Before we spin up the container again with the new .env setting we do a little house cleaning, before we rebuild and re deploy.
docker rmi $(docker images -q)
sudo docker-compose build --no-cache daemon
sudo docker-compose up -d daemon
docker ps //to get the NEW container build
docker logs <containerid>
You should now see a smaller log with just the substrate address (CHECK THAT THE ef..address is still the same as above) and one or two INFO entries.
That is it…YOUR WALLET IS LIVE.
Some notes on security and performance
– The wallet server pools for and signs transactions so when you get alot of transactions the wallet might slow even crash. In this case you might need to increase the RAM and CPU for your server box.
– The .env file contains ALL the keys to the castle…keep it VERY confidential. Ideally you would want to pass in the KEY_PASS and PLATFORM_KEY as commandline parameters and NOT have in sitting in clear text in the .env file.
Next steps it to FUND our wallet and make some transactions.
First we spin up GraphQL to check our Wallet: https://platform.enjin.io/graphiql
To make calls against this endpoint we need to be authenticated by adding the following to the HEADER tab in the lower left side.
{
"Authorization" : "YourEnjinAPIKey"
}
We can then run the query to info about our Enjin project Wallet
query GetWalletQuery
{
GetWallet(account:"efTdx...your Efinity address....ew1LXyK3")
{
id
account { address publicKey}
balances { free, feeFrozen, miscFrozen}
}
}
On the Result tab you should now see some info about your account including 0 free (since we have not funded it yet).
Lets fund it.
At this point I assume you have an Enjin Wallet on your phone (or enjin web wallet) and have some of the (new) ENJ available
Goto to your Enjin Matrix wallet and add Contact…MANUALLY enter the Efinity address from above. Then Send some ENJ (min 10) to test.
Give enjin some time to process the transaction then run the query above again and you SHOULD now see free “1000000000” ish. Remember these saldos are in GWEI.
Now let’s head over to your enjin.io/platform account and here you CREATE a new Collection. This will cost some ENJ. In my case the cost was around 7ENJ but not sure if that is a ‘fixed’ price or not.
Creating the Collection requires your Wallet-daemon to sign the transaction, so if this transaction goes through you know that your cloud wallet-daemon has done its job.
Run the GetWallet query again an you should now see the free number go down by 7ENJ or so.
Note, that there is some non-intuitive stuff going on with these substrate addresses. For instance if you created your account and added one Efinity address and then later want to Edit/Update the Wallet Address with a new Efinity address it LOOKS like it does not work..but the trick here is that when you press Update the new Efinity address IS indeed linked..it just does not look like it. In GraphQL you will see that all Efinity address you link will all reference to the same Project ID. Just be sure that the Efinity address in your Wallet-Daemon is the one you fund.
The Daemon Wlallet is up and working and you can fund you project wallet. Sit back and enjoy.