diff --git a/packages/grid_client/scripts/add_worker.ts b/packages/grid_client/scripts/add_worker.ts
index 450b43a549..4eaaac06c2 100644
--- a/packages/grid_client/scripts/add_worker.ts
+++ b/packages/grid_client/scripts/add_worker.ts
@@ -26,7 +26,8 @@ async function deleteWorker(client, worker) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "testk8s";
+  const grid3 = await getClient(`kubernetes/${name}`);
 
   const workerQueryOptions: FilterOptions = {
     cru: 2,
@@ -36,7 +37,7 @@ async function main() {
   };
 
   const worker: AddWorkerModel = {
-    deployment_name: "testk8s",
+    deployment_name: name,
     name: "worker2",
     node_id: +(await grid3.capacity.filterNodes(workerQueryOptions))[0].nodeId,
     cpu: 2,
@@ -53,10 +54,10 @@ async function main() {
   await addWorker(grid3, worker);
 
   //Get worker information
-  await getWorker(grid3, worker.deployment_name);
+  await getWorker(grid3, name);
 
   //Uncomment the line below to delete the worker
-  // await deleteWorker(grid3, { name: worker.name, deployment_name: worker.deployment_name });
+  // await deleteWorker(grid3, { name: worker.name, deployment_name: name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/caprover_leader.ts b/packages/grid_client/scripts/caprover_leader.ts
index b7e645c543..1456b365ce 100644
--- a/packages/grid_client/scripts/caprover_leader.ts
+++ b/packages/grid_client/scripts/caprover_leader.ts
@@ -25,7 +25,8 @@ async function cancel(client, vms) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "newVMS5";
+  const grid3 = await getClient(`caprover/${name}`);
 
   const vmQueryOptions: FilterOptions = {
     cru: 4,
@@ -35,7 +36,7 @@ async function main() {
   };
 
   const vms: MachinesModel = {
-    name: "newVMS5",
+    name,
     network: {
       name: "wedtest",
       ip_range: "10.249.0.0/16",
@@ -77,10 +78,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: vms.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/caprover_worker.ts b/packages/grid_client/scripts/caprover_worker.ts
index feb89fc058..23b53149ca 100644
--- a/packages/grid_client/scripts/caprover_worker.ts
+++ b/packages/grid_client/scripts/caprover_worker.ts
@@ -24,7 +24,8 @@ async function cancel(client, vms) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "newVMS5";
+  const grid3 = await getClient(`caprover/${name}`);
 
   const vmQueryOptions: FilterOptions = {
     cru: 4,
@@ -34,7 +35,7 @@ async function main() {
   };
 
   const vms: MachinesModel = {
-    name: "newVMS6",
+    name,
     network: {
       name: "wedtest",
       ip_range: "10.249.0.0/16",
@@ -76,10 +77,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: vms.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/client_loader.ts b/packages/grid_client/scripts/client_loader.ts
index 3df59daf83..ca9a263951 100644
--- a/packages/grid_client/scripts/client_loader.ts
+++ b/packages/grid_client/scripts/client_loader.ts
@@ -23,11 +23,12 @@ if (network === undefined || mnemonic === undefined || ssh_key === undefined) {
   };
 }
 
-async function getClient(): Promise<GridClient> {
+async function getClient(projectName = ""): Promise<GridClient> {
   const gridClient = new GridClient({
     network: config.network,
     mnemonic: config.mnemonic,
     storeSecret: config.storeSecret,
+    projectName,
   });
   await gridClient.connect();
   return gridClient;
diff --git a/packages/grid_client/scripts/dynamic_single_vm.ts b/packages/grid_client/scripts/dynamic_single_vm.ts
index de548114f8..b9d0afb2ea 100644
--- a/packages/grid_client/scripts/dynamic_single_vm.ts
+++ b/packages/grid_client/scripts/dynamic_single_vm.ts
@@ -24,7 +24,8 @@ async function cancel(client, vms) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "dynamicVMS";
+  const grid3 = await getClient(`vm/${name}`);
 
   const vmQueryOptions: FilterOptions = {
     cru: 1,
@@ -35,7 +36,7 @@ async function main() {
   };
 
   const vms: MachinesModel = {
-    name: "dynamicVMS",
+    name,
     network: {
       name: "dynamictest",
       ip_range: "10.249.0.0/16",
@@ -73,10 +74,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: vms.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/kubernetes.ts b/packages/grid_client/scripts/kubernetes.ts
index 91700fc2e1..3e09595079 100644
--- a/packages/grid_client/scripts/kubernetes.ts
+++ b/packages/grid_client/scripts/kubernetes.ts
@@ -24,7 +24,8 @@ async function cancel(client, k8s) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "testk8s";
+  const grid3 = await getClient(`kubernetes/${name}`);
 
   const masterQueryOptions: FilterOptions = {
     cru: 2,
@@ -43,7 +44,7 @@ async function main() {
   };
 
   const k: K8SModel = {
-    name: "testk8s",
+    name,
     secret: "secret",
     network: {
       name: "monNetwork",
@@ -87,10 +88,10 @@ async function main() {
   await deploy(grid3, k);
 
   //Get the deployment
-  await getDeployment(grid3, k.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: k.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/kubernetes_mycelium.ts b/packages/grid_client/scripts/kubernetes_mycelium.ts
index 8b285e6e14..e927979964 100644
--- a/packages/grid_client/scripts/kubernetes_mycelium.ts
+++ b/packages/grid_client/scripts/kubernetes_mycelium.ts
@@ -24,10 +24,11 @@ async function cancel(client, k8s) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "testk8sMy";
+  const grid3 = await getClient(`kubernetes/${name}`);
 
   const k: K8SModel = {
-    name: "testk8sMy",
+    name,
     secret: "secret",
     network: {
       name: "monNetwork",
@@ -100,10 +101,10 @@ async function main() {
   await deploy(grid3, k);
 
   //Get the deployment
-  await getDeployment(grid3, k.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: k.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/kubernetes_with_qsfs.ts b/packages/grid_client/scripts/kubernetes_with_qsfs.ts
index 0fcbb06633..e55b24ce4d 100644
--- a/packages/grid_client/scripts/kubernetes_with_qsfs.ts
+++ b/packages/grid_client/scripts/kubernetes_with_qsfs.ts
@@ -38,7 +38,8 @@ async function deleteQsfs(client, qsfs) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "testk8sqsfs";
+  const grid3 = await getClient(`kubernetes/${name}`);
 
   const qsfs_name = "testQsfsK8sq1";
 
@@ -64,7 +65,7 @@ async function main() {
     farmId: 1,
   };
 
-  const qsfsNodes = [];
+  const qsfsNodes: number[] = [];
 
   const allNodes = await grid3.capacity.filterNodes(qsfsQueryOptions);
   if (allNodes.length >= 2) {
@@ -85,7 +86,7 @@ async function main() {
   };
 
   const k: K8SModel = {
-    name: "testk8sqsfs",
+    name,
     secret: "secret",
     network: {
       name: "k8sqsfsNetwork",
@@ -143,7 +144,7 @@ async function main() {
   await deploy(grid3, k);
 
   //Get the deployment
-  await getDeployment(grid3, k.name);
+  await getDeployment(grid3, name);
 
   // //Uncomment the line below to cancel the deployment
   // await cancel(grid3, { name: k.name });
diff --git a/packages/grid_client/scripts/multiple_vms.ts b/packages/grid_client/scripts/multiple_vms.ts
index 8ea6f7d647..9ba3a443e6 100644
--- a/packages/grid_client/scripts/multiple_vms.ts
+++ b/packages/grid_client/scripts/multiple_vms.ts
@@ -24,7 +24,8 @@ async function cancel(client, vms) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "monVMS2";
+  const grid3 = await getClient(`vm/${name}`);
 
   const vmQueryOptions: FilterOptions = {
     cru: 1,
@@ -35,7 +36,7 @@ async function main() {
   };
 
   const vms: MachinesModel = {
-    name: "monVMS2",
+    name,
     network: {
       name: "monNetwork",
       ip_range: "10.238.0.0/16",
@@ -96,10 +97,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   // //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: vms.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/single_vm.ts b/packages/grid_client/scripts/single_vm.ts
index 6364c752e7..a64ac5a9e4 100644
--- a/packages/grid_client/scripts/single_vm.ts
+++ b/packages/grid_client/scripts/single_vm.ts
@@ -24,10 +24,11 @@ async function cancel(client, vms) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "newVMS";
+  const grid3 = await getClient(`vm/${name}`);
 
   const vms: MachinesModel = {
-    name: "newVMS",
+    name,
     network: {
       name: "wedtest",
       ip_range: "10.249.0.0/16",
@@ -65,10 +66,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: vms.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/single_vm_mycelium.ts b/packages/grid_client/scripts/single_vm_mycelium.ts
index 2f9b65704b..07b7152260 100644
--- a/packages/grid_client/scripts/single_vm_mycelium.ts
+++ b/packages/grid_client/scripts/single_vm_mycelium.ts
@@ -24,10 +24,11 @@ async function cancel(client, vms) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "newMY";
+  const grid3 = await getClient(`vm/${name}`);
 
   const vms: MachinesModel = {
-    name: "newMY",
+    name,
     network: {
       name: "hellotest",
       ip_range: "10.249.0.0/16",
@@ -72,10 +73,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: vms.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/vm_with_gpu.ts b/packages/grid_client/scripts/vm_with_gpu.ts
index 5ec8005d48..33c7763719 100644
--- a/packages/grid_client/scripts/vm_with_gpu.ts
+++ b/packages/grid_client/scripts/vm_with_gpu.ts
@@ -24,7 +24,8 @@ async function cancel(client, vms) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "vmgpu";
+  const grid3 = await getClient(`vm/${name}`);
 
   const vmQueryOptions: FilterOptions = {
     cru: 8,
@@ -48,7 +49,7 @@ async function main() {
   }
 
   const vms: MachinesModel = {
-    name: "vmgpu",
+    name,
     network: {
       name: "vmgpuNetwork",
       ip_range: "10.249.0.0/16",
@@ -76,7 +77,7 @@ async function main() {
         env: {
           SSH_KEY: config.ssh_key,
         },
-        gpus: gpuList[0].id,
+        gpus: [gpuList[0].id],
       },
     ],
     metadata: "",
@@ -87,10 +88,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: vms.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/scripts/vm_with_qsfs.ts b/packages/grid_client/scripts/vm_with_qsfs.ts
index 01ddd68fbe..ffef85948f 100644
--- a/packages/grid_client/scripts/vm_with_qsfs.ts
+++ b/packages/grid_client/scripts/vm_with_qsfs.ts
@@ -38,10 +38,10 @@ async function deleteQsfs(client, qsfs) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "wed2710t1";
+  const grid3 = await getClient(`vm/${name}`);
 
   const qsfs_name = "wed2710q1";
-  const machines_name = "wed2710t1";
 
   const vmQueryOptions: FilterOptions = {
     cru: 1,
@@ -57,7 +57,7 @@ async function main() {
     farmId: 1,
   };
 
-  const qsfsNodes = [];
+  const qsfsNodes: number[] = [];
 
   const allNodes = await grid3.capacity.filterNodes(qsfsQueryOptions);
   if (allNodes.length >= 2) {
@@ -79,7 +79,7 @@ async function main() {
   };
 
   const vms: MachinesModel = {
-    name: machines_name,
+    name,
     network: {
       name: "wed2710n1",
       ip_range: "10.201.0.0/16",
@@ -132,10 +132,10 @@ async function main() {
   await deploy(grid3, vms);
 
   //Get the deployment
-  await getDeployment(grid3, vms.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: machines_name });
+  // await cancel(grid3, { name });
   // await deleteQsfs(grid3, { name: qsfs_name });
 
   await grid3.disconnect();
diff --git a/packages/grid_client/scripts/wireguard_vm.ts b/packages/grid_client/scripts/wireguard_vm.ts
index 42cf5a9027..acb0f3ec77 100644
--- a/packages/grid_client/scripts/wireguard_vm.ts
+++ b/packages/grid_client/scripts/wireguard_vm.ts
@@ -2,6 +2,8 @@ import { FilterOptions, GatewayNameModel, MachineModel, MachinesModel, NetworkMo
 import { config, getClient } from "./client_loader";
 import { log } from "./utils";
 
+const name = "newVMs";
+
 function createNetworkModel(gwNode: number, name: string): NetworkModel {
   return {
     name,
@@ -30,7 +32,7 @@ function createMachineModel(node: number) {
 }
 function createMachinesModel(vm: MachineModel, network: NetworkModel): MachinesModel {
   return {
-    name: "newVMs",
+    name,
     network,
     machines: [vm],
     metadata: "",
@@ -91,7 +93,7 @@ async function deleteGw(client, gw) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const grid3 = await getClient(`vm/${name}`);
 
   const gwNode = +(await grid3.capacity.filterNodes({ gateway: true }))[0].nodeId;
 
@@ -112,7 +114,7 @@ async function main() {
   await deployVM(grid3, machines);
 
   //Get VM deployment
-  const deployedVm = await getVMDeployment(grid3, machines.name);
+  const deployedVm = await getVMDeployment(grid3, name);
 
   const vmPrivateIP = (deployedVm as { interfaces: { ip: string }[] }[])[0].interfaces[0].ip;
   const gateway = createGwModel(gwNode, vmPrivateIP, network.name, "pyserver1", 8000);
@@ -125,7 +127,7 @@ async function main() {
   await getGwDeployment(grid3, gateway.name);
 
   // delete
-  // await deleteVM(grid3, { name: machines.name });
+  await deleteVM(grid3, { name });
   // await deleteGw(grid3, { name: gateway.name });
 
   await grid3.disconnect();
diff --git a/packages/grid_client/scripts/zdb.ts b/packages/grid_client/scripts/zdb.ts
index 0818b64fda..e696f78c01 100644
--- a/packages/grid_client/scripts/zdb.ts
+++ b/packages/grid_client/scripts/zdb.ts
@@ -24,7 +24,8 @@ async function cancel(client, zdb) {
 }
 
 async function main() {
-  const grid3 = await getClient();
+  const name = "tttzdbs";
+  const grid3 = await getClient(`zdb/${name}`);
 
   const zdbQueryOptions: FilterOptions = {
     sru: 1,
@@ -34,7 +35,7 @@ async function main() {
   };
 
   const zdbs: ZDBSModel = {
-    name: "tttzdbs",
+    name,
     zdbs: [
       {
         name: "hamada",
@@ -53,10 +54,10 @@ async function main() {
   await deploy(grid3, zdbs);
 
   //Get the deployment
-  await getDeployment(grid3, zdbs.name);
+  await getDeployment(grid3, name);
 
   //Uncomment the line below to cancel the deployment
-  // await cancel(grid3, { name: zdbs.name });
+  // await cancel(grid3, { name });
 
   await grid3.disconnect();
 }
diff --git a/packages/grid_client/src/clients/tf-grid/contracts.ts b/packages/grid_client/src/clients/tf-grid/contracts.ts
index 0b7a5c2749..73bd994ba4 100644
--- a/packages/grid_client/src/clients/tf-grid/contracts.ts
+++ b/packages/grid_client/src/clients/tf-grid/contracts.ts
@@ -17,6 +17,9 @@ export interface ListContractByTwinIdOptions {
   graphqlURL: string;
   twinId: number;
   stateList?: ContractStates[];
+  type?: string;
+  projectName?: string;
+  nodeId?: number;
 }
 
 export interface ContractUsedResources {
@@ -46,7 +49,8 @@ export interface GqlNodeContract extends GqlBaseContract {
   deploymentData: string;
   deploymentHash: string;
   numberOfPublicIPs: number;
-  resourcesUsed: ContractUsedResources;
+  resourcesUsed: ContractUsedResources | undefined;
+  parsedDeploymentData?: { type: string; name: string; projectName: string };
 }
 
 export interface GqlRentContract extends GqlBaseContract {
@@ -81,6 +85,9 @@ export interface ListContractByAddressOptions {
 export interface ListMyContractOptions {
   graphqlURL: string;
   stateList?: ContractStates[];
+  type?: string;
+  projectName?: string;
+  nodeId?: number;
 }
 
 export interface GetConsumptionOptions {
@@ -141,6 +148,56 @@ class TFContracts extends Contracts {
     }
   }
 
+  async listNodeContractsByTwinId(options: ListContractByTwinIdOptions): Promise<GqlNodeContract[]> {
+    options.stateList = options.stateList || [ContractStates.Created, ContractStates.GracePeriod];
+    const state = `[${options.stateList.join(", ")}]`;
+    const gqlClient = new Graphql(options.graphqlURL);
+    const opts = `(where: {twinID_eq: ${options.twinId}, state_in: ${state}}, orderBy: twinID_ASC)`;
+
+    // filter contracts based on deploymentData
+    let filterQuery = "";
+    if (options.nodeId) {
+      filterQuery += ` , nodeID_eq: ${options.nodeId}`;
+    }
+    if (options.type || options.projectName) {
+      filterQuery += " , AND: [";
+
+      if (options.type) {
+        // eslint-disable-next-line no-useless-escape
+        filterQuery += `{ deploymentData_contains: \"\\\"type\\\":\\\"${options.type}\\\"\" },`;
+      }
+
+      if (options.projectName) {
+        // eslint-disable-next-line no-useless-escape
+        filterQuery += `{ deploymentData_contains: \"\\\"projectName\\\":\\\"${options.projectName}\" }`;
+      }
+
+      filterQuery += "]";
+    }
+
+    try {
+      const nodeContractsCount = await gqlClient.getItemTotalCount("nodeContracts", opts);
+      const body = `query getContracts($nodeContractsCount: Int!){
+                nodeContracts(where: {twinID_eq: ${options.twinId}, state_in: ${state}${filterQuery}}, limit: $nodeContractsCount) {
+                  contractID
+                  deploymentData
+                  state
+                  createdAt
+                  nodeID
+                  numberOfPublicIPs
+                }
+              }`;
+      const response = await gqlClient.query(body, {
+        nodeContractsCount,
+      });
+
+      return (response["data"] as GqlContracts).nodeContracts;
+    } catch (err) {
+      (err as Error).message = formatErrorMessage(`Error listing contracts by twin id ${options.twinId}.`, err);
+      throw err;
+    }
+  }
+
   /**
    * Get contract consumption per hour in TFT.
    *
@@ -221,6 +278,18 @@ class TFContracts extends Contracts {
     });
   }
 
+  async listMyNodeContracts(options: ListMyContractOptions): Promise<GqlNodeContract[]> {
+    const twinId = await this.client.twins.getMyTwinId();
+    return await this.listNodeContractsByTwinId({
+      graphqlURL: options.graphqlURL,
+      twinId: twinId,
+      stateList: options.stateList,
+      type: options.type,
+      projectName: options.projectName,
+      nodeId: options.nodeId,
+    });
+  }
+
   async contractLock(options: ContractLockOptions) {
     const res = await super.contractLock(options);
     const amountLocked = new Decimal(res.amountLocked);
diff --git a/packages/grid_client/src/high_level/base.ts b/packages/grid_client/src/high_level/base.ts
index f0de74c782..4ca842d2eb 100644
--- a/packages/grid_client/src/high_level/base.ts
+++ b/packages/grid_client/src/high_level/base.ts
@@ -102,7 +102,7 @@ class HighLevelBase {
       events.emit("logs", `Deleting ip: ${machineIp} from node: ${node_id}, network ${network.name}`);
       const deletedIp = network.deleteReservedIp(node_id, machineIp);
       if (remainingWorkloads.length === 0) {
-        twinDeployments.push(new TwinDeployment(deployment, Operations.delete, 0, 0, network));
+        twinDeployments.push(new TwinDeployment(deployment, Operations.delete, 0, 0, "", network));
       }
       const numberOfIps = network.getNodeReservedIps(node_id).length;
       if (numberOfIps !== 0) {
@@ -122,7 +122,7 @@ class HighLevelBase {
       const contract_id = await network.deleteNode(node_id);
       if (contract_id === deployment.contract_id) {
         if (remainingWorkloads.length === 1) {
-          twinDeployments.push(new TwinDeployment(deployment, Operations.delete, 0, 0, network));
+          twinDeployments.push(new TwinDeployment(deployment, Operations.delete, 0, 0, "", network));
           remainingWorkloads = [];
         } else {
           remainingWorkloads = remainingWorkloads.filter(item => item.name !== network?.name);
@@ -137,10 +137,10 @@ class HighLevelBase {
             continue;
           }
           if (d.workloads.length === 1) {
-            twinDeployments.push(new TwinDeployment(d, Operations.delete, 0, 0, network));
+            twinDeployments.push(new TwinDeployment(d, Operations.delete, 0, 0, "", network));
           } else {
             d.workloads = d.workloads.filter(item => item.name !== network?.name);
-            twinDeployments.push(new TwinDeployment(d, Operations.update, 0, 0, network));
+            twinDeployments.push(new TwinDeployment(d, Operations.update, 0, 0, "", network));
           }
         }
       }
@@ -153,10 +153,10 @@ class HighLevelBase {
             continue;
           }
           if (d.workloads.length === 1) {
-            twinDeployments.push(new TwinDeployment(d, Operations.delete, 0, 0, network));
+            twinDeployments.push(new TwinDeployment(d, Operations.delete, 0, 0, "", network));
           } else {
             d.workloads = d.workloads.filter(item => item.name !== network?.name);
-            twinDeployments.push(new TwinDeployment(d, Operations.update, 0, 0, network));
+            twinDeployments.push(new TwinDeployment(d, Operations.update, 0, 0, "", network));
           }
         }
       }
@@ -193,7 +193,7 @@ class HighLevelBase {
     const deletedMachineWorkloads = filteredWorkloads[1];
 
     if (remainingWorkloads.length === 0 && deletedMachineWorkloads.length === 0) {
-      twinDeployments.push(new TwinDeployment(deployment, Operations.delete, 0, 0));
+      twinDeployments.push(new TwinDeployment(deployment, Operations.delete, 0, 0, ""));
     }
     const [newTwinDeployments, newRemainingWorkloads, deletedNodes, deletedIps, network] =
       await this._deleteMachineNetwork(deployment, remainingWorkloads, deletedMachineWorkloads, node_id);
@@ -207,7 +207,7 @@ class HighLevelBase {
         network!.deleteReservedIp(node_id, deleteIp);
       }
       deployment.workloads = remainingWorkloads;
-      twinDeployments.push(new TwinDeployment(deployment, Operations.update, 0, 0, network!));
+      twinDeployments.push(new TwinDeployment(deployment, Operations.update, 0, 0, "", network!));
     }
     return twinDeployments;
   }
diff --git a/packages/grid_client/src/high_level/gateway.ts b/packages/grid_client/src/high_level/gateway.ts
index 4557854d1e..3857e7c858 100644
--- a/packages/grid_client/src/high_level/gateway.ts
+++ b/packages/grid_client/src/high_level/gateway.ts
@@ -1,4 +1,5 @@
 import { DeploymentFactory, GWPrimitive } from "../primitives/index";
+import { Workload } from "../zos";
 import { HighLevelBase } from "./base";
 import { Operations, TwinDeployment } from "./models";
 
@@ -9,6 +10,7 @@ class GatewayHL extends HighLevelBase {
     tls_passthrough: boolean,
     backends: string[],
     network: string,
+    contractMetadata: string,
     metadata: string,
     description: string,
     fqdn = "",
@@ -16,17 +18,25 @@ class GatewayHL extends HighLevelBase {
   ): Promise<TwinDeployment[]> {
     const public_ips = 0;
     const gw = new GWPrimitive();
-    const workloads = [];
+    const workloads: Workload[] = [];
     if (fqdn != "") {
-      workloads.push(gw.createFQDN(fqdn, tls_passthrough, backends, name, network, metadata, description));
+      workloads.push(gw.createFQDN(fqdn, tls_passthrough, backends, name, network, "", description));
     } else {
-      workloads.push(gw.createName(name, tls_passthrough, backends, network, metadata, description));
+      workloads.push(gw.createName(name, tls_passthrough, backends, network, "", description));
     }
     const deploymentFactory = new DeploymentFactory(this.config);
     const deployment = deploymentFactory.create(workloads, 1626394539, metadata, description, 0);
-    const twinDeployments = [];
+    const twinDeployments: TwinDeployment[] = [];
     twinDeployments.push(
-      new TwinDeployment(deployment, Operations.deploy, public_ips, node_id, null, solutionProviderId),
+      new TwinDeployment(
+        deployment,
+        Operations.deploy,
+        public_ips,
+        node_id,
+        contractMetadata,
+        null,
+        solutionProviderId,
+      ),
     );
     return twinDeployments;
   }
diff --git a/packages/grid_client/src/high_level/kubernetes.ts b/packages/grid_client/src/high_level/kubernetes.ts
index 79c0b5153c..1a43a4f6fd 100644
--- a/packages/grid_client/src/high_level/kubernetes.ts
+++ b/packages/grid_client/src/high_level/kubernetes.ts
@@ -25,6 +25,7 @@ class KubernetesHL extends HighLevelBase {
     network: Network,
     myceliumNetworkSeeds: MyceliumNetworkModel[] = [],
     sshKey: string,
+    contractMetadata: string,
     metadata = "",
     description = "",
     qsfs_disks: QSFSDiskModel[] = [],
@@ -70,6 +71,7 @@ class KubernetesHL extends HighLevelBase {
       myceliumNetworkSeeds!,
       "/sbin/zinit init",
       env,
+      contractMetadata,
       metadata,
       description,
       qsfs_disks,
@@ -101,6 +103,7 @@ class KubernetesHL extends HighLevelBase {
     network: Network,
     myceliumNetworkSeeds: MyceliumNetworkModel[] = [],
     sshKey: string,
+    contractMetadata,
     metadata = "",
     description = "",
     qsfs_disks: QSFSDiskModel[] = [],
@@ -146,6 +149,7 @@ class KubernetesHL extends HighLevelBase {
       myceliumNetworkSeeds,
       "/sbin/zinit init",
       env,
+      contractMetadata,
       metadata,
       description,
       qsfs_disks,
diff --git a/packages/grid_client/src/high_level/machine.ts b/packages/grid_client/src/high_level/machine.ts
index f095774cf4..76fd23988b 100644
--- a/packages/grid_client/src/high_level/machine.ts
+++ b/packages/grid_client/src/high_level/machine.ts
@@ -40,6 +40,7 @@ class VMHL extends HighLevelBase {
     myceliumNetworkSeeds: MyceliumNetworkModel[] = [],
     entrypoint: string,
     env: Record<string, unknown>,
+    contractMetadata: string,
     metadata = "",
     description = "",
     qsfsDisks: QSFSDiskModel[] = [],
@@ -61,7 +62,7 @@ class VMHL extends HighLevelBase {
     const disk = new DiskPrimitive();
     for (const d of disks) {
       totalDisksSize += d.size;
-      workloads.push(disk.create(d.size, d.name, metadata, description));
+      workloads.push(disk.create(d.size, d.name, "", description));
       diskMounts.push(disk.createMount(d.name, d.mountpoint));
     }
 
@@ -136,7 +137,7 @@ class VMHL extends HighLevelBase {
     if (publicIp || publicIp6) {
       const ip = new PublicIPPrimitive();
       ipName = `${name}_pubip`;
-      workloads.push(ip.create(ipName, metadata, description, 0, publicIp, publicIp6));
+      workloads.push(ip.create(ipName, "", description, 0, publicIp, publicIp6));
       if (publicIp) {
         publicIps++;
       }
@@ -176,7 +177,8 @@ class VMHL extends HighLevelBase {
       accessNodeSubnet = network.getFreeSubnet();
     }
     // network
-    const networkMetadata = JSON.stringify({
+    const networkContractMetadata = JSON.stringify({
+      version: 3,
       type: "network",
       name: network.name,
       projectName: this.config.projectName,
@@ -219,7 +221,6 @@ class VMHL extends HighLevelBase {
       access_net_workload = await network.addNode(
         access_node_id,
         mycelium,
-        networkMetadata,
         description,
         accessNodeSubnet,
         myceliumNetworkSeeds,
@@ -230,55 +231,78 @@ class VMHL extends HighLevelBase {
     if (network.nodeExists(nodeId)) {
       const deployment = await network.checkMycelium(nodeId, mycelium, myceliumNetworkSeeds);
       if (deployment) {
-        deployments.push(new TwinDeployment(deployment, Operations.update, 0, 0, network));
+        deployments.push(new TwinDeployment(deployment, Operations.update, 0, 0, networkContractMetadata, network));
       }
     }
 
-    const znet_workload = await network.addNode(
-      nodeId,
-      mycelium,
-      networkMetadata,
-      description,
-      userIPsubnet,
-      myceliumNetworkSeeds,
-    );
+    const znet_workload = await network.addNode(nodeId, mycelium, description, userIPsubnet, myceliumNetworkSeeds);
     if ((await network.exists()) && (znet_workload || access_net_workload)) {
       // update network
       for (const deployment of network.deployments) {
         const d = await deploymentFactory.fromObj(deployment);
         for (const workload of d["workloads"]) {
           if (
-            workload["type"] !== WorkloadTypes.network ||
-            !Addr(network.ipRange).contains(Addr(workload["data"]["subnet"]))
+            workload.type !== WorkloadTypes.network ||
+            !Addr(network.ipRange).contains(Addr(workload.data["subnet"]))
           ) {
             continue;
           }
-          workload.data = network.updateNetwork(workload["data"]);
+          workload.data = network.getUpdatedNetwork(workload["data"]);
           workload.version += 1;
           break;
         }
-        deployments.push(new TwinDeployment(d, Operations.update, 0, 0, network));
+        deployments.push(new TwinDeployment(d, Operations.update, 0, 0, networkContractMetadata, network));
       }
       if (znet_workload) {
-        const deployment = deploymentFactory.create([znet_workload], 0, networkMetadata, description, 0);
-        deployments.push(new TwinDeployment(deployment, Operations.deploy, 0, nodeId, network, solutionProviderId));
+        const deployment = deploymentFactory.create([znet_workload], 0, networkContractMetadata, description, 0);
+        deployments.push(
+          new TwinDeployment(
+            deployment,
+            Operations.deploy,
+            0,
+            nodeId,
+            networkContractMetadata,
+            network,
+            solutionProviderId,
+          ),
+        );
       }
     } else if (znet_workload) {
       // node not exist on the network
       if (!access_net_workload && !hasAccessNode && addAccess) {
         // this node is access node, so add access point on it
         wgConfig = await network.addAccess(nodeId, true);
-        znet_workload["data"] = network.updateNetwork(znet_workload.data);
+        znet_workload["data"] = network.getUpdatedNetwork(znet_workload.data);
       }
-      const deployment = deploymentFactory.create([znet_workload], 0, networkMetadata, description, 0);
-      deployments.push(new TwinDeployment(deployment, Operations.deploy, 0, nodeId, network, solutionProviderId));
+      const deployment = deploymentFactory.create([znet_workload], 0, networkContractMetadata, description, 0);
+      deployments.push(
+        new TwinDeployment(
+          deployment,
+          Operations.deploy,
+          0,
+          nodeId,
+          networkContractMetadata,
+          network,
+          solutionProviderId,
+        ),
+      );
     }
     if (access_net_workload) {
       // network is not exist, and the node provide is not an access node
       const accessNodeId = access_net_workload.data["node_id"];
-      access_net_workload["data"] = network.updateNetwork(access_net_workload.data);
-      const deployment = deploymentFactory.create([access_net_workload], 0, networkMetadata, description, 0);
-      deployments.push(new TwinDeployment(deployment, Operations.deploy, 0, accessNodeId, network, solutionProviderId));
+      access_net_workload["data"] = network.getUpdatedNetwork(access_net_workload.data);
+      const deployment = deploymentFactory.create([access_net_workload], 0, networkContractMetadata, description, 0);
+      deployments.push(
+        new TwinDeployment(
+          deployment,
+          Operations.deploy,
+          0,
+          accessNodeId,
+          networkContractMetadata,
+          network,
+          solutionProviderId,
+        ),
+      );
     }
 
     // vm
@@ -322,7 +346,7 @@ class VMHL extends HighLevelBase {
         ipName,
         entrypoint,
         env,
-        metadata,
+        "",
         description,
         0,
         corex,
@@ -332,14 +356,24 @@ class VMHL extends HighLevelBase {
 
     if (zlogsOutput) {
       const zlogs = new ZlogsPrimitive();
-      workloads.push(zlogs.create(name, zlogsOutput, metadata, description));
+      workloads.push(zlogs.create(name, zlogsOutput, "", description));
     }
 
     // deployment
     // NOTE: expiration is not used for zos deployment
     const deployment = deploymentFactory.create(workloads, 0, metadata, description, 0);
 
-    deployments.push(new TwinDeployment(deployment, Operations.deploy, publicIps, nodeId, network, solutionProviderId));
+    deployments.push(
+      new TwinDeployment(
+        deployment,
+        Operations.deploy,
+        publicIps,
+        nodeId,
+        contractMetadata,
+        network,
+        solutionProviderId,
+      ),
+    );
     return [deployments, wgConfig];
   }
 
diff --git a/packages/grid_client/src/high_level/models.ts b/packages/grid_client/src/high_level/models.ts
index ed6470a750..bff2730a71 100644
--- a/packages/grid_client/src/high_level/models.ts
+++ b/packages/grid_client/src/high_level/models.ts
@@ -13,6 +13,7 @@ class TwinDeployment {
     public operation: Operations,
     public publicIps: number,
     public nodeId: number,
+    public metadata: string,
     public network: Network | null = null,
     public solutionProviderId: number | null = null,
     public returnNetworkContracts = false,
diff --git a/packages/grid_client/src/high_level/network.ts b/packages/grid_client/src/high_level/network.ts
index 984bba8333..06b41664b2 100644
--- a/packages/grid_client/src/high_level/network.ts
+++ b/packages/grid_client/src/high_level/network.ts
@@ -1,13 +1,30 @@
 import { ValidationError } from "@threefold/types";
 import { Addr } from "netaddr";
+import * as PATH from "path";
 
+import { GridClientConfig } from "../config";
 import { MyceliumNetworkModel } from "../modules";
-import { DeploymentFactory, Network } from "../primitives";
+import { DeploymentFactory, Network, UserAccess } from "../primitives";
+import { BackendStorage } from "../storage";
 import { WorkloadTypes, Znet } from "../zos";
 import { HighLevelBase } from "./base";
 import { Operations, TwinDeployment } from "./models";
 
 class NetworkHL extends HighLevelBase {
+  backendStorage: BackendStorage;
+  constructor(public config: GridClientConfig) {
+    super(config);
+    this.backendStorage = new BackendStorage(
+      config.backendStorageType,
+      config.substrateURL,
+      config.mnemonic,
+      config.storeSecret,
+      config.keypairType,
+      config.backendStorage,
+      config.seed,
+    );
+  }
+
   async addNode(
     networkName: string,
     ipRange: string,
@@ -20,29 +37,23 @@ class NetworkHL extends HighLevelBase {
   ) {
     const network = new Network(networkName, ipRange, this.config);
     await network.load();
-    const networkMetadata = JSON.stringify({
+    const contractMetadata = JSON.stringify({
+      version: 3,
       type: "network",
       name: networkName,
       projectName: this.config.projectName,
     });
 
-    const workload = await network.addNode(
-      nodeId,
-      mycelium,
-      networkMetadata,
-      description,
-      subnet,
-      myceliumNetworkSeeds,
-    );
+    const workload = await network.addNode(nodeId, mycelium, description, subnet, myceliumNetworkSeeds);
     if (!workload) {
       throw new ValidationError(`Node ${nodeId} already exists on network ${networkName}.`);
     }
 
     const twinDeployments: TwinDeployment[] = [];
     const deploymentFactory = new DeploymentFactory(this.config);
-    const deployment = deploymentFactory.create([workload], 0, networkMetadata, description, 0);
+    const deployment = deploymentFactory.create([workload], 0, contractMetadata, description, 0);
     twinDeployments.push(
-      new TwinDeployment(deployment, Operations.deploy, 0, nodeId, network, solutionProviderId, true),
+      new TwinDeployment(deployment, Operations.deploy, 0, nodeId, contractMetadata, network, solutionProviderId, true),
     );
 
     if (!(await network.exists())) {
@@ -56,11 +67,13 @@ class NetworkHL extends HighLevelBase {
         if (workload.type !== WorkloadTypes.network || !Addr(network.ipRange).contains(Addr(data.subnet))) {
           continue;
         }
-        workload.data = network.updateNetwork(data);
+        workload.data = network.getUpdatedNetwork(data);
         workload.version += 1;
         break;
       }
-      twinDeployments.push(new TwinDeployment(d, Operations.update, 0, 0, network, solutionProviderId, true));
+      twinDeployments.push(
+        new TwinDeployment(d, Operations.update, 0, 0, contractMetadata, network, solutionProviderId, true),
+      );
     }
     return twinDeployments;
   }
@@ -70,6 +83,31 @@ class NetworkHL extends HighLevelBase {
     await network.load();
     return network.nodeExists(nodeId);
   }
+
+  async getWireguardConfigs(networkName: string, ipRange: string, nodeId?: number): Promise<string[]> {
+    const configs: string[] = [];
+    const network = new Network(networkName, ipRange, this.config);
+    await network.load();
+    if (nodeId && !network.nodeExists(nodeId)) {
+      return configs;
+    }
+    let userAccesses: UserAccess[] = network.userAccesses;
+    if (network.userAccesses && network.userAccesses.length > 0) {
+      if (nodeId && network.nodeExists(nodeId)) {
+        userAccesses = network.userAccesses.filter(userAccess => userAccess.node_id === nodeId);
+      }
+      for (const userAccess of userAccesses) {
+        const nodesWGPubkey = await network.getNodeWGPublicKey(userAccess.node_id);
+        const endpoint = await network.getAccessNodeEndpoint(userAccess.node_id);
+        configs.push(network.getWireguardConfig(userAccess.subnet, userAccess.private_key, nodesWGPubkey, endpoint));
+      }
+      return configs;
+    } else {
+      const path = PATH.join(this.config.storePath, "networks", networkName, "info.json");
+      const networkInfo = await this.backendStorage.load(path);
+      return networkInfo["wireguardConfigs"] || [];
+    }
+  }
 }
 
 export { NetworkHL };
diff --git a/packages/grid_client/src/high_level/twinDeploymentHandler.ts b/packages/grid_client/src/high_level/twinDeploymentHandler.ts
index 9f75e559cd..c2983d9a38 100644
--- a/packages/grid_client/src/high_level/twinDeploymentHandler.ts
+++ b/packages/grid_client/src/high_level/twinDeploymentHandler.ts
@@ -136,14 +136,13 @@ class TwinDeploymentHandler {
   }
 
   async saveNetworks(twinDeployments: TwinDeployment[]) {
+    // left just to delete the old keys
     for (const twinDeployment of twinDeployments) {
       if (twinDeployment.network) {
         if (twinDeployment.operation === Operations.delete) {
           await twinDeployment.network.save();
           continue;
         }
-        // deploy or update operations
-        await twinDeployment.network.save(twinDeployment.deployment.contract_id, twinDeployment.nodeId);
       }
     }
   }
@@ -433,6 +432,7 @@ class TwinDeploymentHandler {
             Operations.update,
             0,
             old_contract.contractType.nodeContract.nodeId,
+            "",
           ),
         );
       }
@@ -459,7 +459,7 @@ class TwinDeploymentHandler {
       }
       const extrinsic = await this.tfclient.contracts.createNode({
         hash: twinDeployment.deployment.challenge_hash(),
-        data: twinDeployment.deployment.metadata,
+        data: twinDeployment.metadata,
         nodeId: twinDeployment.nodeId,
         numberOfPublicIps: twinDeployment.publicIps,
         solutionProviderId: twinDeployment.solutionProviderId,
@@ -505,8 +505,16 @@ class TwinDeploymentHandler {
     await this.checkNodesCapacity(twinDeployments);
     await this.checkFarmIps(twinDeployments);
 
-    const contracts = { created: [], updated: [], deleted: [] };
-    const resultContracts = { created: [], updated: [], deleted: [] };
+    const contracts: { created: Contract[]; updated: Contract[]; deleted: { contractId: number }[] } = {
+      created: [],
+      updated: [],
+      deleted: [],
+    };
+    const resultContracts: { created: Contract[]; updated: Contract[]; deleted: { contractId: number }[] } = {
+      created: [],
+      updated: [],
+      deleted: [],
+    };
     let nodeExtrinsics: ExtrinsicResult<Contract>[] = [];
     let nameExtrinsics: ExtrinsicResult<Contract>[] = [];
     let deletedExtrinsics: ExtrinsicResult<number>[] = [];
@@ -518,7 +526,7 @@ class TwinDeploymentHandler {
         }
         if (workload.type === WorkloadTypes.network) {
           events.emit("logs", `Updating network workload with name: ${workload.name}`);
-          workload["data"] = twinDeployment.network.updateNetwork(workload.data);
+          twinDeployment.network.updateWorkload(twinDeployment.nodeId, workload);
         }
       }
       const extrinsics = await this.PrepareExtrinsic(twinDeployment, contracts);
diff --git a/packages/grid_client/src/high_level/zdb.ts b/packages/grid_client/src/high_level/zdb.ts
index 132762424a..f3168cbaaa 100644
--- a/packages/grid_client/src/high_level/zdb.ts
+++ b/packages/grid_client/src/high_level/zdb.ts
@@ -17,6 +17,7 @@ class ZdbHL extends HighLevelBase {
     mode: ZdbModes,
     password: string,
     publicNamespace: boolean,
+    contractMetadata: string,
     metadata = "",
     description = "",
     solutionProviderId?: number,
@@ -31,7 +32,7 @@ class ZdbHL extends HighLevelBase {
     const zdbFactory = new ZdbPrimitive();
     const zdbWorkload = zdbFactory.create(name, disk_size, mode, password, publicNamespace, metadata, description);
     const deployment = deploymentFactory.create([zdbWorkload], 1626394539, metadata, description, 0);
-    return new TwinDeployment(deployment, Operations.deploy, 0, node_id, null, solutionProviderId);
+    return new TwinDeployment(deployment, Operations.deploy, 0, node_id, contractMetadata, null, solutionProviderId);
   }
   async delete(deployment: Deployment, names: string[]) {
     return await this._delete(deployment, names, [WorkloadTypes.zdb]);
diff --git a/packages/grid_client/src/modules/base.ts b/packages/grid_client/src/modules/base.ts
index de2c611f22..83985877db 100644
--- a/packages/grid_client/src/modules/base.ts
+++ b/packages/grid_client/src/modules/base.ts
@@ -1,7 +1,8 @@
+import { Contract } from "@threefold/tfchain_client";
 import { GridClientErrors, ValidationError } from "@threefold/types";
 import * as PATH from "path";
 
-import { RMB } from "../clients";
+import { GqlNodeContract, RMB } from "../clients";
 import { TFClient } from "../clients/tf-grid/client";
 import { GridClientConfig } from "../config";
 import { formatErrorMessage } from "../helpers";
@@ -21,7 +22,15 @@ import { QuantumSafeFS, QuantumSafeFSResult } from "../zos/qsfs";
 import { Workload, WorkloadTypes } from "../zos/workload";
 import { Zmachine, ZmachineResult } from "../zos/zmachine";
 import { Zmount } from "../zos/zmount";
-
+import { ContractStates } from "./models";
+
+const modulesNames = {
+  machines: "vm",
+  kubernetes: "kubernetes",
+  gateways: "gateway",
+  qsfs_zdbs: "QSFS",
+  zdb: "zdb",
+};
 class BaseModule {
   moduleName = "";
   projectName = "";
@@ -31,6 +40,9 @@ class BaseModule {
   twinDeploymentHandler: TwinDeploymentHandler;
   backendStorage: BackendStorage;
   tfClient: TFClient;
+  contracts: Required<GqlNodeContract>[];
+  static newContracts: GqlNodeContract[] = [];
+  static deletedContracts: number[] = [];
 
   constructor(public config: GridClientConfig) {
     this.projectName = config.projectName;
@@ -57,7 +69,7 @@ class BaseModule {
     return PATH.join(this.config.storePath, this.projectName, this.moduleName, name);
   }
 
-  async getDeploymentContracts(name: string) {
+  async getOldDeploymentContracts(name: string) {
     const path = this.getNewDeploymentPath(name, "contracts.json");
     const contracts = await this.backendStorage.load(path);
     if (!contracts) {
@@ -66,23 +78,39 @@ class BaseModule {
     return contracts;
   }
 
-  async save(name: string, contracts: Record<string, unknown[]>) {
+  async getDeploymentContracts(name: string) {
+    const contracts = await this.getMyContracts();
+    return contracts.filter(c => c.parsedDeploymentData.name === name);
+  }
+
+  async save(name: string, contracts: { created: Contract[]; updated: Contract[]; deleted: { contractId: number }[] }) {
     const contractsPath = PATH.join(this.getNewDeploymentPath(name), "contracts.json");
     const wireguardPath = PATH.join(this.getDeploymentPath(name), `${name}.conf`);
-    const oldContracts = await this.getDeploymentContracts(name);
+    const oldContracts = await this.getOldDeploymentContracts(name);
     let StoreContracts = oldContracts;
     let backendOperations = [];
 
     for (const contract of contracts["created"]) {
-      StoreContracts.push({
-        contract_id: contract["contractId"],
-        node_id: contract["contractType"]["nodeContract"]["nodeId"],
+      if (!contract.contractType.nodeContract) continue;
+      BaseModule.newContracts.push({
+        contractID: String(contract.contractId),
+        createdAt: Date.now().toString(),
+        deploymentData: contract.contractType.nodeContract.deploymentData,
+        deploymentHash: contract.contractType.nodeContract.deploymentHash,
+        gridVersion: "4",
+        id: "",
+        nodeID: contract.contractType.nodeContract.nodeId,
+        numberOfPublicIPs: contract.contractType.nodeContract.publicIps,
+        solutionProviderID: String(contract.solutionProviderId),
+        state: ContractStates.Created,
+        twinID: String(contract.twinId),
+        parsedDeploymentData: JSON.parse(contract.contractType.nodeContract.deploymentData),
+        resourcesUsed: undefined,
       });
-      const contractPath = PATH.join(this.config.storePath, "contracts", `${contract["contractId"]}.json`);
-      const contractInfo = { projectName: this.projectName, moduleName: this.moduleName, deploymentName: name };
-      backendOperations = backendOperations.concat(await this.backendStorage.dump(contractPath, contractInfo));
     }
+
     for (const contract of contracts["deleted"]) {
+      BaseModule.deletedContracts.push(contract.contractId);
       StoreContracts = StoreContracts.filter(c => c["contract_id"] !== contract["contractId"]);
       const contractPath = PATH.join(this.config.storePath, "contracts", `${contract["contractId"]}.json`);
       backendOperations = backendOperations.concat(await this.backendStorage.dump(contractPath, ""));
@@ -147,9 +175,52 @@ class BaseModule {
     await Promise.all(keys.map(__updatePath).flat(1));
   }
 
+  private async getMyContracts(fetch = false) {
+    if (fetch || !this.contracts) {
+      let contracts = await this.tfClient.contracts.listMyNodeContracts({
+        graphqlURL: this.config.graphqlURL,
+        type: modulesNames[this.moduleName],
+        projectName: this.projectName,
+      });
+      const alreadyFetchedContracts: GqlNodeContract[] = [];
+      for (const contract of BaseModule.newContracts) {
+        if (contract.parsedDeploymentData?.projectName !== this.projectName) continue;
+        if (contract.parsedDeploymentData.type !== modulesNames[this.moduleName]) continue;
+        const c = contracts.filter(c => +c.contractID === +contract.contractID);
+        if (c.length > 0) {
+          alreadyFetchedContracts.push(contract);
+          continue;
+        }
+        contracts.push(contract);
+      }
+
+      for (const contract of alreadyFetchedContracts) {
+        const index = BaseModule.newContracts.indexOf(contract);
+        if (index > -1) BaseModule.newContracts.splice(index, 1);
+      }
+
+      contracts = contracts.filter(c => !BaseModule.deletedContracts.includes(+c.contractID));
+
+      const parsedContracts: Required<GqlNodeContract>[] = [];
+      for (const contract of contracts) {
+        const parsedDeploymentData = JSON.parse(contract.deploymentData);
+        parsedContracts.push({ ...contract, parsedDeploymentData });
+      }
+
+      this.contracts = parsedContracts;
+    }
+
+    return this.contracts;
+  }
+
+  private _getContractsName(contracts: Required<GqlNodeContract>[]): string[] {
+    return Array.from(new Set(contracts.map(c => c.parsedDeploymentData.name)));
+  }
+
   async _list(): Promise<string[]> {
     await this._migrateListKeys();
-    return this.backendStorage.list(this.getNewDeploymentPath(""));
+    const contracts = await this.getMyContracts(true);
+    return this._getContractsName(contracts);
   }
 
   async exists(name: string): Promise<boolean> {
@@ -166,10 +237,10 @@ class BaseModule {
   }
 
   async _getDeploymentNodeIds(name: string): Promise<number[]> {
-    const nodeIds = [];
+    const nodeIds: number[] = [];
     const contracts = await this.getDeploymentContracts(name);
     for (const contract of contracts) {
-      nodeIds.push(contract["node_id"]);
+      nodeIds.push(contract.nodeID);
     }
     return nodeIds;
   }
@@ -177,18 +248,20 @@ class BaseModule {
   async _getContractIdFromNodeId(name: string, nodeId: number): Promise<number> {
     const contracts = await this.getDeploymentContracts(name);
     for (const contract of contracts) {
-      if (contract["node_id"] === nodeId) {
-        return contract["contract_id"];
+      if (contract.nodeID === nodeId) {
+        return +contract.contractID;
       }
     }
+    return 0;
   }
   async _getNodeIdFromContractId(name: string, contractId: number): Promise<number> {
     const contracts = await this.getDeploymentContracts(name);
     for (const contract of contracts) {
-      if (contract["contract_id"] === contractId) {
-        return contract["node_id"];
+      if (+contract.contractID === contractId) {
+        return contract.nodeID;
       }
     }
+    return 0;
   }
 
   async _getWorkloadsByTypes(deploymentName: string, deployments, types: WorkloadTypes[]): Promise<Workload[]> {
@@ -241,11 +314,13 @@ class BaseModule {
         cpu: data.compute_capacity.cpu,
         memory: data.compute_capacity.memory / 1024 ** 2, // MB
       },
-      mounts: data.mounts.map(m => ({
-        name: m.name,
-        mountPoint: m.mountpoint,
-        ...this._getDiskData(deployments, m.name, workload["contractId"]),
-      })),
+      mounts: data.mounts
+        ? data.mounts.map(m => ({
+            name: m.name,
+            mountPoint: m.mountpoint,
+            ...this._getDiskData(deployments, m.name, workload["contractId"]),
+          }))
+        : [],
       env: data.env,
       entrypoint: data.entrypoint,
       metadata: workload.metadata,
@@ -292,18 +367,18 @@ class BaseModule {
     }
     const contracts = await this.getDeploymentContracts(name);
     if (contracts.length === 0) {
-      await this.save(name, { created: [], deleted: [] });
+      await this.save(name, { created: [], updated: [], deleted: [] });
     }
     await this.tfClient.connect();
     for (const contract of contracts) {
-      const c = await this.tfClient.contracts.get({ id: contract["contract_id"] });
+      const c = await this.tfClient.contracts.get({ id: +contract.contractID });
       if (c === null) {
-        await this.save(name, { created: [], deleted: [{ contractId: contract["contract_id"] }] });
+        await this.save(name, { created: [], updated: [], deleted: [{ contractId: +contract.contractID }] });
         continue;
       }
       const nodes = new Nodes(this.config.graphqlURL, this.config.proxyURL, this.config.rmbClient);
-      const node_twin_id = await nodes.getNodeTwinId(contract["node_id"]);
-      const payload = JSON.stringify({ contract_id: contract["contract_id"] });
+      const node_twin_id = await nodes.getNodeTwinId(contract.nodeID);
+      const payload = JSON.stringify({ contract_id: +contract.contractID });
       let deployment;
       try {
         deployment = await this.rmb.request([node_twin_id], "zos.deployment.get", payload);
@@ -320,7 +395,7 @@ class BaseModule {
       if (found) {
         deployments.push(deployment);
       } else {
-        await this.save(name, { created: [], deleted: [{ contractId: contract["contract_id"] }] });
+        await this.save(name, { created: [], updated: [], deleted: [{ contractId: +contract.contractID }] });
       }
     }
     return deployments;
@@ -363,7 +438,7 @@ class BaseModule {
         if (!updateOldDeployment) {
           continue;
         }
-        finalTwinDeployments.push(new TwinDeployment(updateOldDeployment, Operations.update, 0, 0, network));
+        finalTwinDeployments.push(new TwinDeployment(updateOldDeployment, Operations.update, 0, 0, "", network));
       }
       if (!doneDeploymentIPWorkloadNames.includes(pubIPOLdWorkload)) {
         const tDeployments = await module.delete(oldDeployment, []);
@@ -408,7 +483,7 @@ class BaseModule {
         if (!updateOldDeployment) {
           continue;
         }
-        finalTwinDeployments.push(new TwinDeployment(updateOldDeployment, Operations.update, 0, 0, network));
+        finalTwinDeployments.push(new TwinDeployment(updateOldDeployment, Operations.update, 0, 0, "", network));
         break;
       }
       if (!deploymentFound) {
diff --git a/packages/grid_client/src/modules/gateway.ts b/packages/grid_client/src/modules/gateway.ts
index f9e2a00cf8..b4f5639e3c 100644
--- a/packages/grid_client/src/modules/gateway.ts
+++ b/packages/grid_client/src/modules/gateway.ts
@@ -36,7 +36,8 @@ class GWModule extends BaseModule {
       throw new ValidationError(`Another gateway deployment with the same name ${options.name} already exists.`);
     }
     events.emit("logs", `Start creating the gateway deployment with name ${options.name}`);
-    const metadata = JSON.stringify({
+    const contractMetadata = JSON.stringify({
+      version: 3,
       type: "gateway",
       name: options.name,
       projectName: this.config.projectName,
@@ -47,7 +48,8 @@ class GWModule extends BaseModule {
       options.tls_passthrough,
       options.backends,
       options.network,
-      options.metadata || metadata,
+      contractMetadata,
+      options.metadata,
       options.description,
       options.fqdn,
       options.solutionProviderId,
@@ -65,7 +67,8 @@ class GWModule extends BaseModule {
       throw new ValidationError(`Another gateway deployment with the same name ${options.name} already exists.`);
     }
     events.emit("logs", `Start creating the gateway deployment with name ${options.name}`);
-    const metadata = JSON.stringify({
+    const contractMetadata = JSON.stringify({
+      version: 3,
       type: "gateway",
       name: options.name,
       projectName: this.config.projectName,
@@ -76,7 +79,8 @@ class GWModule extends BaseModule {
       options.tls_passthrough,
       options.backends,
       options.network,
-      options.metadata || metadata,
+      contractMetadata,
+      options.metadata,
       options.description,
       "",
       options.solutionProviderId,
diff --git a/packages/grid_client/src/modules/k8s.ts b/packages/grid_client/src/modules/k8s.ts
index 74ccd53d4c..5a4590a789 100644
--- a/packages/grid_client/src/modules/k8s.ts
+++ b/packages/grid_client/src/modules/k8s.ts
@@ -81,10 +81,11 @@ class K8sModule extends BaseModule {
 
     let deployments: TwinDeployment[] = [];
     let wireguardConfig = "";
-    const metadata = JSON.stringify({
+    const contractMetadata = JSON.stringify({
+      version: 3,
       type: "kubernetes",
       name: options.name,
-      projectName: this.config.projectName,
+      projectName: this.config.projectName || `kubernetes/${options.name}`,
     });
     const masters_names: string[] = [];
     const workers_names: string[] = [];
@@ -109,7 +110,8 @@ class K8sModule extends BaseModule {
         network,
         options.network.myceliumSeeds!,
         options.ssh_key,
-        options.metadata || metadata,
+        contractMetadata,
+        options.metadata,
         options.description,
         master.qsfs_disks,
         this.config.projectName,
@@ -156,7 +158,8 @@ class K8sModule extends BaseModule {
         network,
         options.network.myceliumSeeds!,
         options.ssh_key,
-        options.metadata || metadata,
+        contractMetadata,
+        options.metadata,
         options.description,
         worker.qsfs_disks,
         this.config.projectName,
@@ -280,6 +283,12 @@ class K8sModule extends BaseModule {
     const networkIpRange = Addr(masterWorkload.data["network"].interfaces[0].ip).mask(16).toString();
     const network = new Network(networkName, networkIpRange, this.config);
     await network.load();
+    const contractMetadata = JSON.stringify({
+      version: 3,
+      type: "kubernetes",
+      name: options.deployment_name,
+      projectName: this.config.projectName || `kubernetes/${options.deployment_name}`,
+    });
     const [twinDeployments] = await this.kubernetes.add_worker(
       options.name,
       options.node_id,
@@ -297,6 +306,7 @@ class K8sModule extends BaseModule {
       network,
       [{ nodeId: options.node_id, seed: options.myceliumNetworkSeed! }],
       masterWorkload.data["env"]["SSH_KEY"],
+      contractMetadata,
       masterWorkload.metadata,
       masterWorkload.description,
       options.qsfs_disks,
diff --git a/packages/grid_client/src/modules/machines.ts b/packages/grid_client/src/modules/machines.ts
index 4a02a2390e..1e17d115b3 100644
--- a/packages/grid_client/src/modules/machines.ts
+++ b/packages/grid_client/src/modules/machines.ts
@@ -35,10 +35,11 @@ class MachinesModule extends BaseModule {
 
     let twinDeployments: TwinDeployment[] = [];
     let wireguardConfig = "";
-    const metadata = JSON.stringify({
+    const contractMetadata = JSON.stringify({
+      version: 3,
       type: "vm",
       name: options.name,
-      projectName: this.config.projectName,
+      projectName: this.config.projectName || `vm/${options.name}`,
     });
 
     const machines_names: string[] = [];
@@ -65,7 +66,8 @@ class MachinesModule extends BaseModule {
         options.network.myceliumSeeds!,
         machine.entrypoint,
         machine.env,
-        options.metadata || metadata,
+        contractMetadata,
+        options.metadata,
         options.description,
         machine.qsfs_disks,
         this.config.projectName,
@@ -168,7 +170,12 @@ class MachinesModule extends BaseModule {
     const networkIpRange = Addr(workload.data["network"].interfaces[0].ip).mask(16).toString();
     const network = new Network(networkName, networkIpRange, this.config);
     await network.load();
-
+    const contractMetadata = JSON.stringify({
+      version: 3,
+      type: "vm",
+      name: options.deployment_name,
+      projectName: this.config.projectName || `vm/${options.name}`,
+    });
     const [twinDeployments] = await this.vm.create(
       options.name,
       options.node_id,
@@ -186,6 +193,7 @@ class MachinesModule extends BaseModule {
       [{ nodeId: options.node_id, seed: options.myceliumNetworkSeed! }],
       options.entrypoint,
       options.env,
+      contractMetadata,
       workload.metadata,
       workload.description,
       options.qsfs_disks,
diff --git a/packages/grid_client/src/modules/models.ts b/packages/grid_client/src/modules/models.ts
index f84170e172..7c7d83766a 100644
--- a/packages/grid_client/src/modules/models.ts
+++ b/packages/grid_client/src/modules/models.ts
@@ -182,7 +182,7 @@ class K8SDeleteModel extends BaseGetDeleteModel {}
 
 class AddWorkerModel extends KubernetesNodeModel {
   @Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) deployment_name: string;
-  @Expose() @IsString() @IsOptional() myceliumNetworkSeed: string;
+  @Expose() @IsString() @IsOptional() myceliumNetworkSeed?: string;
 }
 
 class DeleteWorkerModel {
@@ -802,6 +802,7 @@ class NetworkHasNodeModel {
 
 class NetworkGetModel {
   @Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string;
+  @Expose() @IsString() @IsNotEmpty() ipRange: string;
 }
 
 class SetDedicatedNodeExtraFeesModel {
diff --git a/packages/grid_client/src/modules/networks.ts b/packages/grid_client/src/modules/networks.ts
index e1ee8b41ce..e67dc35ad2 100644
--- a/packages/grid_client/src/modules/networks.ts
+++ b/packages/grid_client/src/modules/networks.ts
@@ -48,9 +48,7 @@ class NetworkModule extends BaseModule {
   @expose
   @validateInput
   async getWireGuardConfigs(options: NetworkGetModel) {
-    const path = PATH.join(this.config.storePath, this.moduleName, options.name, "info.json");
-    const networkInfo = await this.backendStorage.load(path);
-    return networkInfo["wireguardConfigs"];
+    return await this.network.getWireguardConfigs(options.name, options.ipRange);
   }
 }
 
diff --git a/packages/grid_client/src/modules/qsfs_zdbs.ts b/packages/grid_client/src/modules/qsfs_zdbs.ts
index 4a1dab5354..7fa228cbdb 100644
--- a/packages/grid_client/src/modules/qsfs_zdbs.ts
+++ b/packages/grid_client/src/modules/qsfs_zdbs.ts
@@ -7,8 +7,8 @@ import { validateInput } from "../helpers/validator";
 import { TwinDeployment } from "../high_level/models";
 import { ZdbHL } from "../high_level/zdb";
 import { ZdbBackend } from "../zos/qsfs";
-import { WorkloadTypes } from "../zos/workload";
-import { ZdbModes } from "../zos/zdb";
+import { Workload, WorkloadTypes } from "../zos/workload";
+import { Zdb, ZdbModes, ZdbResult } from "../zos/zdb";
 import { BaseModule } from "./base";
 import { QSFSZDBDeleteModel, QSFSZDBGetModel, QSFSZDBSModel } from "./models";
 import { checkBalance } from "./utils";
@@ -27,9 +27,10 @@ class QSFSZdbsModule extends BaseModule {
       throw new ValidationError("QSFS zdbs count can't be less than 3.");
     }
     const count = options.count + 4; // 4 zdbs for meta
-    const twinDeployments = [];
-    const metadata = JSON.stringify({
-      type: "QSFS",
+    const twinDeployments: TwinDeployment[] = [];
+    const contractMetadata = JSON.stringify({
+      version: 3,
+      type: "qsfs",
       name: options.name,
       projectName: this.config.projectName,
     });
@@ -47,7 +48,8 @@ class QSFSZdbsModule extends BaseModule {
         mode as ZdbModes,
         options.password,
         true,
-        options.metadata || metadata,
+        contractMetadata,
+        options.metadata,
         options.description,
         options.solutionProviderId,
       );
@@ -91,7 +93,7 @@ class QSFSZdbsModule extends BaseModule {
 
   async getZdbs(name: string) {
     const deployments = await this._get(name);
-    const zdbs = [];
+    const zdbs: Workload[] = [];
     for (const deployment of deployments) {
       for (const workload of deployment.workloads) {
         if (workload.type !== WorkloadTypes.zdb) {
@@ -102,16 +104,18 @@ class QSFSZdbsModule extends BaseModule {
         zdbs.push(workload);
       }
     }
-    const qsfsZdbs = { meta: [], groups: [] };
+    const qsfsZdbs: { meta: ZdbBackend[]; groups: ZdbBackend[] } = { meta: [], groups: [] };
     for (const zdb of zdbs) {
+      const data = zdb.data as Zdb;
+      const result = zdb.result.data as ZdbResult;
       const zdbBackend = new ZdbBackend();
-      zdbBackend.namespace = zdb.result.data.Namespace;
-      zdbBackend.password = zdb.data.password;
-      zdbBackend.address = `[${zdb.result.data.IPs[1]}]:${zdb.result.data.Port}`;
-      zdbBackend["size"] = zdb.data.size;
+      zdbBackend.namespace = result.Namespace;
+      zdbBackend.password = data.password;
+      zdbBackend.address = `[${result.IPs[1]}]:${result.Port}`;
+      zdbBackend["size"] = data.size;
       zdbBackend["contractId"] = zdb["contractId"];
       zdbBackend["nodeId"] = zdb["nodeId"];
-      if (zdb.data.mode === ZdbModes.user) {
+      if (data.mode === ZdbModes.user) {
         qsfsZdbs.meta.push(zdbBackend);
       } else {
         qsfsZdbs.groups.push(zdbBackend);
diff --git a/packages/grid_client/src/modules/zdb.ts b/packages/grid_client/src/modules/zdb.ts
index 260fce306a..24200bf939 100644
--- a/packages/grid_client/src/modules/zdb.ts
+++ b/packages/grid_client/src/modules/zdb.ts
@@ -13,7 +13,7 @@ import { AddZDBModel, DeleteZDBModel, ZDBDeleteModel, ZDBGetModel, ZDBSModel } f
 import { checkBalance } from "./utils";
 
 class ZdbsModule extends BaseModule {
-  fileName = "zdbs.json";
+  moduleName = "zdb";
   workloadTypes = [WorkloadTypes.zdb];
   zdb: ZdbHL;
   constructor(public config: GridClientConfig) {
@@ -24,10 +24,11 @@ class ZdbsModule extends BaseModule {
   async _createDeployment(options: ZDBSModel): Promise<TwinDeployment[]> {
     const twinDeployments: TwinDeployment[] = [];
     const zdbs_names: string[] = [];
-    const metadata = JSON.stringify({
+    const contractMetadata = JSON.stringify({
+      version: 3,
       type: "zdb",
       name: options.name,
-      projectName: this.config.projectName,
+      projectName: this.config.projectName || `zdb/${options.name}`,
     });
     for (const instance of options.zdbs) {
       if (zdbs_names.includes(instance.name))
@@ -41,7 +42,8 @@ class ZdbsModule extends BaseModule {
         instance.mode,
         instance.password,
         instance.publicNamespace,
-        options.metadata || metadata,
+        contractMetadata,
+        options.metadata,
         options.description,
         instance.solutionProviderId,
       );
@@ -133,6 +135,12 @@ class ZdbsModule extends BaseModule {
       throw new ValidationError(
         `There is another zdb with the same name "${options.name}" in this deployment ${options.deployment_name}.`,
       );
+    const contractMetadata = JSON.stringify({
+      version: 3,
+      type: "zdb",
+      name: options.deployment_name,
+      projectName: this.config.projectName || `zdb/${options.name}`,
+    });
     events.emit("logs", `Start adding ZDB instance: ${options.name} to deployment: ${options.deployment_name}`);
     const twinDeployment = await this.zdb.create(
       options.name,
@@ -141,8 +149,9 @@ class ZdbsModule extends BaseModule {
       options.mode,
       options.password,
       options.publicNamespace,
+      contractMetadata,
       oldDeployments[0].metadata,
-      oldDeployments[0].metadata,
+      oldDeployments[0].description,
       options.solutionProviderId,
     );
 
diff --git a/packages/grid_client/src/modules/zos.ts b/packages/grid_client/src/modules/zos.ts
index a9591d61a7..3821ec5935 100644
--- a/packages/grid_client/src/modules/zos.ts
+++ b/packages/grid_client/src/modules/zos.ts
@@ -45,7 +45,7 @@ class Zos {
       }
     }
     console.log(`Deploying on node_id: ${node_id} with number of public IPs: ${publicIps}`);
-    const twinDeployment = new TwinDeployment(deployment, Operations.deploy, publicIps, node_id);
+    const twinDeployment = new TwinDeployment(deployment, Operations.deploy, publicIps, node_id, deployment.metadata);
     const twinDeploymentHandler = new TwinDeploymentHandler(this.config);
     return await twinDeploymentHandler.handle([twinDeployment]);
   }
diff --git a/packages/grid_client/src/primitives/network.ts b/packages/grid_client/src/primitives/network.ts
index ae258e60d3..20d4f97737 100644
--- a/packages/grid_client/src/primitives/network.ts
+++ b/packages/grid_client/src/primitives/network.ts
@@ -8,6 +8,7 @@ import { default as TweetNACL } from "tweetnacl";
 
 import { RMB } from "../clients/rmb/client";
 import { TFClient } from "../clients/tf-grid/client";
+import { GqlNodeContract } from "../clients/tf-grid/contracts";
 import { GridClientConfig } from "../config";
 import { events } from "../helpers/events";
 import { formatErrorMessage, generateRandomHexSeed, getRandomNumber, randomChoice } from "../helpers/utils";
@@ -15,6 +16,7 @@ import { validateHexSeed } from "../helpers/validator";
 import { MyceliumNetworkModel } from "../modules";
 import { DeploymentFactory } from "../primitives/deployment";
 import { BackendStorage, BackendStorageType } from "../storage/backend";
+import { Zmachine } from "../zos";
 import { Deployment } from "../zos/deployment";
 import { Workload, WorkloadTypes } from "../zos/workload";
 import { Peer, Znet } from "../zos/znet";
@@ -37,13 +39,26 @@ class AccessPoint {
   node_id: number;
 }
 
+export interface UserAccess {
+  subnet: string;
+  private_key: string;
+  node_id: number;
+}
+
+interface NetworkMetadata {
+  version: number;
+  user_accesses: UserAccess[];
+}
+
 class Network {
   capacity: Nodes;
   nodes: Node[] = [];
   deployments: Deployment[] = [];
   reservedSubnets: string[] = [];
   networks: Znet[] = [];
+  contracts: Required<GqlNodeContract>[];
   accessPoints: AccessPoint[] = [];
+  userAccesses: UserAccess[] = [];
   backendStorage: BackendStorage;
   _endpoints: Record<string, string> = {};
   _accessNodes: number[] = [];
@@ -82,31 +97,54 @@ class Network {
     }
   }
 
-  async addAccess(node_id: number, ipv4: boolean): Promise<string> {
-    if (!this.nodeExists(node_id)) {
-      throw new ValidationError(`Node ${node_id} does not exist in the network. Please add it first.`);
+  private getUpdatedMetadata(nodeId: number, metadata: string): string {
+    for (const node of this.nodes) {
+      if (node.node_id === nodeId) {
+        const parsedMetadata: NetworkMetadata = JSON.parse(metadata || "{}");
+        parsedMetadata.version = 3;
+        parsedMetadata.user_accesses = this.userAccesses;
+        return JSON.stringify(parsedMetadata);
+      }
     }
-    events.emit("logs", `Adding access to node ${node_id}`);
+    return metadata;
+  }
+
+  updateWorkload(nodeId: number, workload: Workload): Workload {
+    workload.data = this.getUpdatedNetwork(workload.data);
+    workload.metadata = this.getUpdatedMetadata(nodeId, workload.metadata);
+    return workload;
+  }
+
+  async getAccessNodeEndpoint(nodeId: number, ipv4 = true): Promise<string> {
     const accessNodes = await this.capacity.getAccessNodes(this.config.twinId);
-    if (Object.keys(accessNodes).includes(node_id.toString())) {
-      if (ipv4 && !accessNodes[node_id]["ipv4"]) {
-        throw new GridClientErrors.Nodes.InvalidResourcesError(`Node ${node_id} does not have ipv4 public config.`);
+    if (Object.keys(accessNodes).includes(nodeId.toString())) {
+      if (ipv4 && !accessNodes[nodeId]["ipv4"]) {
+        throw new GridClientErrors.Nodes.InvalidResourcesError(`Node ${nodeId} does not have ipv4 public config.`);
       }
     } else {
-      throw new GridClientErrors.Nodes.AccessNodeError(`Node ${node_id} is not an access node.`);
+      throw new GridClientErrors.Nodes.AccessNodeError(`Node ${nodeId} is not an access node.`);
     }
 
-    const nodeWGListeningPort = this.getNodeWGListeningPort(node_id);
+    const nodeWGListeningPort = this.getNodeWGListeningPort(nodeId);
     let endpoint = "";
-    if (accessNodes[node_id]["ipv4"]) {
-      endpoint = `${accessNodes[node_id]["ipv4"].split("/")[0]}:${nodeWGListeningPort}`;
-    } else if (accessNodes[node_id]["ipv6"]) {
-      endpoint = `[${accessNodes[node_id]["ipv6"].split("/")[0]}]:${nodeWGListeningPort}`;
+    if (accessNodes[nodeId]["ipv4"]) {
+      endpoint = `${accessNodes[nodeId]["ipv4"].split("/")[0]}:${nodeWGListeningPort}`;
+    } else if (accessNodes[nodeId]["ipv6"]) {
+      endpoint = `[${accessNodes[nodeId]["ipv6"].split("/")[0]}]:${nodeWGListeningPort}`;
     } else {
       throw new GridClientErrors.Nodes.InvalidResourcesError(
-        `Couldn't find ipv4 or ipv6 in the public config of node ${node_id}.`,
+        `Couldn't find ipv4 or ipv6 in the public config of node ${nodeId}.`,
       );
     }
+    return endpoint;
+  }
+
+  async addAccess(node_id: number, ipv4: boolean): Promise<string> {
+    if (!this.nodeExists(node_id)) {
+      throw new ValidationError(`Node ${node_id} does not exist in the network. Please add it first.`);
+    }
+    events.emit("logs", `Adding access to node ${node_id}`);
+    const endpoint = await this.getAccessNodeEndpoint(node_id, ipv4);
 
     const nodesWGPubkey = await this.getNodeWGPublicKey(node_id);
     const keypair = this.generateWireguardKeypair();
@@ -118,6 +156,11 @@ class Network {
     this.accessPoints.push(accessPoint);
     await this.generatePeers();
     this.updateNetworkDeployments();
+    this.userAccesses.push({
+      node_id,
+      private_key: keypair.privateKey,
+      subnet: accessPoint.subnet,
+    });
     this.wireguardConfig = this.getWireguardConfig(accessPoint.subnet, keypair.privateKey, nodesWGPubkey, endpoint);
     return this.wireguardConfig;
   }
@@ -147,7 +190,7 @@ class Network {
           hex_key: seed,
           peers: [],
         };
-        this.updateNetwork(network);
+        this.getUpdatedNetwork(network);
         this.updateNetworkDeployments();
 
         const deploymentFactory = new DeploymentFactory(this.config);
@@ -157,7 +200,7 @@ class Network {
           const d = await deploymentFactory.fromObj(deployment);
           for (const workload of d["workloads"]) {
             workload.data["mycelium"]["hex_key"] = seed;
-            workload.data = this.updateNetwork(workload["data"]);
+            workload.data = this.getUpdatedNetwork(workload["data"]);
             workload.version += 1;
           }
           return d;
@@ -169,7 +212,6 @@ class Network {
   async addNode(
     nodeId: number,
     mycelium: boolean,
-    metadata = "",
     description = "",
     subnet = "",
     myceliumSeeds: MyceliumNetworkModel[] = [],
@@ -208,14 +250,14 @@ class Network {
     this.networks.push(znet);
     await this.generatePeers();
     this.updateNetworkDeployments();
-    znet = this.updateNetwork(znet);
+    znet = this.getUpdatedNetwork(znet);
 
     const znet_workload = new Workload();
     znet_workload.version = 0;
     znet_workload.name = this.name;
     znet_workload.type = WorkloadTypes.network;
     znet_workload.data = znet;
-    znet_workload.metadata = metadata;
+    znet_workload.metadata = "";
     znet_workload.description = description;
 
     const node = new Node();
@@ -247,7 +289,7 @@ class Network {
     return contract_id;
   }
 
-  updateNetwork(znet): Znet {
+  getUpdatedNetwork(znet): Znet {
     for (const net of this.networks) {
       if (net.subnet === znet.subnet) {
         return net;
@@ -279,47 +321,95 @@ class Network {
       return;
     }
     events.emit("logs", `Loading network ${this.name}`);
-    const network = await this.getNetwork();
-    if (network["ip_range"] !== this.ipRange) {
-      throw new ValidationError(`The same network name ${this.name} with a different ip range already exists.`);
+
+    if (await this.existOnNewNetwork()) {
+      await this.loadNetworkFromContracts();
+    } else {
+      const network = await this.getNetwork();
+      if (network["ip_range"] !== this.ipRange) {
+        throw new ValidationError(`The same network name ${this.name} with a different ip range already exists.`);
+      }
+
+      await this.tfClient.connect();
+      for (const node of network["nodes"]) {
+        const contract = await this.tfClient.contracts.get({
+          id: node.contract_id,
+        });
+        if (contract === null) continue;
+        const node_twin_id = await this.capacity.getNodeTwinId(node.node_id);
+        const payload = JSON.stringify({ contract_id: node.contract_id });
+        let res;
+        try {
+          res = await this.rmb.request([node_twin_id], "zos.deployment.get", payload);
+        } catch (e) {
+          (e as Error).message = formatErrorMessage(`Failed to load network deployment ${node.contract_id}`, e);
+          throw e;
+        }
+        res["node_id"] = node.node_id;
+        for (const workload of res["workloads"]) {
+          if (
+            workload["type"] !== WorkloadTypes.network ||
+            !Addr(this.ipRange).contains(Addr(workload["data"]["subnet"]))
+          ) {
+            continue;
+          }
+          if (workload.result.state === "deleted") {
+            continue;
+          }
+          const znet = this._fromObj(workload["data"]);
+          znet["node_id"] = node.node_id;
+          const n: Node = node;
+          this.nodes.push(n);
+          this.networks.push(znet);
+          this.deployments.push(res);
+        }
+      }
+      await this.getAccessPoints();
+      await this.save();
     }
+  }
 
-    await this.tfClient.connect();
-    for (const node of network["nodes"]) {
-      const contract = await this.tfClient.contracts.get({
-        id: node.contract_id,
-      });
-      if (contract === null) continue;
-      const node_twin_id = await this.capacity.getNodeTwinId(node.node_id);
-      const payload = JSON.stringify({ contract_id: node.contract_id });
-      let res;
+  private async loadNetworkFromContracts() {
+    const contracts = await this.getDeploymentContracts(this.name);
+    for (const contract of contracts) {
+      const node_twin_id = await this.capacity.getNodeTwinId(contract.nodeID);
+      const payload = JSON.stringify({ contract_id: +contract.contractID });
+      let res: Deployment;
       try {
         res = await this.rmb.request([node_twin_id], "zos.deployment.get", payload);
       } catch (e) {
-        (e as Error).message = formatErrorMessage(`Failed to load network deployment ${node.contract_id}`, e);
+        (e as Error).message = formatErrorMessage(`Failed to load network deployment ${contract.contractID}`, e);
         throw e;
       }
-      res["node_id"] = node.node_id;
-      for (const workload of res["workloads"]) {
-        if (
-          workload["type"] !== WorkloadTypes.network ||
-          !Addr(this.ipRange).contains(Addr(workload["data"]["subnet"]))
-        ) {
+      res["node_id"] = contract.nodeID;
+      for (const workload of res.workloads) {
+        const data = workload.data as Znet;
+        if (workload.type !== WorkloadTypes.network || workload.name !== this.name) {
           continue;
         }
         if (workload.result.state === "deleted") {
           continue;
         }
-        const znet = this._fromObj(workload["data"]);
-        znet["node_id"] = node.node_id;
-        const n: Node = node;
+        const znet = this._fromObj(data);
+        znet["node_id"] = contract.nodeID;
+        const parsedMetadata: NetworkMetadata = JSON.parse(workload.metadata);
+        const reservedIps = await this.getReservedIps(contract.nodeID);
+
+        if (znet.ip_range !== this.ipRange) {
+          throw new ValidationError(`The same network name ${this.name} with a different ip range already exists.`);
+        }
+        this.userAccesses = parsedMetadata.user_accesses;
+        const n: Node = {
+          contract_id: +contract.contractID,
+          node_id: contract.nodeID,
+          reserved_ips: reservedIps,
+        };
         this.nodes.push(n);
         this.networks.push(znet);
         this.deployments.push(res);
       }
     }
     await this.getAccessPoints();
-    await this.save();
   }
 
   _fromObj(net: Znet): Znet {
@@ -537,9 +627,63 @@ class Network {
     return await this.backendStorage.load(PATH.join(path, this.name, "info.json"));
   }
 
+  private async getMyNetworkContracts(fetch = false) {
+    if (fetch || !this.contracts) {
+      const contracts = await this.tfClient.contracts.listMyNodeContracts({
+        graphqlURL: this.config.graphqlURL,
+        type: "network",
+      });
+
+      const parsedContracts: Required<GqlNodeContract>[] = [];
+
+      for (const contract of contracts) {
+        const parsedDeploymentData = JSON.parse(contract.deploymentData);
+        parsedContracts.push({ ...contract, parsedDeploymentData });
+      }
+
+      this.contracts = parsedContracts;
+    }
+
+    return this.contracts;
+  }
+
+  private async getReservedIps(nodeId: number): Promise<string[]> {
+    const node_twin_id = await this.capacity.getNodeTwinId(nodeId);
+    const payload = JSON.stringify({ network_name: this.name });
+    let reservedIps: string[];
+    try {
+      reservedIps = await this.rmb.request([node_twin_id], "zos.network.list_private_ips", payload);
+    } catch (e) {
+      (e as Error).message = formatErrorMessage(`Failed to list reserved ips from node ${nodeId}`, e);
+      throw e;
+    }
+    return reservedIps;
+  }
+
+  private async getDeploymentContracts(name: string) {
+    const contracts = await this.getMyNetworkContracts();
+    return contracts.filter(c => c.parsedDeploymentData.name === name);
+  }
+
+  private getContractsName(contracts: Required<GqlNodeContract>[]): string[] {
+    return Array.from(new Set(contracts.map(c => c.parsedDeploymentData.name)));
+  }
+
+  private async listNewNetworks() {
+    const contracts = await this.getMyNetworkContracts(true);
+    return this.getContractsName(contracts);
+  }
+
+  private async existOnNewNetwork() {
+    return (await this.listNewNetworks()).includes(this.name);
+  }
+
   async getNetworkNames(): Promise<string[]> {
+    const newNames = await this.listNewNetworks();
+
     const path = this.getNetworksPath();
-    return await this.backendStorage.list(path);
+    const oldNames = await this.backendStorage.list(path);
+    return Array.from(new Set([...newNames, ...oldNames]));
   }
 
   async getFreePort(node_id: number): Promise<number> {
@@ -628,56 +772,11 @@ AllowedIPs = ${this.ipRange}, ${networkIP}
 PersistentKeepalive = 25\nEndpoint = ${endpoint}`;
   }
 
-  async save(contract_id = 0, node_id = 0) {
-    let network;
-    if (await this.exists()) {
-      network = await this.getNetwork();
-    } else {
-      network = {
-        ip_range: this.ipRange,
-        nodes: [],
-        wireguardConfigs: [],
-      };
-    }
-
-    if (this.wireguardConfig && !network.wireguardConfigs.includes(this.wireguardConfig)) {
-      network.wireguardConfigs.push(this.wireguardConfig);
-    }
-
+  async save() {
     if (this.nodes.length === 0) {
       await this.delete();
       return;
     }
-
-    const nodes = [];
-    for (const node of this.nodes) {
-      if (!node.contract_id && node.node_id === node_id) {
-        node.contract_id = contract_id;
-      }
-      if (!node.contract_id) {
-        continue;
-      }
-      nodes.push({
-        contract_id: node.contract_id,
-        node_id: node.node_id,
-        reserved_ips: this.getNodeReservedIps(node.node_id),
-      });
-    }
-    network.nodes = nodes;
-    if (nodes.length !== 0) {
-      await this._save(network);
-    } else {
-      await this.delete();
-    }
-  }
-
-  async _save(network): Promise<void> {
-    const path = PATH.join(this.getNetworksPath(), this.name, "info.json");
-    const current = await this.backendStorage.load(path);
-    if (JSON.stringify(current) !== JSON.stringify(network)) {
-      const updateOperations = await this.backendStorage.dump(path, network);
-      await this.saveIfKVStoreBackend(updateOperations);
-    }
   }
 
   async delete(): Promise<void> {
diff --git a/packages/playground/src/components/icon_action_btn.vue b/packages/playground/src/components/icon_action_btn.vue
index 857bf748c8..e5b5cd25f9 100644
--- a/packages/playground/src/components/icon_action_btn.vue
+++ b/packages/playground/src/components/icon_action_btn.vue
@@ -10,6 +10,7 @@
         variant="tonal"
         :height="height"
         class="my-1 mr-1"
+        :disabled="disabled"
       >
         <v-icon> {{ icon }}</v-icon>
       </v-btn>
@@ -24,6 +25,7 @@ defineProps<{
   color?: string;
   href?: string;
   height?: string;
+  disabled?: boolean;
 }>();
 defineEmits(["click"]);
 </script>
diff --git a/packages/playground/src/components/k8s_deployment_table.vue b/packages/playground/src/components/k8s_deployment_table.vue
index a0b644f278..53443644c1 100644
--- a/packages/playground/src/components/k8s_deployment_table.vue
+++ b/packages/playground/src/components/k8s_deployment_table.vue
@@ -44,8 +44,8 @@
               }}
               <template v-if="deployment.contracts && deployment.contracts.length > 0">
                 with contract id:
-                <span v-for="contract in deployment.contracts" :key="contract.contract_id">
-                  {{ contract.contract_id }} .
+                <span v-for="contract in deployment.contracts" :key="contract.contractID">
+                  {{ contract.contractID }} .
                 </span>
               </template>
             </li>
@@ -59,6 +59,10 @@
 
     <AccessDeploymentAlert />
 
+    <InputTooltip tooltip="List all deployments, including those created outside the Dashboard." inline>
+      <VSwitch inset color="primary" label="Show All Deployments" v-model="showAllDeployments" />
+    </InputTooltip>
+
     <ListTable
       :headers="[
         { title: 'PLACEHOLDER', key: 'data-table-select' },
@@ -72,7 +76,7 @@
         { title: 'Health', key: 'status', sortable: false },
         { title: 'Actions', key: 'actions', sortable: false },
       ]"
-      :items="items"
+      :items="showAllDeployments ? items : items.filter(i => !i.fromAnotherClient)"
       :loading="loading"
       :deleting="deleting"
       :model-value="$props.modelValue"
@@ -128,10 +132,12 @@ import { getNodeHealthColor, NodeHealth } from "@/utils/get_nodes";
 
 import { useProfileManager } from "../stores";
 import { getGrid, updateGrid } from "../utils/grid";
+import { markAsFromAnotherClient } from "../utils/helpers";
 import { loadK8s, mergeLoadedDeployments } from "../utils/load_deployment";
 const profileManager = useProfileManager();
 const showDialog = ref(false);
 const showEncryption = ref(false);
+const showAllDeployments = ref(false);
 const failedDeployments = ref<any[]>([]);
 
 const props = defineProps<{
@@ -144,7 +150,6 @@ defineEmits<{ (event: "update:model-value", value: any[]): void }>();
 const count = ref<number>();
 const items = ref<any[]>([]);
 const loading = ref(false);
-const namesOfFailedDeployments = ref("");
 
 onMounted(loadDeployments);
 async function loadDeployments() {
@@ -155,6 +160,10 @@ async function loadDeployments() {
   const chunk2 = await loadK8s(updateGrid(grid!, { projectName: props.projectName.toLowerCase() }));
   const chunk3 = await loadK8s(updateGrid(grid!, { projectName: "" }));
 
+  chunk3.items = chunk3.items.map(i => {
+    return !i.projectName || i.projectName === "Kubernetes" ? markAsFromAnotherClient(i) : i;
+  });
+
   const clusters = mergeLoadedDeployments(chunk1, chunk2, chunk3);
   failedDeployments.value = [
     ...(Array.isArray((chunk1 as any).failedDeployments) ? (chunk1 as any).failedDeployments : []),
diff --git a/packages/playground/src/components/vm_deployment_table.vue b/packages/playground/src/components/vm_deployment_table.vue
index 09c214faeb..f68c27d16b 100644
--- a/packages/playground/src/components/vm_deployment_table.vue
+++ b/packages/playground/src/components/vm_deployment_table.vue
@@ -48,9 +48,17 @@
 
     <AccessDeploymentAlert />
 
+    <InputTooltip
+      v-if="props.projectName.toLowerCase() === 'vm'"
+      tooltip="List all deployments, including those created outside the Dashboard."
+      inline
+    >
+      <VSwitch inset color="primary" label="Show All Deployments" v-model="showAllDeployments" />
+    </InputTooltip>
+
     <ListTable
       :headers="filteredHeaders"
-      :items="items"
+      :items="showAllDeployments ? items : items.filter(i => !i.fromAnotherClient)"
       :loading="loading"
       :deleting="deleting"
       :model-value="$props.modelValue"
@@ -75,7 +83,7 @@
       </template>
 
       <template #[`item.wireguard`]="{ item }">
-        {{ item.value.interfaces[0].ip || "-" }}
+        {{ item.value.interfaces?.[0]?.ip || "-" }}
       </template>
 
       <template #[`item.flist`]="{ item }">
@@ -139,6 +147,7 @@ import { getNodeHealthColor, NodeHealth } from "@/utils/get_nodes";
 
 import { useProfileManager } from "../stores";
 import { getGrid, updateGrid } from "../utils/grid";
+import { markAsFromAnotherClient } from "../utils/helpers";
 import { loadVms, mergeLoadedDeployments } from "../utils/load_deployment";
 
 const profileManager = useProfileManager();
@@ -155,11 +164,12 @@ const count = ref<number>();
 const items = ref<any[]>([]);
 const showDialog = ref(false);
 const showEncryption = ref(false);
+const showAllDeployments = ref(false);
 const failedDeployments = ref<
   {
     name: string;
     nodes?: number[];
-    contracts?: { contract_id: number; node_id: number }[];
+    contracts?: { contractID: number; node_id: number }[];
   }[]
 >([]);
 
@@ -181,19 +191,17 @@ async function loadDeployments() {
     await migrateModule(grid!.gateway);
   }
 
-  const filter =
+  const chunk3 =
     props.projectName.toLowerCase() === ProjectName.VM.toLowerCase()
-      ? undefined
-      : ([vm]: [{ flist: string }]) => vm.flist.replace(/-/g, "").includes(props.projectName.toLowerCase());
+      ? await loadVms(updateGrid(grid!, { projectName: "" }))
+      : { count: 0, items: [] };
 
-  const chunk3 =
-    props.projectName.toLowerCase() === ProjectName.Fullvm.toLowerCase()
-      ? { count: 0, items: [] }
-      : await loadVms(updateGrid(grid!, { projectName: "" }), { filter });
   if (chunk3.count > 0 && migrateGateways) {
     await migrateModule(grid!.gateway);
   }
 
+  chunk3.items = chunk3.items.map(markAsFromAnotherClient);
+
   const vms = mergeLoadedDeployments(chunk1, chunk2, chunk3 as any);
   failedDeployments.value = [
     ...(Array.isArray((chunk1 as any).failedDeployments) ? (chunk1 as any).failedDeployments : []),
@@ -272,7 +280,7 @@ const failedDeploymentList = computed(() => {
       const contractMessage =
         contracts.length > 0
           ? ` <span class="ml-4 text-primary font-weight-bold">With Contract ID:</span> ${contracts
-              .map(c => c.contract_id)
+              .map(c => c.contractID)
               .join(", ")}.`
           : "";
 
diff --git a/packages/playground/src/utils/deploy_k8s.ts b/packages/playground/src/utils/deploy_k8s.ts
index a18dc941c4..1f47a4d1ea 100644
--- a/packages/playground/src/utils/deploy_k8s.ts
+++ b/packages/playground/src/utils/deploy_k8s.ts
@@ -28,7 +28,7 @@ export async function deployK8s(grid: GridClient, options: DeployK8SOptions) {
   k8s.ssh_key = options.sshKey;
   await grid.k8s.deploy(k8s);
   const data = (await loadK8S(grid, k8s.name)) as { masters: any[]; workers: any[]; wireguard?: string };
-  const wireguard = await getWireguardConfig(grid, k8s.network.name).catch(() => []);
+  const wireguard = await getWireguardConfig(grid, k8s.network.name, k8s.network.ip_range).catch(() => []);
   data.wireguard = wireguard[0];
   return data;
 }
diff --git a/packages/playground/src/utils/deploy_vm.ts b/packages/playground/src/utils/deploy_vm.ts
index 8f48651376..03ec474b25 100644
--- a/packages/playground/src/utils/deploy_vm.ts
+++ b/packages/playground/src/utils/deploy_vm.ts
@@ -30,7 +30,7 @@ export async function loadVM(grid: GridClient, name: string) {
   const vm = (await grid.machines.getObj(name)) as any;
   vm.deploymentName = name;
   vm.projectName = grid.clientOptions.projectName;
-  const wireguard = await getWireguardConfig(grid, vm[0].interfaces[0].network).catch(() => []);
+  const wireguard = await getWireguardConfig(grid, vm[0].interfaces[0].network, vm[0].interfaces[0].ip).catch(() => []);
   vm.wireguard = wireguard[0];
   return vm;
 }
diff --git a/packages/playground/src/utils/helpers.ts b/packages/playground/src/utils/helpers.ts
index 367388570d..b44d036627 100644
--- a/packages/playground/src/utils/helpers.ts
+++ b/packages/playground/src/utils/helpers.ts
@@ -75,3 +75,14 @@ export function toGigaBytes(value?: number) {
   const gb = value / giga;
   return parseFloat(gb.toFixed(2));
 }
+
+export function markAsFromAnotherClient(deployment: any): any {
+  deployment.fromAnotherClient = true;
+  if (Array.isArray(deployment)) {
+    deployment.map(t => {
+      t.fromAnotherClient = true;
+      return t;
+    });
+  }
+  return deployment;
+}
diff --git a/packages/playground/src/utils/load_deployment.ts b/packages/playground/src/utils/load_deployment.ts
index c0d53369df..5a5b157a07 100644
--- a/packages/playground/src/utils/load_deployment.ts
+++ b/packages/playground/src/utils/load_deployment.ts
@@ -61,7 +61,13 @@ export async function loadVms(grid: GridClient, options: LoadVMsOptions = {}) {
       return;
     }
 
-    const machinePromise = grids[index].machines.getObj(name);
+    const machinePromise = grids[index].machines.getObj(name).then(res => {
+      if (!projectName && (!Array.isArray(res) || res.length === 0)) {
+        grids[index] = updateGrid(grids[index], { projectName: "" });
+        return grids[index].machines.getObj(name);
+      }
+      return res;
+    });
     const timeoutPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         reject(new Error("Timeout"));
@@ -117,7 +123,9 @@ export async function loadVms(grid: GridClient, options: LoadVMsOptions = {}) {
     }),
   );
   const wireguards = await Promise.all(
-    vms.map((vm, index) => getWireguardConfig(grids[index], vm[0].interfaces[0].network).catch(() => [])),
+    vms.map((vm, index) =>
+      getWireguardConfig(grids[index], vm[0].interfaces[0].network, vm[0].interfaces[0].ip).catch(() => []),
+    ),
   );
 
   const data = vms.map((vm, index) => {
@@ -135,10 +143,15 @@ export async function loadVms(grid: GridClient, options: LoadVMsOptions = {}) {
     failedDeployments,
   };
 }
-export function getWireguardConfig(grid: GridClient, name: string) {
+export function getWireguardConfig(grid: GridClient, name: string, ipRange: string) {
   const projectName = grid.clientOptions!.projectName;
+  if (!ipRange.endsWith("/16")) {
+    const parts = ipRange.split(".");
+    parts[2] = parts[3] = "0";
+    ipRange = parts.join(".") + "/16";
+  }
   return updateGrid(grid, { projectName: "" })
-    .networks.getWireGuardConfigs({ name })
+    .networks.getWireGuardConfigs({ name, ipRange })
     .finally(() => updateGrid(grid, { projectName }));
 }
 
@@ -151,7 +164,7 @@ export async function loadK8s(grid: GridClient) {
 
   const projectName = grid.clientOptions.projectName;
   const grids = (await Promise.all(
-    clusters.map(n => getGrid(grid.clientOptions, `${projectName}/${n}`)),
+    clusters.map(n => getGrid(grid.clientOptions, projectName ? `${projectName}/${n}` : n)),
   )) as GridClient[];
   const failedDeployments: FailedDeployment[] = [];
 
@@ -168,7 +181,14 @@ export async function loadK8s(grid: GridClient) {
     }
 
     try {
-      const clusterPromise = grids[index].k8s.getObj(name);
+      const clusterPromise = grids[index].k8s.getObj(name).then(res => {
+        if (!projectName && res && res.masters && res.masters.length === 0) {
+          grids[index] = updateGrid(grids[index], { projectName: "" });
+          return grids[index].k8s.getObj(name);
+        }
+
+        return res;
+      });
       const timeoutPromise = new Promise((resolve, reject) => {
         setTimeout(() => {
           reject(new Error("Timeout"));
@@ -211,7 +231,11 @@ export async function loadK8s(grid: GridClient) {
 
   const wireguards = await Promise.all(
     k8s.map((cluster, index) =>
-      getWireguardConfig(grids[index], cluster.masters[0].interfaces[0].network).catch(() => []),
+      getWireguardConfig(
+        grids[index],
+        cluster.masters[0].interfaces[0].network,
+        cluster.masters[0].interfaces[0].ip,
+      ).catch(() => []),
     ),
   );
   const data = k8s.map((cluster, index) => {
@@ -233,10 +257,24 @@ export async function loadK8s(grid: GridClient) {
 export function mergeLoadedDeployments<T>(...deployments: LoadedDeployments<T>[]) {
   return deployments.reduce(
     (res, current) => {
-      res.count += current.count;
-      res.items = res.items.concat(current.items);
+      insertIfNotFound(current, res);
+      res.count = res.items.length;
       return res;
     },
     { count: 0, items: [] },
   );
 }
+
+function insertIfNotFound(newItems: LoadedDeployments<any>, oldItems: LoadedDeployments<any>) {
+  for (const item of newItems.items) {
+    let found = false;
+    for (const i of oldItems.items) {
+      if (item.deploymentName === i.deploymentName) {
+        found = true;
+      }
+    }
+    if (!found) {
+      oldItems.items.push(item);
+    }
+  }
+}
diff --git a/packages/playground/src/utils/nodeSelector.ts b/packages/playground/src/utils/nodeSelector.ts
index ebb9f2343f..c91eecff4f 100644
--- a/packages/playground/src/utils/nodeSelector.ts
+++ b/packages/playground/src/utils/nodeSelector.ts
@@ -162,7 +162,7 @@ export function normalizeNodeOptions(
     size: window.env.PAGE_SIZE,
     page: pagination.value.page,
     location: location || {},
-    twinId: gridStore.client.twinId,
+    twinId: gridStore.client?.twinId,
     farm,
   };
 }
diff --git a/packages/playground/src/weblets/tf_deployment_list.vue b/packages/playground/src/weblets/tf_deployment_list.vue
index 5dcde95dd8..cbb7c51eb3 100644
--- a/packages/playground/src/weblets/tf_deployment_list.vue
+++ b/packages/playground/src/weblets/tf_deployment_list.vue
@@ -42,7 +42,12 @@
             @click="openDialog(tabs[activeTab].value, item)"
           />
 
-          <IconActionBtn icon="mdi-cog" tooltip="Manage Domains" @click="dialog = item.value.deploymentName" />
+          <IconActionBtn
+            icon="mdi-cog"
+            tooltip="Manage Domains"
+            :disabled="item.value.fromAnotherClient"
+            @click="dialog = item.value.deploymentName"
+          />
 
           <ManageGatewayDialog
             v-if="dialog === item.value.deploymentName"
@@ -306,7 +311,13 @@
               icon="mdi-eye-outline"
               @click="openDialog(tabs[activeTab].value, item)"
             />
-            <IconActionBtn icon="mdi-cog" tooltip="Manage Workers" @click="dialog = item.value.deploymentName" />
+
+            <IconActionBtn
+              icon="mdi-cog"
+              :disabled="item.value.fromAnotherClient"
+              tooltip="Manage Workers"
+              @click="dialog = item.value.deploymentName"
+            />
 
             <ManageK8SWorkerDialog
               v-if="dialog === item.value.deploymentName"
diff --git a/packages/playground/src/weblets/tf_kubernetes.vue b/packages/playground/src/weblets/tf_kubernetes.vue
index b3cf24d186..a9286ec2bd 100644
--- a/packages/playground/src/weblets/tf_kubernetes.vue
+++ b/packages/playground/src/weblets/tf_kubernetes.vue
@@ -86,6 +86,7 @@ import { createWorker } from "../components/k8s_worker.vue";
 import { useLayout } from "../components/weblet_layout.vue";
 import { useProfileManager } from "../stores";
 import type { K8SWorker as K8sWorker } from "../types";
+import { ProjectName } from "../types";
 import { deployK8s } from "../utils/deploy_k8s";
 import { getGrid } from "../utils/grid";
 import { generateName, generatePassword } from "../utils/strings";
@@ -107,7 +108,8 @@ async function deploy() {
 
   try {
     layout.value?.validateSSH();
-    const grid = await getGrid(profileManager.profile!, name.value);
+    const projectName = ProjectName.Kubernetes.toLowerCase() + "/" + name.value;
+    const grid = await getGrid(profileManager.profile!, projectName);
 
     await layout.value.validateBalance(grid!);
 
diff --git a/packages/weblets/src/utils/getWireguardConfig.ts b/packages/weblets/src/utils/getWireguardConfig.ts
index 7170fe91be..6e5aeaf03d 100644
--- a/packages/weblets/src/utils/getWireguardConfig.ts
+++ b/packages/weblets/src/utils/getWireguardConfig.ts
@@ -9,8 +9,11 @@ export default async function getWireguardConfig(network: NetworkGetModel) {
     const profile = get(window.configs.baseConfig);
     if (!profile) return;
     const client = await getGrid(profile as unknown as IProfile, c => c, "");
+    const parts = network.ipRange.split(".");
+    parts[2] = parts[3] = "0";
+    network.ipRange = parts.join(".") + "/16";
 
-    const wireguard = await client.networks.getWireGuardConfigs({ name: network.name });
+    const wireguard = await client.networks.getWireGuardConfigs({ name: network.name, ipRange: network.ipRange });
     return wireguard;
   } catch (error) {
     console.log("error", error);