From 3c398901e76335a9f417009b3cf54295d204951c Mon Sep 17 00:00:00 2001
From: aman035 <guptaaman200115@gmail.com>
Date: Fri, 14 Jun 2024 13:48:03 +0530
Subject: [PATCH] fix: added validator class and fix api route

---
 packages/d-node-notif/project.json            |    2 +-
 .../d-node-notif/src/lib/abis/validator.ts    | 1134 +++++++++++++++++
 .../src/lib/alias/getAliasInfo.ts             |    2 +-
 .../src/lib/channels/_getSubscribers.ts       |    2 +-
 .../src/lib/channels/getChannel.ts            |    2 +-
 .../lib/channels/getChannelNotifications.ts   |    2 +-
 .../src/lib/channels/getChannels.ts           |    2 +-
 .../src/lib/channels/getDelegates.ts          |   22 +-
 .../src/lib/channels/getSubscribers.ts        |   90 +-
 .../d-node-notif/src/lib/channels/search.ts   |   18 +-
 .../src/lib/chat/helpers/service.ts           |    4 +-
 packages/d-node-notif/src/lib/config.ts       |   43 +-
 .../d-node-notif/src/lib/helpers/config.ts    |   22 +-
 .../d-node-notif/src/lib/helpers/crypto.ts    |    8 +
 .../src/lib/payloads/sendNotifications.ts     |    2 +-
 .../pushNotification/pushNotificationBase.ts  |    2 +-
 .../src/lib/pushValidator/pushValidator.ts    |  144 +++
 .../lib/pushValidator/pushValidatorTypes.ts   |   44 +
 .../src/lib/user/getDelegations.ts            |   20 +-
 .../d-node-notif/src/lib/user/getFeeds.ts     |   14 +-
 .../src/lib/user/getFeedsPerChannel.ts        |    2 +-
 .../src/lib/user/getSubscriptions.ts          |   11 +-
 packages/d-node-notif/src/lib/user/getUser.ts |    2 +-
 .../src/lib/user/getUsersBatch.ts             |    2 +-
 .../src/lib/user/profile.updateUser.ts        |    2 +-
 packages/d-node-notif/tests/.env.sample       |    2 +-
 .../tests/lib/initialize/initialize.test.ts   |   22 +
 .../lib/pushValidator/pushValidator.test.ts   |   57 +
 28 files changed, 1545 insertions(+), 134 deletions(-)
 create mode 100644 packages/d-node-notif/src/lib/abis/validator.ts
 create mode 100644 packages/d-node-notif/src/lib/pushValidator/pushValidator.ts
 create mode 100644 packages/d-node-notif/src/lib/pushValidator/pushValidatorTypes.ts
 create mode 100644 packages/d-node-notif/tests/lib/initialize/initialize.test.ts
 create mode 100644 packages/d-node-notif/tests/lib/pushValidator/pushValidator.test.ts

diff --git a/packages/d-node-notif/project.json b/packages/d-node-notif/project.json
index 8d645914c..ce5577eb5 100644
--- a/packages/d-node-notif/project.json
+++ b/packages/d-node-notif/project.json
@@ -23,7 +23,7 @@
   },
   "test": {
     "executor": "@nrwl/workspace:run-commands",
-    "outputs": ["coverage/packages/restapi"],
+    "outputs": ["coverage/packages/d-node-notif"],
     "options": {
       "commands": ["yarn run test:d-node-notif"],
       "passWithNoTests": true
diff --git a/packages/d-node-notif/src/lib/abis/validator.ts b/packages/d-node-notif/src/lib/abis/validator.ts
new file mode 100644
index 000000000..7cb6d21ca
--- /dev/null
+++ b/packages/d-node-notif/src/lib/abis/validator.ts
@@ -0,0 +1,1134 @@
+export const validatorABI = [
+  {
+    inputs: [],
+    stateMutability: 'nonpayable',
+    type: 'constructor',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: false,
+        internalType: 'address',
+        name: 'previousAdmin',
+        type: 'address',
+      },
+      {
+        indexed: false,
+        internalType: 'address',
+        name: 'newAdmin',
+        type: 'address',
+      },
+    ],
+    name: 'AdminChanged',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'beacon',
+        type: 'address',
+      },
+    ],
+    name: 'BeaconUpgraded',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: false,
+        internalType: 'uint16',
+        name: 'valPerBlock',
+        type: 'uint16',
+      },
+      {
+        indexed: false,
+        internalType: 'uint16',
+        name: 'valPerBlockTarget',
+        type: 'uint16',
+      },
+    ],
+    name: 'BlockParamsUpdated',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: false,
+        internalType: 'uint8',
+        name: 'version',
+        type: 'uint8',
+      },
+    ],
+    name: 'Initialized',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'ownerWallet',
+        type: 'address',
+      },
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'nodeWallet',
+        type: 'address',
+      },
+      {
+        indexed: false,
+        internalType: 'enum ValidatorV1.NodeType',
+        name: 'nodeType',
+        type: 'uint8',
+      },
+      {
+        indexed: false,
+        internalType: 'uint256',
+        name: 'nodeTokens',
+        type: 'uint256',
+      },
+      {
+        indexed: false,
+        internalType: 'string',
+        name: 'nodeApiBaseUrl',
+        type: 'string',
+      },
+    ],
+    name: 'NodeAdded',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: false,
+        internalType: 'address',
+        name: 'nodeWallet',
+        type: 'address',
+      },
+      {
+        indexed: false,
+        internalType: 'address',
+        name: 'reporterWallet',
+        type: 'address',
+      },
+      {
+        indexed: false,
+        internalType: 'address[]',
+        name: 'voters',
+        type: 'address[]',
+      },
+      {
+        indexed: false,
+        internalType: 'enum ValidatorV1.VoteAction',
+        name: 'voteAction',
+        type: 'uint8',
+      },
+    ],
+    name: 'NodeReported',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'nodeWallet',
+        type: 'address',
+      },
+      {
+        indexed: false,
+        internalType: 'enum ValidatorV1.NodeStatus',
+        name: 'nodeStatus',
+        type: 'uint8',
+      },
+      {
+        indexed: false,
+        internalType: 'uint256',
+        name: 'nodeTokens',
+        type: 'uint256',
+      },
+    ],
+    name: 'NodeStatusChanged',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'previousOwner',
+        type: 'address',
+      },
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'newOwner',
+        type: 'address',
+      },
+    ],
+    name: 'OwnershipTransferStarted',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'previousOwner',
+        type: 'address',
+      },
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'newOwner',
+        type: 'address',
+      },
+    ],
+    name: 'OwnershipTransferred',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: false,
+        internalType: 'uint16',
+        name: 'nodeRandomMinCount',
+        type: 'uint16',
+      },
+      {
+        indexed: false,
+        internalType: 'uint16',
+        name: 'nodeRandomPingCount',
+        type: 'uint16',
+      },
+    ],
+    name: 'RandomParamsUpdated',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      {
+        indexed: true,
+        internalType: 'address',
+        name: 'implementation',
+        type: 'address',
+      },
+    ],
+    name: 'Upgraded',
+    type: 'event',
+  },
+  {
+    inputs: [],
+    name: 'BAN_PERCENT',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'REPORTS_BEFORE_SLASH_S',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'REPORTS_BEFORE_SLASH_V',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'REPORT_THRESHOLD_PER_BLOCK',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'SLASHES_BEFORE_BAN_S',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'SLASHES_BEFORE_BAN_V',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'SLASH_PERCENT',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'VERSION',
+    outputs: [
+      {
+        internalType: 'string',
+        name: '',
+        type: 'string',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'acceptOwnership',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    name: 'dnodes',
+    outputs: [
+      {
+        internalType: 'address',
+        name: '',
+        type: 'address',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'getActiveVNodes',
+    outputs: [
+      {
+        components: [
+          {
+            internalType: 'address',
+            name: 'nodeWallet',
+            type: 'address',
+          },
+          {
+            internalType: 'string',
+            name: 'nodeApiBaseUrl',
+            type: 'string',
+          },
+        ],
+        internalType: 'struct ValidatorV1.ActiveValidator[]',
+        name: '',
+        type: 'tuple[]',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'getDNodes',
+    outputs: [
+      {
+        internalType: 'address[]',
+        name: '',
+        type: 'address[]',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'getDNodesLength',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: '_nodeWallet',
+        type: 'address',
+      },
+    ],
+    name: 'getNodeInfo',
+    outputs: [
+      {
+        components: [
+          {
+            internalType: 'address',
+            name: 'ownerWallet',
+            type: 'address',
+          },
+          {
+            internalType: 'address',
+            name: 'nodeWallet',
+            type: 'address',
+          },
+          {
+            internalType: 'enum ValidatorV1.NodeType',
+            name: 'nodeType',
+            type: 'uint8',
+          },
+          {
+            internalType: 'uint256',
+            name: 'nodeTokens',
+            type: 'uint256',
+          },
+          {
+            internalType: 'string',
+            name: 'nodeApiBaseUrl',
+            type: 'string',
+          },
+          {
+            components: [
+              {
+                internalType: 'uint16',
+                name: 'reportCounter',
+                type: 'uint16',
+              },
+              {
+                internalType: 'uint16',
+                name: 'slashCounter',
+                type: 'uint16',
+              },
+              {
+                internalType: 'uint128[]',
+                name: 'reportedInBlocks',
+                type: 'uint128[]',
+              },
+              {
+                internalType: 'address[]',
+                name: 'reportedBy',
+                type: 'address[]',
+              },
+              {
+                internalType: 'uint128[]',
+                name: 'reportedKeys',
+                type: 'uint128[]',
+              },
+            ],
+            internalType: 'struct ValidatorV1.NodeCounters',
+            name: 'counters',
+            type: 'tuple',
+          },
+          {
+            internalType: 'enum ValidatorV1.NodeStatus',
+            name: 'status',
+            type: 'uint8',
+          },
+        ],
+        internalType: 'struct ValidatorV1.NodeInfo',
+        name: '',
+        type: 'tuple',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'getSNodes',
+    outputs: [
+      {
+        internalType: 'address[]',
+        name: '',
+        type: 'address[]',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'getSNodesLength',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'getVNodes',
+    outputs: [
+      {
+        internalType: 'address[]',
+        name: '',
+        type: 'address[]',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'getVNodesLength',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'uint16',
+        name: 'protocolVersion_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'address',
+        name: 'pushToken_',
+        type: 'address',
+      },
+      {
+        internalType: 'uint16',
+        name: 'valPerBlockTarget_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'nodeRandomMinCount_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'nodeRandomPingCount_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'REPORTS_BEFORE_SLASH_V_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'REPORTS_BEFORE_SLASH_S_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'SLASHES_BEFORE_BAN_V_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'SLASHES_BEFORE_BAN_S_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'SLASH_PERCENT_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'BAN_PERCENT_',
+        type: 'uint16',
+      },
+    ],
+    name: 'initialize',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'minStakeD',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'minStakeS',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'minStakeV',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: '',
+        type: 'address',
+      },
+    ],
+    name: 'nodeMap',
+    outputs: [
+      {
+        internalType: 'address',
+        name: 'ownerWallet',
+        type: 'address',
+      },
+      {
+        internalType: 'address',
+        name: 'nodeWallet',
+        type: 'address',
+      },
+      {
+        internalType: 'enum ValidatorV1.NodeType',
+        name: 'nodeType',
+        type: 'uint8',
+      },
+      {
+        internalType: 'uint256',
+        name: 'nodeTokens',
+        type: 'uint256',
+      },
+      {
+        internalType: 'string',
+        name: 'nodeApiBaseUrl',
+        type: 'string',
+      },
+      {
+        components: [
+          {
+            internalType: 'uint16',
+            name: 'reportCounter',
+            type: 'uint16',
+          },
+          {
+            internalType: 'uint16',
+            name: 'slashCounter',
+            type: 'uint16',
+          },
+          {
+            internalType: 'uint128[]',
+            name: 'reportedInBlocks',
+            type: 'uint128[]',
+          },
+          {
+            internalType: 'address[]',
+            name: 'reportedBy',
+            type: 'address[]',
+          },
+          {
+            internalType: 'uint128[]',
+            name: 'reportedKeys',
+            type: 'uint128[]',
+          },
+        ],
+        internalType: 'struct ValidatorV1.NodeCounters',
+        name: 'counters',
+        type: 'tuple',
+      },
+      {
+        internalType: 'enum ValidatorV1.NodeStatus',
+        name: 'status',
+        type: 'uint8',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'nodeRandomMinCount',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'nodeRandomPingCount',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'owner',
+    outputs: [
+      {
+        internalType: 'address',
+        name: '',
+        type: 'address',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'pendingOwner',
+    outputs: [
+      {
+        internalType: 'address',
+        name: '',
+        type: 'address',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'protocolVersion',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'proxiableUUID',
+    outputs: [
+      {
+        internalType: 'bytes32',
+        name: '',
+        type: 'bytes32',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: 'from_',
+        type: 'address',
+      },
+      {
+        internalType: 'address',
+        name: 'to_',
+        type: 'address',
+      },
+      {
+        internalType: 'uint256',
+        name: 'amount_',
+        type: 'uint256',
+      },
+    ],
+    name: 'redistributeStaked',
+    outputs: [
+      {
+        internalType: 'bool',
+        name: '',
+        type: 'bool',
+      },
+    ],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'uint256',
+        name: 'nodeTokens_',
+        type: 'uint256',
+      },
+      {
+        internalType: 'enum ValidatorV1.NodeType',
+        name: 'nodeType_',
+        type: 'uint8',
+      },
+      {
+        internalType: 'string',
+        name: 'nodeApiBaseUrl_',
+        type: 'string',
+      },
+      {
+        internalType: 'address',
+        name: 'nodeWallet_',
+        type: 'address',
+      },
+    ],
+    name: 'registerNodeAndStake',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'renounceOwnership',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'enum ValidatorV1.NodeType',
+        name: 'targetNodeType_',
+        type: 'uint8',
+      },
+      {
+        internalType: 'bytes',
+        name: 'voteBlob_',
+        type: 'bytes',
+      },
+      {
+        internalType: 'bytes[]',
+        name: 'signatures_',
+        type: 'bytes[]',
+      },
+    ],
+    name: 'reportNode',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: 'addr_',
+        type: 'address',
+      },
+    ],
+    name: 'setStorageContract',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    name: 'snodes',
+    outputs: [
+      {
+        internalType: 'address',
+        name: '',
+        type: 'address',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'storageContract',
+    outputs: [
+      {
+        internalType: 'address',
+        name: '',
+        type: 'address',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'totalFees',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'totalStaked',
+    outputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: 'newOwner',
+        type: 'address',
+      },
+    ],
+    name: 'transferOwnership',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: 'to_',
+        type: 'address',
+      },
+      {
+        internalType: 'uint256',
+        name: 'amount_',
+        type: 'uint256',
+      },
+    ],
+    name: 'unstakeFees',
+    outputs: [
+      {
+        internalType: 'bool',
+        name: '',
+        type: 'bool',
+      },
+    ],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: 'nodeWallet_',
+        type: 'address',
+      },
+    ],
+    name: 'unstakeNode',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'uint16',
+        name: 'valPerBlockTarget_',
+        type: 'uint16',
+      },
+    ],
+    name: 'updateBlockParams',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'uint16',
+        name: 'nodeRandomMinCount_',
+        type: 'uint16',
+      },
+      {
+        internalType: 'uint16',
+        name: 'nodeRandomPingCount_',
+        type: 'uint16',
+      },
+    ],
+    name: 'updateRandomParams',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: 'newImplementation',
+        type: 'address',
+      },
+    ],
+    name: 'upgradeTo',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'address',
+        name: 'newImplementation',
+        type: 'address',
+      },
+      {
+        internalType: 'bytes',
+        name: 'data',
+        type: 'bytes',
+      },
+    ],
+    name: 'upgradeToAndCall',
+    outputs: [],
+    stateMutability: 'payable',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'valPerBlock',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'valPerBlockTarget',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      {
+        internalType: 'uint256',
+        name: '',
+        type: 'uint256',
+      },
+    ],
+    name: 'vnodes',
+    outputs: [
+      {
+        internalType: 'address',
+        name: '',
+        type: 'address',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'vnodesActive',
+    outputs: [
+      {
+        internalType: 'uint16',
+        name: '',
+        type: 'uint16',
+      },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+];
diff --git a/packages/d-node-notif/src/lib/alias/getAliasInfo.ts b/packages/d-node-notif/src/lib/alias/getAliasInfo.ts
index a1636293e..c98c8e37e 100644
--- a/packages/d-node-notif/src/lib/alias/getAliasInfo.ts
+++ b/packages/d-node-notif/src/lib/alias/getAliasInfo.ts
@@ -25,7 +25,7 @@ export const getAliasInfo = async (options: GetAliasInfoOptionsType) => {
   const aliasChainId: number = ALIAS_CHAIN_ID[aliasChain][env];
 
   const _alias = getCAIPWithChainId(alias, aliasChainId, 'Alias');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/alias`;
   const requestUrl = `${apiEndpoint}/${_alias}/channel`;
 
diff --git a/packages/d-node-notif/src/lib/channels/_getSubscribers.ts b/packages/d-node-notif/src/lib/channels/_getSubscribers.ts
index 60a05a764..10cf311ba 100644
--- a/packages/d-node-notif/src/lib/channels/_getSubscribers.ts
+++ b/packages/d-node-notif/src/lib/channels/_getSubscribers.ts
@@ -34,7 +34,7 @@ export const _getSubscribers = async (
 
   const chainId = channelCAIPDetails.networkId;
 
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/channels/_get_subscribers`;
   const requestUrl = `${apiEndpoint}`;
 
diff --git a/packages/d-node-notif/src/lib/channels/getChannel.ts b/packages/d-node-notif/src/lib/channels/getChannel.ts
index cd24d0011..976a10b86 100644
--- a/packages/d-node-notif/src/lib/channels/getChannel.ts
+++ b/packages/d-node-notif/src/lib/channels/getChannel.ts
@@ -17,7 +17,7 @@ export const getChannel = async (options: GetChannelOptionsType) => {
   const { channel, env = Constants.ENV.PROD, raw = true } = options || {};
 
   const _channel = await getCAIPAddress(env, channel, 'Channel');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/channels`;
   const requestUrl = `${apiEndpoint}/${_channel}`;
 
diff --git a/packages/d-node-notif/src/lib/channels/getChannelNotifications.ts b/packages/d-node-notif/src/lib/channels/getChannelNotifications.ts
index b934999d7..9364ea824 100644
--- a/packages/d-node-notif/src/lib/channels/getChannelNotifications.ts
+++ b/packages/d-node-notif/src/lib/channels/getChannelNotifications.ts
@@ -25,7 +25,7 @@ export const getChannelNotifications = async (
   } = options || {};
 
   const _channel = await getCAIPAddress(env, channel, 'Channel');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v2/channels`;
   const query = getQueryParams(
     filter
diff --git a/packages/d-node-notif/src/lib/channels/getChannels.ts b/packages/d-node-notif/src/lib/channels/getChannels.ts
index 0b463a96b..d9411ab64 100644
--- a/packages/d-node-notif/src/lib/channels/getChannels.ts
+++ b/packages/d-node-notif/src/lib/channels/getChannels.ts
@@ -27,7 +27,7 @@ export const getChannels = async (options: getChannelsOptionsType) => {
     order = CONSTANTS.FILTER.CHANNEL_LIST.ORDER.DESCENDING,
   } = options || {};
 
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/channels`;
   const requestUrl = `${apiEndpoint}?page=${page}&limit=${limit}&sort=${sort}&order=${order}`;
 
diff --git a/packages/d-node-notif/src/lib/channels/getDelegates.ts b/packages/d-node-notif/src/lib/channels/getDelegates.ts
index c2a81cbfa..1cf3233e7 100644
--- a/packages/d-node-notif/src/lib/channels/getDelegates.ts
+++ b/packages/d-node-notif/src/lib/channels/getDelegates.ts
@@ -1,34 +1,26 @@
-import {
-  getCAIPAddress,
-  getAPIBaseUrls
-} from '../helpers';
+import { getCAIPAddress, getAPIBaseUrls } from '../helpers';
 import Constants, { ENV } from '../constants';
 import { axiosGet } from '../utils/axiosUtil';
 
 /**
- *  GET v1/channels/${channelAddressInCAIP}/delegates  
+ *  GET v1/channels/${channelAddressInCAIP}/delegates
  */
 
 export type GetDelegatesOptionsType = {
   /** address of the channel */
   channel: string;
   env?: ENV;
-}
+};
 
 /**
  *  Returns the list of addresses that the channel has delegated to
  */
 
-export const getDelegates = async (
-  options : GetDelegatesOptionsType
-) => {
-  const {
-    channel,
-    env = Constants.ENV.PROD,
-  } = options || {};
+export const getDelegates = async (options: GetDelegatesOptionsType) => {
+  const { channel, env = Constants.ENV.PROD } = options || {};
 
   const _channel = await getCAIPAddress(env, channel, 'Channel');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/channels`;
   const requestUrl = `${apiEndpoint}/${_channel}/delegates`;
 
@@ -37,4 +29,4 @@ export const getDelegates = async (
     .catch((err) => {
       console.error(`[EPNS-SDK] - API ${requestUrl}: `, err);
     });
-}
+};
diff --git a/packages/d-node-notif/src/lib/channels/getSubscribers.ts b/packages/d-node-notif/src/lib/channels/getSubscribers.ts
index ee9090f5c..f8836f413 100644
--- a/packages/d-node-notif/src/lib/channels/getSubscribers.ts
+++ b/packages/d-node-notif/src/lib/channels/getSubscribers.ts
@@ -9,66 +9,62 @@ import { parseSubscrbersApiResponse } from '../utils/parseSubscribersAPI';
  */
 
 export type GetChannelSubscribersOptionsType = {
-    channel: string; // plain ETH Format only
-    page?: number,
-    limit?: number,
-    category?: number,
-    setting?: boolean,
-    env?: ENV,
-    raw?: boolean
-}
+  channel: string; // plain ETH Format only
+  page?: number;
+  limit?: number;
+  category?: number;
+  setting?: boolean;
+  env?: ENV;
+  raw?: boolean;
+};
 
 export const getSubscribers = async (
   options: GetChannelSubscribersOptionsType
 ): Promise<Subscribers> => {
-
   try {
-  
     const {
-        channel,
-        page = 1,
-        limit = 10,
-        category = null,
-        setting = false,
-        env = Constants.ENV.PROD,
-        raw = true
+      channel,
+      page = 1,
+      limit = 10,
+      category = null,
+      setting = false,
+      env = Constants.ENV.PROD,
+      raw = true,
     } = options || {};
 
     try {
-        if (channel == null || channel.length == 0) {
-            throw new Error(`channel cannot be null or empty`);
-        }
+      if (channel == null || channel.length == 0) {
+        throw new Error(`channel cannot be null or empty`);
+      }
 
-        if (page <= 0) {
-            throw new Error("page must be greater than 0");
-        }
+      if (page <= 0) {
+        throw new Error('page must be greater than 0');
+      }
 
-        if (limit <= 0) {
-            throw new Error("limit must be greater than 0");
-        }
+      if (limit <= 0) {
+        throw new Error('limit must be greater than 0');
+      }
 
-        if (limit > 30) {
-            throw new Error("limit must be lesser than or equal to 30");
-        }
-        const _channel = await getCAIPAddress(env, channel, 'Channel');
-        const API_BASE_URL = getAPIBaseUrls(env);
-        let apiEndpoint = `${API_BASE_URL}/v1/channels/${_channel}/subscribers?page=${page}&limit=${limit}&setting=${setting}`;
-        if(category){
-            apiEndpoint = apiEndpoint+`&category=${category}`
-        }
-        return await axiosGet(apiEndpoint)
-          .then((response) => {
-            if(raw)
-              return response.data
-            else
-              return parseSubscrbersApiResponse(response.data)
-          })
-          .catch((err) => {
-            console.error(`[Push SDK] - API ${apiEndpoint}: `, err);
-          });
+      if (limit > 30) {
+        throw new Error('limit must be lesser than or equal to 30');
+      }
+      const _channel = await getCAIPAddress(env, channel, 'Channel');
+      const API_BASE_URL = await getAPIBaseUrls(env);
+      let apiEndpoint = `${API_BASE_URL}/v1/channels/${_channel}/subscribers?page=${page}&limit=${limit}&setting=${setting}`;
+      if (category) {
+        apiEndpoint = apiEndpoint + `&category=${category}`;
+      }
+      return await axiosGet(apiEndpoint)
+        .then((response) => {
+          if (raw) return response.data;
+          else return parseSubscrbersApiResponse(response.data);
+        })
+        .catch((err) => {
+          console.error(`[Push SDK] - API ${apiEndpoint}: `, err);
+        });
     } catch (err) {
-        console.error(`[Push SDK] - API  - Error - API send() -:  `, err);
-        throw Error(`[Push SDK] - API  - Error - API send() -: ${err}`);
+      console.error(`[Push SDK] - API  - Error - API send() -:  `, err);
+      throw Error(`[Push SDK] - API  - Error - API send() -: ${err}`);
     }
   } catch (err) {
     console.error(`[Push SDK] - API  - Error - API send() -:  `, err);
diff --git a/packages/d-node-notif/src/lib/channels/search.ts b/packages/d-node-notif/src/lib/channels/search.ts
index 0abe5a628..f001e15fb 100644
--- a/packages/d-node-notif/src/lib/channels/search.ts
+++ b/packages/d-node-notif/src/lib/channels/search.ts
@@ -1,11 +1,11 @@
 import { getAPIBaseUrls, getQueryParams, getLimit } from '../helpers';
-import Constants, {ENV} from '../constants';
+import Constants, { ENV } from '../constants';
 import { axiosGet } from '../utils/axiosUtil';
 
 /**
- *  GET /v1/channels/search/ 
+ *  GET /v1/channels/search/
  *  optional params: page=(1)&limit=(20{min:1}{max:30})&query=(searchquery)
- *  
+ *
  */
 
 export type SearchChannelOptionsType = {
@@ -13,11 +13,9 @@ export type SearchChannelOptionsType = {
   env?: ENV;
   page?: number;
   limit?: number;
-}
+};
 
-export const search = async (
-  options: SearchChannelOptionsType
-) => {
+export const search = async (options: SearchChannelOptionsType) => {
   const {
     query,
     env = Constants.ENV.PROD,
@@ -26,12 +24,12 @@ export const search = async (
   } = options || {};
 
   if (!query) throw Error('"query" not provided!');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/channels/search/`;
   const queryObj = {
     page,
     limit: getLimit(limit),
-    query: query
+    query: query,
   };
   const requestUrl = `${apiEndpoint}?${getQueryParams(queryObj)}`;
   return axiosGet(requestUrl)
@@ -39,4 +37,4 @@ export const search = async (
     .catch((err) => {
       console.error(`[Push SDK] - API ${requestUrl}: `, err);
     });
-}
+};
diff --git a/packages/d-node-notif/src/lib/chat/helpers/service.ts b/packages/d-node-notif/src/lib/chat/helpers/service.ts
index 2ba85e554..baae8fd3e 100644
--- a/packages/d-node-notif/src/lib/chat/helpers/service.ts
+++ b/packages/d-node-notif/src/lib/chat/helpers/service.ts
@@ -35,7 +35,7 @@ export const createUserService = async (options: CreateUserOptionsType) => {
   } = options || {};
   let { user } = options || {};
 
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
 
   const requestUrl = `${API_BASE_URL}/v2/users/`;
 
@@ -88,7 +88,7 @@ export const authUpdateUserService = async (options: CreateUserOptionsType) => {
     env = Constants.ENV.PROD,
   } = options || {};
 
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
 
   const requestUrl = `${API_BASE_URL}/v2/users/${walletToPCAIP10(user)}/auth`;
 
diff --git a/packages/d-node-notif/src/lib/config.ts b/packages/d-node-notif/src/lib/config.ts
index 2fe58b612..fe88edc0d 100644
--- a/packages/d-node-notif/src/lib/config.ts
+++ b/packages/d-node-notif/src/lib/config.ts
@@ -2,6 +2,7 @@ import { ENV } from './constants';
 import { coreABI } from './abis/core';
 import { commABI } from './abis/comm';
 import { tokenABI } from './abis/token';
+import { validatorABI } from './abis/validator';
 import {
   mainnet,
   polygon,
@@ -20,6 +21,7 @@ import {
   polygonZkEvmCardona,
   cyberTestnet,
   cyber,
+  localhost,
 } from 'viem/chains';
 
 // for methods not needing the entire config
@@ -30,7 +32,7 @@ export const API_BASE_URL = {
   /**
    * **This is for local development only**
    */
-  [ENV.LOCAL]: 'http://localhost:4000/apis',
+  [ENV.LOCAL]: 'http://localhost:4001/apis',
 };
 
 const BLOCKCHAIN_NETWORK = {
@@ -69,6 +71,7 @@ export const ETH_CHAIN_ID = {
   [ENV.DEV]: 11155111,
   [ENV.LOCAL]: 11155111,
 };
+
 export const ALIAS_CHAIN_ID: {
   [key: string]: { [key in ENV]: number };
 } = {
@@ -197,7 +200,7 @@ export const CORE_CONFIG = {
     EPNS_CORE_CONTRACT: '0x5ab1520e2bd519bdab2e1347eee81c00a77f4946',
   },
   [ENV.LOCAL]: {
-    API_BASE_URL: API_BASE_URL[ENV.DEV],
+    API_BASE_URL: API_BASE_URL[ENV.LOCAL],
     EPNS_CORE_CONTRACT: '0x5ab1520e2bd519bdab2e1347eee81c00a77f4946',
   },
 };
@@ -347,13 +350,14 @@ const CONFIG = {
       EPNS_COMMUNICATOR_CONTRACT: '0xA1DF3E68D085aa6918bcc2506b24e499830Db0eB',
     },
     [BLOCKCHAIN_NETWORK.CYBER_CONNECT_TESTNET]: {
-      API_BASE_URL: API_BASE_URL[ENV.DEV],
+      API_BASE_URL: API_BASE_URL[ENV.LOCAL],
       EPNS_COMMUNICATOR_CONTRACT: '0x9cb3bd7550B5c92baA056Fc0F08132f49508145F',
     },
   },
 };
 
 export default CONFIG;
+
 export const TOKEN = {
   [ENV.PROD]: '0xf418588522d5dd018b425E472991E52EBBeEEEEE',
   [ENV.STAGING]: '0x37c779a1564DCc0e3914aB130e0e787d93e21804',
@@ -374,10 +378,12 @@ export const MIN_TOKEN_BALANCE = {
   [ENV.DEV]: 50,
   [ENV.LOCAL]: 50,
 };
+
 export const ABIS = {
   CORE: coreABI,
   COMM: commABI,
   TOKEN: tokenABI,
+  VALIDATOR: validatorABI,
 };
 
 export const CHANNEL_TYPE = {
@@ -525,27 +531,27 @@ export const VIEM_CONFIG = {
   [ENV.LOCAL]: {
     [BLOCKCHAIN_NETWORK.ETH_SEPOLIA]: {
       NETWORK: sepolia,
-      API_BASE_URL: API_BASE_URL[ENV.DEV],
+      API_BASE_URL: API_BASE_URL[ENV.LOCAL],
       EPNS_COMMUNICATOR_CONTRACT: '0x9dDCD7ed7151afab43044E4D694FA064742C428c',
     },
     [BLOCKCHAIN_NETWORK.POLYGON_AMOY]: {
       NETWORK: polygonAmoy,
-      API_BASE_URL: API_BASE_URL[ENV.DEV],
+      API_BASE_URL: API_BASE_URL[ENV.LOCAL],
       EPNS_COMMUNICATOR_CONTRACT: '0x9cb3bd7550b5c92baa056fc0f08132f49508145f',
     },
     [BLOCKCHAIN_NETWORK.BSC_TESTNET]: {
       NETWORK: bscTestnet,
-      API_BASE_URL: API_BASE_URL[ENV.DEV],
+      API_BASE_URL: API_BASE_URL[ENV.LOCAL],
       EPNS_COMMUNICATOR_CONTRACT: '0x4132061E3349ff36cFfCadA460E10Bd4f31F7ea8',
     },
     [BLOCKCHAIN_NETWORK.OPTIMISM_TESTNET]: {
       NETWORK: optimismSepolia,
-      API_BASE_URL: API_BASE_URL[ENV.DEV],
+      API_BASE_URL: API_BASE_URL[ENV.LOCAL],
       EPNS_COMMUNICATOR_CONTRACT: '0x754787358fac861ef904c92d54f7adb659779317',
     },
     [BLOCKCHAIN_NETWORK.POLYGON_ZK_EVM_TESTNET]: {
       NETWORK: polygonZkEvmCardona,
-      API_BASE_URL: API_BASE_URL[ENV.DEV],
+      API_BASE_URL: API_BASE_URL[ENV.LOCAL],
       EPNS_COMMUNICATOR_CONTRACT: '0x9cb3bd7550b5c92baa056fc0f08132f49508145f',
     },
     [BLOCKCHAIN_NETWORK.ARBITRUM_TESTNET]: {
@@ -565,7 +571,7 @@ export const VIEM_CONFIG = {
     },
     [BLOCKCHAIN_NETWORK.CYBER_CONNECT_TESTNET]: {
       NETWORK: cyberTestnet,
-      API_BASE_URL: API_BASE_URL[ENV.STAGING],
+      API_BASE_URL: API_BASE_URL[ENV.LOCAL],
       EPNS_COMMUNICATOR_CONTRACT: '0x9cb3bd7550B5c92baA056Fc0F08132f49508145F',
     },
   },
@@ -579,3 +585,22 @@ export const ALPHA_FEATURE_CONFIG = {
     feature: [] as string[],
   },
 };
+
+export const VALIDATOR_CONFIG = {
+  [ENV.PROD]: {
+    NETWORK: mainnet,
+    VALIDATOR_CONTRACT: 'TODO',
+  },
+  [ENV.STAGING]: {
+    NETWORK: sepolia,
+    VALIDATOR_CONTRACT: 'TODO',
+  },
+  [ENV.DEV]: {
+    NETWORK: sepolia,
+    VALIDATOR_CONTRACT: 'TODO',
+  },
+  [ENV.LOCAL]: {
+    NETWORK: localhost,
+    VALIDATOR_CONTRACT: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9',
+  },
+};
diff --git a/packages/d-node-notif/src/lib/helpers/config.ts b/packages/d-node-notif/src/lib/helpers/config.ts
index 3a48744dc..29812a4ed 100644
--- a/packages/d-node-notif/src/lib/helpers/config.ts
+++ b/packages/d-node-notif/src/lib/helpers/config.ts
@@ -1,21 +1,21 @@
 import CONFIG, { API_BASE_URL, ConfigType } from '../config';
-import {ENV} from '../constants';
+import { ENV } from '../constants';
+import { PushValidator } from '../pushValidator/pushValidator';
 
 /**
  * This config helper returns the API url as well as the
  * EPNS communicator contract method address
  */
 export const getConfig = (
-  env:  ENV,
+  env: ENV,
   {
     blockchain,
-    networkId
+    networkId,
   }: {
-    blockchain: string,
-    networkId: string
+    blockchain: string;
+    networkId: string;
   }
 ): ConfigType => {
-
   const blockchainSelector = `${blockchain}:${networkId}`;
   const configuration = CONFIG[env][blockchainSelector];
 
@@ -25,17 +25,17 @@ export const getConfig = (
         env: ${env},
         blockchain: ${blockchain},
         networkId: ${networkId}
-    `)
+    `);
   }
 
   return configuration;
 };
 
-
 /**
  * This config helper returns only the API urls
  */
-export function getAPIBaseUrls(env:  ENV) {
+export async function getAPIBaseUrls(env: ENV) {
   if (!env) throw Error('ENV not provided!');
-  return API_BASE_URL[env];
-}
\ No newline at end of file
+  const pushValidator = await PushValidator.initalize({ env });
+  return `${pushValidator.activeValidatorURL}/apis`;
+}
diff --git a/packages/d-node-notif/src/lib/helpers/crypto.ts b/packages/d-node-notif/src/lib/helpers/crypto.ts
index f71c071db..d21be8ddb 100644
--- a/packages/d-node-notif/src/lib/helpers/crypto.ts
+++ b/packages/d-node-notif/src/lib/helpers/crypto.ts
@@ -583,3 +583,11 @@ export const validatePssword = (password: string) => {
     throw new Error('Password must contain at least one special character!');
   }
 };
+
+export const getRandomElement = <T>(array: T[]): T => {
+  if (array.length === 0) {
+    throw new Error('Array is empty');
+  }
+  const randomIndex = Math.floor(Math.random() * array.length);
+  return array[randomIndex];
+};
diff --git a/packages/d-node-notif/src/lib/payloads/sendNotifications.ts b/packages/d-node-notif/src/lib/payloads/sendNotifications.ts
index ea02b3c12..36b68c035 100644
--- a/packages/d-node-notif/src/lib/payloads/sendNotifications.ts
+++ b/packages/d-node-notif/src/lib/payloads/sendNotifications.ts
@@ -155,7 +155,7 @@ export async function sendNotification(options: ISendNotificationInputOptions) {
     const uuid = getUUID();
     const chainId = parseInt(channelCAIPDetails.networkId, 10);
 
-    const API_BASE_URL = getAPIBaseUrls(env);
+    const API_BASE_URL = await getAPIBaseUrls(env);
     let COMMUNICATOR_CONTRACT = '';
     if (senderType === 0) {
       const { EPNS_COMMUNICATOR_CONTRACT } = getConfig(env, channelCAIPDetails);
diff --git a/packages/d-node-notif/src/lib/pushNotification/pushNotificationBase.ts b/packages/d-node-notif/src/lib/pushNotification/pushNotificationBase.ts
index 9953abbde..78a15374f 100644
--- a/packages/d-node-notif/src/lib/pushNotification/pushNotificationBase.ts
+++ b/packages/d-node-notif/src/lib/pushNotification/pushNotificationBase.ts
@@ -917,7 +917,7 @@ export class PushNotificationBaseClass {
    * @returns Channel info for the alias
    */
   private async getAliasInfo(aliasInCaip: string) {
-    const API_BASE_URL = getAPIBaseUrls(this.env!);
+    const API_BASE_URL = await getAPIBaseUrls(this.env!);
     const apiEndpoint = `${API_BASE_URL}/v1/alias`;
     const requestUrl = `${apiEndpoint}/${aliasInCaip}/channel`;
 
diff --git a/packages/d-node-notif/src/lib/pushValidator/pushValidator.ts b/packages/d-node-notif/src/lib/pushValidator/pushValidator.ts
new file mode 100644
index 000000000..4f517aa96
--- /dev/null
+++ b/packages/d-node-notif/src/lib/pushValidator/pushValidator.ts
@@ -0,0 +1,144 @@
+import axios from 'axios';
+import { getRandomElement } from '../helpers';
+import {
+  ActiveValidator,
+  PingReply,
+  TokenReply,
+  ValidatorContract,
+} from './pushValidatorTypes';
+import { axiosGet } from '../utils/axiosUtil';
+import { createPublicClient, getContract, http } from 'viem';
+import * as config from '../config';
+import { ENV } from '../constants';
+
+/**
+ * @description Push validator class is used for the following:
+ * - Interact with validator.sol ( Only Read calls )
+ * - Get token to interact with a random validator node
+ * - Ping a random validator node to check if it is alive
+ */
+export class PushValidator {
+  private static instance: PushValidator;
+  private validatorContractClient: ValidatorContract;
+  /**
+   * @dev - active validator URL ( Used for Get calls to a validator node )
+   */
+  public activeValidatorURL: string;
+  public env: ENV;
+
+  private constructor(
+    activeValidatorURL: string,
+    env: ENV,
+    validatorContractClient: ValidatorContract
+  ) {
+    this.activeValidatorURL = activeValidatorURL;
+    this.env = env;
+    this.validatorContractClient = validatorContractClient;
+  }
+
+  static initalize = async (options?: { env: ENV }): Promise<PushValidator> => {
+    const settings = options || { env: ENV.STAGING };
+
+    /**
+     * @dev - If instance is not created or env is different, create a new instance
+     */
+    if (
+      !PushValidator.instance ||
+      PushValidator.instance.env !== settings.env
+    ) {
+      const validatorContractClient =
+        PushValidator.createValidatorContractClient(settings.env);
+      const activeValidator = await PushValidator.getActiveValidator(
+        validatorContractClient
+      );
+      PushValidator.instance = new PushValidator(
+        activeValidator.nodeApiBaseUrl,
+        settings.env,
+        validatorContractClient
+      );
+    }
+    return PushValidator.instance;
+  };
+
+  /**
+   * @description Get validator node token
+   * @returns Token reply object with API token and validator URL
+   */
+  getToken = async (): Promise<TokenReply | null> => {
+    const activeValidator = await PushValidator.getActiveValidator(
+      this.validatorContractClient
+    );
+    const requestUrl = `${activeValidator.nodeApiBaseUrl}/apis/v1/messaging/validatorToken`;
+    return await axiosGet(requestUrl)
+      .then((response) => {
+        if (response.status != 200) {
+          throw new Error(
+            `error status: ${response.status} data: ${response.data}`
+          );
+        }
+        return response.data;
+      })
+      .catch((err) => {
+        console.error(`[Push SDK] - API ${requestUrl}: `, err);
+        return null;
+      });
+  };
+
+  /**
+   * @description Ping validator
+   * @param validatorUrl - Validator URL to ping (default is active validator URL)
+   * @returns Ping reply object
+   */
+  ping = async (
+    validatorUrl: string = this.activeValidatorURL
+  ): Promise<PingReply | null> => {
+    const requestUrl = `${validatorUrl}/apis/v1/messaging/ping`;
+    return await axiosGet(requestUrl)
+      .then((response) => {
+        if (response.status != 200) {
+          throw new Error(
+            `error status: ${response.status} data: ${response.data}`
+          );
+        }
+        return response.data;
+      })
+      .catch((err) => {
+        console.error(`[Push SDK] - API ${requestUrl}: `, err);
+        return null;
+      });
+  };
+
+  /**
+   * @description Get active validator
+   * @returns Active validator object
+   */
+  private static getActiveValidator = async (
+    validatorContractClient: ValidatorContract
+  ): Promise<ActiveValidator> => {
+    const activeValidators =
+      await validatorContractClient.read.getActiveVNodes();
+    return getRandomElement(activeValidators);
+  };
+
+  /**
+   * @description Create validator contract client
+   * @param env - Environment
+   * @dev - Currently only supports public client
+   * @returns Validator contract client
+   */
+  private static createValidatorContractClient = (
+    env: ENV
+  ): ValidatorContract => {
+    const client = createPublicClient({
+      chain: config.VALIDATOR_CONFIG[env].NETWORK,
+      transport: http(),
+    });
+    return getContract({
+      abi: config.ABIS.VALIDATOR,
+      address: config.VALIDATOR_CONFIG[env].VALIDATOR_CONTRACT as `0x${string}`,
+      client: {
+        public: client,
+      },
+    }) as any;
+  };
+}
diff --git a/packages/d-node-notif/src/lib/pushValidator/pushValidatorTypes.ts b/packages/d-node-notif/src/lib/pushValidator/pushValidatorTypes.ts
new file mode 100644
index 000000000..3cf10ebe8
--- /dev/null
+++ b/packages/d-node-notif/src/lib/pushValidator/pushValidatorTypes.ts
@@ -0,0 +1,44 @@
+export type TokenReply = { validatorToken: string; validatorUrl: string };
+
+export type PingReply = {
+  nodeId: string;
+  tsMillis: number;
+  status: string;
+};
+
+export type ActiveValidator = {
+  nodeWallet: string;
+  nodeApiBaseUrl: string;
+};
+
+/**
+ * @description Validator contract interface ( VIEM CLIENT )
+ */
+export type ValidatorContract = {
+  read: {
+    getActiveVNodes(): Promise<ActiveValidator[]>;
+    nodeMap(address: string): Promise<NodeInfo>;
+  };
+};
+
+type NodeInfo = {
+  ownerWallet: string;
+  nodeWallet: string;
+  nodeType: NodeType;
+  nodeApiBaseUrl: string;
+  status: NodeStatus;
+};
+
+enum NodeType {
+  VNode = 0, // validator 0
+  SNode = 1, // storage 1
+  DNode = 2, // delivery 2
+}
+
+enum NodeStatus {
+  OK,
+  Reported,
+  Slashed,
+  BannedAndUnstaked,
+  Unstaked,
+}
diff --git a/packages/d-node-notif/src/lib/user/getDelegations.ts b/packages/d-node-notif/src/lib/user/getDelegations.ts
index fe7fc175a..3497cc10a 100644
--- a/packages/d-node-notif/src/lib/user/getDelegations.ts
+++ b/packages/d-node-notif/src/lib/user/getDelegations.ts
@@ -1,7 +1,4 @@
-import {
-  getCAIPAddress,
-  getAPIBaseUrls
-} from '../helpers';
+import { getCAIPAddress, getAPIBaseUrls } from '../helpers';
 import Constants, { ENV } from '../constants';
 import { axiosGet } from '../utils/axiosUtil';
 
@@ -13,22 +10,17 @@ export type UserDelegationsOptionsType = {
   /** wallet address of user */
   user: string;
   env?: ENV;
-}
+};
 
 /**
  *  Returns the list of channels that the user has been delegated to
  */
 
-export const getDelegations = async (
-  options : UserDelegationsOptionsType
-) => {
-  const {
-    user,
-    env = Constants.ENV.PROD,
-  } = options || {};
+export const getDelegations = async (options: UserDelegationsOptionsType) => {
+  const { user, env = Constants.ENV.PROD } = options || {};
 
   const _user = await getCAIPAddress(env, user, 'User');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/users/${_user}/delegations`;
   const requestUrl = `${apiEndpoint}`;
 
@@ -37,4 +29,4 @@ export const getDelegations = async (
     .catch((err) => {
       console.error(`[EPNS-SDK] - API ${requestUrl}: `, err);
     });
-}
+};
diff --git a/packages/d-node-notif/src/lib/user/getFeeds.ts b/packages/d-node-notif/src/lib/user/getFeeds.ts
index 4317838f8..6594499bf 100644
--- a/packages/d-node-notif/src/lib/user/getFeeds.ts
+++ b/packages/d-node-notif/src/lib/user/getFeeds.ts
@@ -4,7 +4,7 @@ import {
   getQueryParams,
   getLimit,
 } from '../helpers';
-import Constants, {ENV} from '../constants';
+import Constants, { ENV } from '../constants';
 import { parseApiResponse } from '../utils';
 import { axiosGet } from '../utils/axiosUtil';
 
@@ -15,11 +15,9 @@ export type FeedsOptionsType = {
   limit?: number;
   spam?: boolean;
   raw?: boolean;
-}
+};
 
-export const getFeeds = async (
-  options: FeedsOptionsType
-) => {
+export const getFeeds = async (options: FeedsOptionsType) => {
   const {
     user,
     env = Constants.ENV.PROD,
@@ -30,13 +28,13 @@ export const getFeeds = async (
   } = options || {};
 
   const _user = await getCAIPAddress(env, user, 'User');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/users/${_user}/feeds`;
 
   const queryObj = {
     page,
     limit: getLimit(limit),
-    spam
+    spam,
   };
 
   const requestUrl = `${apiEndpoint}?${getQueryParams(queryObj)}`;
@@ -50,4 +48,4 @@ export const getFeeds = async (
     .catch((err) => {
       console.error(`[Push SDK] - API ${requestUrl}: `, err);
     });
-}
+};
diff --git a/packages/d-node-notif/src/lib/user/getFeedsPerChannel.ts b/packages/d-node-notif/src/lib/user/getFeedsPerChannel.ts
index a82dcc3e2..e0c0a3bb1 100644
--- a/packages/d-node-notif/src/lib/user/getFeedsPerChannel.ts
+++ b/packages/d-node-notif/src/lib/user/getFeedsPerChannel.ts
@@ -32,7 +32,7 @@ export const getFeedsPerChannel = async (
   } = options || {};
 
   const _user = await getCAIPAddress(env, user, 'User');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   if (channels.length == 0) {
     throw new Error('channels cannot be empty');
   }
diff --git a/packages/d-node-notif/src/lib/user/getSubscriptions.ts b/packages/d-node-notif/src/lib/user/getSubscriptions.ts
index d67d2f994..ed88d38c2 100644
--- a/packages/d-node-notif/src/lib/user/getSubscriptions.ts
+++ b/packages/d-node-notif/src/lib/user/getSubscriptions.ts
@@ -21,14 +21,15 @@ export const getSubscriptions = async (
   } = options || {};
 
   const _user = await getCAIPAddress(env, user, 'User');
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const apiEndpoint = `${API_BASE_URL}/v1/users/${_user}/subscriptions`;
-  const query = channel? getQueryParams({
-    channel: channel
-  }): ""
+  const query = channel
+    ? getQueryParams({
+        channel: channel,
+      })
+    : '';
   const requestUrl = `${apiEndpoint}?${query}`;
 
- 
   return axiosGet(requestUrl)
     .then((response) => {
       if (raw) {
diff --git a/packages/d-node-notif/src/lib/user/getUser.ts b/packages/d-node-notif/src/lib/user/getUser.ts
index ee67b568b..aefb69cfe 100644
--- a/packages/d-node-notif/src/lib/user/getUser.ts
+++ b/packages/d-node-notif/src/lib/user/getUser.ts
@@ -11,7 +11,7 @@ export const get = async (options: AccountEnvOptionsType): Promise<IUser> => {
     throw new Error(`Invalid address!`);
   }
   const caip10 = walletToPCAIP10(account);
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const requestUrl = `${API_BASE_URL}/v2/users/?caip10=${caip10}`;
   return axiosGet(requestUrl)
     .then(async (response) => {
diff --git a/packages/d-node-notif/src/lib/user/getUsersBatch.ts b/packages/d-node-notif/src/lib/user/getUsersBatch.ts
index 03b3b05a0..74e7845d0 100644
--- a/packages/d-node-notif/src/lib/user/getUsersBatch.ts
+++ b/packages/d-node-notif/src/lib/user/getUsersBatch.ts
@@ -13,7 +13,7 @@ export interface GetBatchType {
 export const getBatch = async (options: GetBatchType): Promise<IUser> => {
   const { env = Constants.ENV.PROD, userIds } = options || {};
 
-  const API_BASE_URL = getAPIBaseUrls(env);
+  const API_BASE_URL = await getAPIBaseUrls(env);
   const requestUrl = `${API_BASE_URL}/v2/users/batch`;
 
   const MAX_USER_IDS_LENGTH = 100;
diff --git a/packages/d-node-notif/src/lib/user/profile.updateUser.ts b/packages/d-node-notif/src/lib/user/profile.updateUser.ts
index e33d76bad..31d1fdbf3 100644
--- a/packages/d-node-notif/src/lib/user/profile.updateUser.ts
+++ b/packages/d-node-notif/src/lib/user/profile.updateUser.ts
@@ -102,7 +102,7 @@ export const profileUpdateCore = async (
 
     const body = { ...updatedProfile, verificationProof };
 
-    const API_BASE_URL = getAPIBaseUrls(env);
+    const API_BASE_URL = await getAPIBaseUrls(env);
     const apiEndpoint = `${API_BASE_URL}/v2/users/${user.did}/profile`;
 
     // Report Progress
diff --git a/packages/d-node-notif/tests/.env.sample b/packages/d-node-notif/tests/.env.sample
index 1111df0ea..5beb47713 100644
--- a/packages/d-node-notif/tests/.env.sample
+++ b/packages/d-node-notif/tests/.env.sample
@@ -1,6 +1,6 @@
 # MAKE A COPY OF THIS AND FILL WITH YOUR CREDENTIALS AND NAME IT .env (Remove .sample Part)
 
-# ENVIRONMENT | 'STAGING' or 'PROD' or 'DEV'
+# ENVIRONMENT | 'STAGING' or 'PROD' or 'DEV' or 'LOCAL'
 ENV=env_name
 
 ## CHANNEL WITH ALIAS
diff --git a/packages/d-node-notif/tests/lib/initialize/initialize.test.ts b/packages/d-node-notif/tests/lib/initialize/initialize.test.ts
new file mode 100644
index 000000000..fe6f12c06
--- /dev/null
+++ b/packages/d-node-notif/tests/lib/initialize/initialize.test.ts
@@ -0,0 +1,22 @@
+import { PushAPI } from '../../../src/lib/pushAPI/PushAPI';
+import { expect } from 'chai';
+import { ethers } from 'ethers';
+import { ENV } from '../../../src/lib/constants';
+
+describe('PushAPI.channel functionality', () => {
+  // accessing env dynamically using process.env
+  const envMode = process.env.ENV as keyof typeof ENV;
+  const env = ENV[envMode];
+
+  let signer: ethers.Wallet;
+
+  beforeEach(async () => {
+    signer = ethers.Wallet.createRandom();
+  });
+
+  it('Initialize user with validator node', async () => {
+    await PushAPI.initialize(signer, {
+      env,
+    });
+  });
+});
diff --git a/packages/d-node-notif/tests/lib/pushValidator/pushValidator.test.ts b/packages/d-node-notif/tests/lib/pushValidator/pushValidator.test.ts
new file mode 100644
index 000000000..a7c4cd894
--- /dev/null
+++ b/packages/d-node-notif/tests/lib/pushValidator/pushValidator.test.ts
@@ -0,0 +1,57 @@
+import { PushValidator } from '../../../src/lib/pushValidator/pushValidator';
+import { expect } from 'chai';
+import { ethers } from 'ethers';
+import { ENV } from '../../../src/lib/constants';
+import { ActiveValidator } from '../../../src/lib/pushValidator/pushValidatorTypes';
+
+describe.only('PushValidator Class', () => {
+  // accessing env dynamically using process.env
+  const envMode = process.env.ENV as keyof typeof ENV;
+  const env = ENV[envMode];
+
+  it('Initialize PushValidator', async () => {
+    const validatorInstance = await PushValidator.initalize({ env });
+    expect(validatorInstance.env).to.equal(env);
+
+    /**
+     * @dev - TS is a funny language, add `any` and access private properties
+     */
+    const activeValidators = (
+      (await (
+        validatorInstance as any
+      ).validatorContractClient.read.getActiveVNodes()) as []
+    ).map((each) => {
+      return (each as any).nodeApiBaseUrl;
+    });
+
+    expect(validatorInstance.activeValidatorURL).to.be.oneOf(activeValidators);
+  });
+  it('Ping every active validator node', async () => {
+    const validatorInstance = await PushValidator.initalize({ env });
+
+    const activeValidators: ActiveValidator[] = await (
+      validatorInstance as any
+    ).validatorContractClient.read.getActiveVNodes();
+
+    for (const each of activeValidators) {
+      const pingReply = await validatorInstance.ping(each.nodeApiBaseUrl);
+      expect(pingReply).to.not.be.null;
+      expect(pingReply?.nodeId).to.equal(each.nodeWallet);
+      expect(pingReply?.status).to.equal(1);
+    }
+  });
+  it('Ping active read validator node', async () => {
+    const validatorInstance = await PushValidator.initalize({ env });
+    // default active read validator
+    const pingReply = await validatorInstance.ping();
+    expect(pingReply).to.not.be.null;
+    expect(pingReply?.status).to.equal(1);
+  });
+  it('Get token from random active validator node', async () => {
+    const validatorInstance = await PushValidator.initalize({ env });
+    const token = await validatorInstance.getToken();
+    expect(token).to.not.be.null;
+    expect(token?.validatorToken).to.be.string;
+    expect(token?.validatorUrl).to.be.string;
+  });
+});