Home

Validator Nodes

Introduction#

Dijets Primary Network validates Dijets Ternary Chain Ledgers. In this tutorial, we’ll add a node to the Primary Network on Dijets.

The Method Chain manages metadata on Dijets. This includes tracking which nodes are in which Subnets, which blockchains exist, and which Subnets are validating which blockchains. To add a validator, we’ll issue transactions to the Method Chain.

caution

Note that once you issue the transaction to add a node as a validator, there is no way to change the parameters. You can’t remove your stake early or change the stake amount, node ID, or reward address. Please make sure you’re using the correct values in the API calls below. If you’re not sure, feel free to join our Qowalts to ask questions.

Requirements#

You've completed Run an Dijets Node and are familiar with Dijets architecture. In this tutorial, we use DijetsJS and Dijets Postman collection to help us make API calls.

In order to ensure your node is well-connected, make sure that your node can receive and send TCP traffic on the staking port (9651 by default) and that you started your node with config flag --public-ip=[YOUR NODE'S PUBLIC IP HERE]. Failing to do either of these may jeopardize your staking reward.

Add a Validator with Dijets Wallet#

First, we show you how to add your node as a validator by using Dijets Wallet.

Retrieve the Node ID#

Get your node’s ID by calling info.getNodeID:

curl -X POST --data '{
    "jsonrpc":"2.0",
    "id"     :1,
    "method" :"info.getNodeID"
}' -H 'content-type:application/json' 127.0.0.1:9650/ext/info

The response has your node’s ID:

{
  "jsonrpc": "2.0",
  "result": {
    "nodeID": "NodeID-5mb46qkSBj81k9g9e4VFjGGSbaaSLFRzD"
  },
  "id": 1
}

Add as a Validator#

Open the wallet, and go to the Earn tab. Choose Add Validator under the Validate section.

Fill out the staking parameters. They are explained in more detail in this doc. When you’ve filled in all the staking parameters and double-checked them, click Confirm. Make sure the staking period is at least 2 weeks, the delegation fee rate is at least 2%, and you’re staking at least 2,000 DJTX on Mainnet (1 DJTX on Dijets TestNet Testnet).

You should see a success message, and your balance should be updated.

Calling platform.getPendingValidators verifies that your transaction was accepted. Note that this API call should be made before your node's validation start time, otherwise, the return will not include your node's id as it is no longer pending.

Go back to the Earn tab, and click Estimated Rewards.

Once your validator’s start time has passed, you will see the rewards it may earn, as well as its start time, end time, and the percentage of its validation period that has passed.

You can also call platform.getCurrentValidators to check that your node's id is included in the response.

That’s it!

Add a Validator with DijetsJS#

We can also add a node to the validator set using DijetsJS.

Install DijetsJS#

To use DijetsJS, you can clone the repo:

git clone https://github.com/Dijets-Inc/dijetsjs.git

or add it to an existing project:

yarn add dijets

For this tutorial we will use ts-node to run the example scripts directly from an DijetsJS directory.

Dijets TestNet Workflow#

In this section, we will use Dijets TestNet Testnet to show how to add a node to the validator set.

Open your DijetsJS directory and select the examples/platformvm folder to view the source code for the examples scripts.

We will use the buildAddValidatorTx.ts script to add a validator. To learn more about the buildAddValidatorTx API, please click here.

Private Key

Locate this line in the file

const privKey: string = `${PrivateKeyPrefix}${DefaultLocalGenesisPrivateKey}`

and replace this with a private key that you control. You can use this code to generate a new key.

const privKey: string = "<YOUR-PRIVATE-KEY-HERE>"

Network Setting

The following settings work when using a local node started with --network-id=testnet:

const ip: string = "localhost"
const port: number = 9650
const protocol: string = "http"
const networkID: number = 5

However, to connect directly to the Dijets API server, the following changes are needed:

const ip: string = "dijets.ukwest.cloudapp.azure.com"
const port: number = 443
const protocol: string = "https"
const networkID: number = 1

Depending on the networkID passed in when instantiating an Dijets object in the code, the encoded addresses used will have a distinctive Human Readable Part(HRP) per network.

Example Address: 5 - X-dijets19rknw8l0grnfunjrzwxlxync6zrlu33yxqzg0h

For Dijets TestNet Testnet, 5 is the correct value to use.

To learn more about encoded addresses, click here.

Settings for Validation

Next we need to specify the node's validation period and delegation fee.

const nodeID: string = "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg"
const startTime: BN = UnixNow().add(new BN(60 * 1))
const endTime: BN = startTime.add(new BN(26300000))
const delegationFee: number = 10

Node ID

This is the node ID of the validator being added. See above section on how to retrieve the node id by using API info.getNodeID.

Staking Period

startTime and endTime are required to specify the time of starting/leaving validation. The minimum duration that one can validate the Primary Network is 2 weeks, and the maximum duration is one year. One can start a new validation on the Primary Network after finishing one, it’s just that the maximum continuous duration is one year. startTime and endTime are the Unix times when your validator will start and stop validating the Primary Network, respectively. startTime must be in the future relative to the time the transaction is issued.

The sample code uses const startTime: BN = UnixNow().add(new BN(60 * 1)) and const endTime: BN = startTime.add(new BN(26300000)) to compute the Unix time 1 minute and 304 days in the future (at the time when this article was written) to use as the values of startTime and endTime, respectively.

:::tip

You can create your own Unix timestamp here or by using the UnixNow() method

:::

To create your own start times, please follow the steps below:

Locate this line in the file

const startTime: BN = UnixNow().add(new BN(60 * 1))
const endTime: BN = startTime.add(new BN(26300000))

Change startTime and endTime to new BN values, for example:

const startTime: BN = new BN(1654656829) // Wed Jun 08 2022 02:53:49 GMT+0000
const endTime: BN = new BN(1662602029) // Thu Sep 08 2022 01:53:49 GMT+0000

Delegation Fee Rate

Dijets allows for delegation of stake. This parameter is the percent fee this validator charges when others delegate stake to them. For example, if delegationFeeRate is 10 and someone delegates to this validator, then when the delegation period is over, 10% of the reward goes to the validator and the rest goes to the delegator, if this node meets the validation reward requirements.

Stake Amount

Set the proper staking amount in calling pchain.buildAddValidatorTx by replacing stakeAmount.minValidatorStake with a number in the unit of gwei, for example, BN(1e12) which is 10,000 DJTX.

Addresses

By default, the example uses the variable pAddressStrings to define toAddresses, fromAddresses, changeAddresses and rewardAddresses:

const pAddressStrings: string[] = pchain.keyChain().getAddressStrings()

This retrieves the Method Chain addresses that belong to the private key that appears earlier in the example.

No change is needed in the addresses for the default action. For customization, please refer to this section.

Execute the Code

Now that we have made all of the necessary changes to the example script, it's time to add a validator to the Dijets TestNet Network.

Run the command:

ts-node examples/platformvm/buildAddValidatorTx.ts

The response has the transaction ID.

Success! TXID: 2ftDVwmss5eJk8HFsNVi6a3vWK9s3szZFhEeSY2HCS8xDb8Cra

We can check the transaction’s status by running the example script: getTxStatus.ts following the steps below:

  1. Ensure that your network settings are correct before running the script.

  2. Locate this line in the file

const main = async (): Promise<any> => {
  const txID: string = "x1NLb9JaHkKTXvSRReVSsFwQ38mY7bfD1Ky1BPv721VhrpuSE"
  ...
  }

and replace it with the buildAddValidator TXID

const main = async (): Promise<any> => {
 const txID: string = "2ftDVwmss5eJk8HFsNVi6a3vWK9s3szZFhEeSY2HCS8xDb8Cra"
 ...
 }

Run the command:

ts-node examples/platformvm/getTxStatus.ts

This returns:

{ status: 'Committed' }

The status should be Committed, meaning the transaction was successful.

We can see if the node is now in the pending validator set for the Dijets TestNet network by using the example:getPendingValidators.ts. Just change the network settings to meet Dijets TestNet requirements and then run the script:

ts-node examples/platformvm/getPendingValidators.ts

The response should include the node we just added:

{
  "validators": [
    {
      "nodeID": "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg",
      "startTime": "1654656829",
      "endtime": "1662602029",
      "stakeAmount": "1000000000"
    }
  ],
  "delegators": []
}

When the time reaches 1654656829 (Wed Jun 08 2022 02:53:49 GMT+0000), this node will start validating the Primary Network. When it reaches 1662602029 (Thu Sep 08 2022 01:53:49 GMT+0000), this node will stop validating the Primary Network. The staked DJTX and the rewards, if any, will be returned to pAddressStrings.

Customizing Addresses

There are 4 addresses which are needed when calling pchain.buildAddValidatorTx. Only 2 of them can be changed: toAddresses and rewardAddresses. For backward-compatibility reasons, fromAddresses and changeAddresses are just placeholders and are ignored.

toAddresses

An array of addresses who receive the staked tokens at the end of the staking period.

rewardAddresses

When a validator stops validating the Primary Network, they will receive a reward if they are sufficiently responsive and correct while they validated the Primary Network. These tokens are sent to rewardAddresses. The original stake will be sent back to the addresses defined in toAddresses.

A validator’s stake is never slashed, regardless of their behavior they will always receive their stake back when they’re done validating.

Locate this part of the code

let privKey: string = `${PrivateKeyPrefix}${DefaultLocalGenesisPrivateKey}`
pKeychain.importKey(privKey)

and replace privKey with private keys that you control. To generate a new keypair, we can use the createKeypair.ts example script along with Dijets TestNet Network Settings.

let privKey: string =
  "PrivateKey-PY2dvfxzvBAe1a5nn7x23wmZMgAYJaS3XAZXzdUa22JtzUvKM"
pKeychain.importKey(privKey)
privKey = "PrivateKey-2Y3Vg9LShMJyUDBHzQqv5WtKDJ8yAVHyM3H5CNCBBmtg3pQEQG"
pKeychain.importKey(privKey)
privKey = "PrivateKey-NaV16owRSfa5TAtxtoU1BPUoM2y1ohttRbwKJG1j7onE4Ge1s"
pKeychain.importKey(privKey)
priKey = "PrivateKey-26JMUsR5RCkf5k9ME8WxKCWEuCK5s2SrALUn7vEa2urwyDDc91"
pKeychain.importKey(privKey)

const pAddressStrings: string[] = pchain.keyChain().getAddressStrings()

This example would create a keychain with 4 addresses:

  "P-dijets1jx644d9y00y5q4hz8cq4wr75a2erne2y4e32xc", // pAddressStrings[0]
  "P-dijets1wchdgdp94j8tszlpsp56qvgkvdn20svpmnm8qk", // pAddressStrings[1]
  "P-dijets1f36kkpy6yzd7ayrywxvvprns7qlrcu3hwqdya8", // pAddressStrings[2]
  "P-dijets1qw7yt3fp43kuwsufff4vhezs2yl00slr09vmh5", // pAddressStrings[3]

Now we can pass in each address according to its slot in the pAddressStrings array:

const unsignedTx: UnsignedTx = await pchain.buildAddValidatorTx(
  utxoSet,
  [pAddressStrings[0], pAddressStrings[1]], // toAddresses, one or more addresses
  [pAddressStrings[0]], // fromAddresses, required for backward-compatibility
  [pAddressStrings[0]], // changeAddresses, required for backward-compatibility
  nodeID,
  startTime,
  endTime,
  stakeAmount.minValidatorStake,
  [pAddressStrings[2], pAddressStrings[3]], //rewardAddresses, one or more addresses
  delegationFee,
  locktime,
  threshold, 
  memo,
  asOf
)

Mainnet Workflow#

The Dijets TestNet workflow above can be adapted to Mainnet with the following modifications:

Need some help?

You can join Dijets Support Space for a live chat with one of the team members. Join us on Qowalts.