First you need node and npm, which are probably not installed yet. node is the main interpreter of the Node.js JavaScript runtime environment, while npm is the node package manager used to manage JavaScript packages and dependencies. You probably know JavaScript from websites, with Node.js it can also be used for server side applications. Unfortunately Ubuntu doesn’t install a recent version of Node.js by default, so you have to add a ppa for that (a personal package archive, meaning it’s a third party contribution).

~# curl -sL https://deb.nodesource.com/setup_10.x \

-o nodesource_setup.sh

~# chmod +x nodesource_setup.sh

~# sudo ./nodesource_setup.sh

This didn’t install npm yet, it only setup the system so it knows where to find the current version by downloading and executing a script, which in the end simply added a new package source in /etc/apt/sources.list.d/.

Now you can install Node.js as usual:

~# sudo apt-get install nodejs

You can check that it worked like this:

~# node -v v10.15.0

The version returned should be at least 10.15.x (or later).

If you’re not using Ubuntu (or as an alternative method) you can try nvm.

You also have to install a Python interpreter (yet another programming language, but a great one which I’d recommend taking a closer look at if you plan to learn some coding) and some tools required to compile applications. On Ubuntu there’s a package called build-essential which contains what is needed, so install it:

~# sudo apt-get install python build-essential

This will probably install a plethora of dependencies, that’s fine. The system package manager fortunately handles it all. If you compiled the node yourself (see part 2), you already have the build-essential package, but it doesn’t hurt to use the command again, apt-get will simply ignore it.

You also need git, which should be installed already (otherwise do so). Git is a version-control system heavily used in open source projects, and you’ve surely been on GitHub before, which derived its name from it. You have to clone the web3-fusion-extend repository:

~# git clone https://github.com/FUSIONFoundation/web3-fusion-extend.git Cloning into 'web3-fusion-extend'...

remote: Enumerating objects: 48, done.

remote: Counting objects: 100% (48/48), done.

remote: Compressing objects: 100% (38/38), done.

remote: Total 666 (delta 19), reused 35 (delta 10), pack-reused 618

Receiving objects: 100% (666/666), 172.44 KiB | 832.00 KiB/s, done.

Resolving deltas: 100% (373/373), done.

There’s now a local versioned copy of the Fusion JavaScript API on your system. It contains the base files required to setup the auto buying of tickets in the shell. Jump to to the correct subdirectory

~# cd web3-fusion-extend/examples/autoPurchaseTickets/

and then enter

~# npm install

npm doesn’t need any other arguments in this case, since it will look for a file called package.json in the directory you’re currently in and does what is defined in it. It’ll download many dependencies and build some stuff now, this might take a while. If it exits with an error, it’ll usually tell you what exactly went wrong. You might have to scroll up a bit though.

You can now use node (which is the name of the Node.js main executable in this case, not related to your Fusion node) to run autoPurchaseTicket.js. A real-world example would look like this for the node you setup earlier:

~# node autoPurchaseTicket.js \

-c "wss://mainnetpublicgateway1.fusionnetwork.io:10001" \

-p "/var/lib/fusion/password.txt" \

-k "/var/lib/fusion/data/keystore/UTC--2018-12-29T00-19-08.227Z--0x0000000000000000000000000000000000000000" \

-d 32659 -n 1000

-n 1000 is the amount of tickets you want to buy. You can set it to some really high value, more than you could actually buy with the amount of PSN you have, then it’ll always use the full balance. -d 32659 is the ChainID.

-c “wss://mainnetpublicgateway1.fusionnetwork.io:10001” is the gateway you’ll be using to buy tickets. You can also use your own:

~# node autoPurchaseTicket.js \

-c "ws://127.0.0.1:9001" \

-p "/var/lib/fusion/password.txt" \

-k "/var/lib/fusion/data/keystore/UTC--2018-12-29T00-19-08.227Z--0x0000000000000000000000000000000000000000" \

-d 32659 -n 1000

This only works if you’re running the tool on the same system as your node of course. Note that it’s ws instead of wss here because it’s an unencrypted local connection (similar to HTTP and HTTPS), and that the port is 9001 instead of 10001.

If you see this when the tool starts

Unable to decrypt file Error: Key derivation failed - possibly wrong password

then the password in your password.txt is incorrect. It has to be the same you’re using to run the node. The file has to be UTF-8 encoded; you can do this with Notepad++ for example. Just open the file and select Encoding > Convert to UTF-8 from the menu.

This on the other hand isn’t a real error (despite insisting that it is):

error Error: Returned error: not enough time lock or asset balance

You’ll see it when your -n parameter exceeds the number of tickets you can actually buy and simply means that you already bought the maximum amount of tickets your available PSN allows.

Visit the Staking Monitor to see if you’re acually staking. “Staking Status” should be “Active” and you should see a value greater than zero for “Tickets”.

You can simply run autoPurchaseTicket.js in a screen session (see part 1) and keep it that way. Alternatively, you can install pm2, the Node.js process manager, which allows you to run the application in the background “the Node.js way”.

~# sudo npm install pm2 -g

This will install another bunch of dependencies, too. -g installs the package globally, so it can be used anywhere on the system and not only with this project. The command has to be changed so it looks like this:

~# sudo pm2 start autoPurchaseTicket.js --watch --force -- \

-c "wss://mainnetpublicgateway1.fusionnetwork.io:10001" \

-p "/var/lib/fusion/password.txt" \

-k "/var/lib/fusion/data/keystore/UTC--2018-12-29T00-19-08.227Z--0x0000000000000000000000000000000000000000" \

-d 32659 -n 1000

You’re now running autoPurchaseTicket.js under the control of pm2. You don’t have to call node explicitly here, pm2 does that for you. The — watch option makes pm2 automatically restart the process if autoPurchaseTicket.js changes, e.g. when it’s updated. — force allows you to run the same script multiple times with different arguments, for example if you want to start it both with the central and your local gateway for whatever reason.

Note the two hyphens at the end of the first line, they make sure that all arguments that follow are passed to the auto buy tool and not to pm2, which wouldn’t understand them.

pm2 has a lot of commands, most of which you probably won’t need. Enter

~# pm2 -h

to see all of them. For now you’ll only need the following:

~# sudo pm2 list

This returns a list of running processes. You need the process ID or name to control a process. Currently there should be only one process with ID 0.

~# sudo pm2 log 0

Since the process is running in the background, you don’t see its output normally. log allows you to see what it’s doing. Alternatively you can use attach, which looks exactly like it would on the normal shell. It works dfferently, but that doesn’t really matter in this case.

~# sudo pm2 show 0

This shows all kinds of interesting information about a process.

~# sudo pm2 stop 0

This stops the process. It still appears in the process list though (pm2 list), so you can easily start it again by entering

~# sudo pm2 start 0

instead of the whole long command you initially used. If you want to get rid of the process altogether, use

~# sudo pm2 delete 0

To update the auto buy tool, just pull the current version from Github, and also update the Node.js packages it depends on:

~# cd web3-fusion-extend/examples/autoPurchaseTickets/

~# git pull

~# npm install

If you’re using pm2, it’ll automatically restart the process, otherwise stop and start it manually.

Someone asked what’s actually going on with all the gateway and buying tickets stuff, so some words on this. It’s not part of the setup process anymore, so feel free to skip it if you don’t care.

A gateway is basically just a node without the staking part, so it doesn’t create new blocks by itself (or seal blocks, as it’s called officially) but only syncs the blockchain, answers requests and broadcasts transactions.

Whenever you interact with a node, e.g. by sending coins via MyFusionWallet, that involves talking to one of its RPC interfaces (like the Websocket you’re using locally on port 9001). So there’s a dedicated, often configurable, node behind every graphical frontend you see.

These interfaces expose functions, which are bundled in modules. Which modules you can use is configured when the node starts, because you don’t want to make a function like admin.stopWS or miner.start available to the whole world. The option looks like this for the Websocket interface for example: — wsapi eth,net,fsn,fsntx. You can see the modules and their functions here; the ticket buying happens through a set of modules specifically built for Fusion, whose names are unsurprisingly starting with fsn.

Now when you’re running autoPurchaseTicket.js, it‘ll mostly say this:

0|autoPurc | 15 of 100 purchasing one, action happening around block 2954

0|autoPurc | wait for buy ticket tx -> 0x72796c67cd3055d1fba5ca7c484a831499c1a5257d313ef2eb2362cc9b08feab

0|autoPurc | Ticket bought

You can deduce that it creates a transaction and waits for its completion, so buying tickets happens on the blockchain too and is not some kind of off-chain process. You can also find these transactions on the Block Explorer.

The script is generally built on Web3.js functions which are extended with Fusion specific additions, so consequently the Github repository you cloned ealier is called web3-fusion-extend.

Internally, the whole magic boils down to this part:

const tx = await web3.fsntx.buildBuyTicketTx({ from: key.address });

tx.gasPrice = web3.utils.toWei(new web3.utils.BN(gasPrice), "gwei"); const txHash = await web3.fsn.signAndTransmit(

tx,

signInfo.signTransaction

);

console.log("wait for buy ticket tx -> ", txHash);

Here a transaction is created based on information the gateway provides, using the gas price you specified with the -g option. There’s no need to increase this, as buy ticket transactions will always be included in a block first to prevent the network from stalling. It then gets signed and transmitted back to the gateway, which then broadcasts it to other nodes.

The process of signing a transaction is client side and can also be done offline; you may have already wondered what this is good for for example.